Last week, I shipped something that's been brewing in my mind for months: RaftStack, an NPM CLI tool that standardizes how we initialize and maintain TypeScript projects at RaftLabs. What started as an idea to improve our development workflow turned into a full development framework that's now adopted by all 30+ engineers in our organization.
Here's the story of why I built it, what problems it solves, and how 20 seconds of setup time now saves us days of repetitive work.
Why RaftLabs Encouraged This
One thing I love about working at RaftLabs is the culture of continuous improvement. When I pitched the idea of building internal tooling to standardize our workflows, leadership didn't just approve it—they gave me a full week to focus on nothing else. That kind of investment in developer experience is rare, and it's why projects like RaftStack can go from idea to organization-wide adoption so quickly.
RaftLabs has always delivered quality products to clients. But as we scaled from a small team to 30+ engineers, we recognized an opportunity: what if we could make excellence the default rather than something each team had to figure out independently?
The Challenge: Scaling Engineering Excellence
RaftLabs is a service-based company that builds products for clients—sometimes MVPs that ship in a month, sometimes enterprise projects that span six months or more. We're proud of the diverse, challenging work we take on. At any given time, multiple projects run in parallel, each with its own technical requirements and timelines.
As we grew, we noticed a pattern common to many scaling engineering teams: without explicit standards, each project evolved its own conventions.
Repository Drift
Different projects had developed different practices. One used 4-space indentation, another used 2. Some had strict TypeScript configurations, others were more relaxed. Commit messages varied from beautifully formatted Conventional Commits to quick notes during crunch time.
Some projects had well-organized Git hooks that validated commits and ran linting. Others—especially older ones or quick prototypes—didn't have these guardrails yet. None of this was due to lack of skill; our engineers are excellent. It was simply a coordination problem that every growing team faces.
The AI Tooling Opportunity
Here's an industry-wide observation: AI-assisted coding tools dramatically increase development speed, but they also amplify whatever patterns exist in your codebase—good or bad. Across the industry, teams have noticed that without guardrails, AI-generated code can lead to:
- Larger files that could benefit from better separation of concerns
- Relaxed type safety when strict typing would catch bugs earlier
- Bigger pull requests that take longer to review thoroughly
This isn't a criticism of AI tools—we love them and use them daily. It's recognition that any tool that increases output velocity needs corresponding quality gates. The faster you can write code, the more important it becomes to have automated checks ensuring that code meets your standards.
The Setup Time Sink
The most tangible problem was project initialization. Our engineers—skilled as they are—were spending valuable time on repetitive setup work:
- Initialize a repo (Turborepo, NX, or similar)
- Search through previous projects for proven configurations
- Copy and adapt Husky hooks, Prettier config, ESLint rules
- Debug integration issues when configs from different sources clashed
- Document the setup for the team
This process could take 2-3 days of an engineer's time—time better spent solving actual client problems.
We had talented people doing repetitive work. That's the kind of inefficiency that begs for automation.
The Solution: One Command to Rule Them All
With full support from leadership, I set out to solve this properly. Not with documentation alone (though we have that too), not with templates (they drift over time), but with a CLI that makes best practices the path of least resistance.
pnpm dlx @raftlabs/raftstack initThat's it. Run this command in any TypeScript repository, answer a few questions, and in about 20 seconds, your project has:
- Git Hooks (Husky) for pre-commit, commit-msg, and pre-push validation
- Commit Standards (Commitlint + cz-git) with an interactive commit wizard
- Code Formatting (Prettier + lint-staged) that runs on every commit
- Branch Naming Rules validated on every push
- GitHub Integration: PR templates, CI workflows, CODEOWNERS
- AI Code Review configuration (CodeRabbit or GitHub Copilot)
- Contributing Guidelines and quick reference documentation
Smart Detection, Zero Configuration
RaftStack automatically detects your project structure:
- NX workspace? Detected.
- Turborepo? Detected.
- pnpm workspace? Detected.
- Single package? Detected.
It also figures out your package manager (npm, pnpm, or Yarn) and adapts all generated scripts accordingly. No manual configuration needed.
The Interactive Wizard
Instead of making assumptions, the CLI asks you what you need:
? Select your project type: (auto-detected: Turborepo)
? Enable Asana task linking in commits?
? Configure AI code review (CodeRabbit/GitHub Copilot)?
? Set up CODEOWNERS for automatic reviewer assignment?Based on your answers, it generates exactly what you need—nothing more, nothing less.
What Gets Created
After running the CLI, your project gains this structure:
your-project/
├── .husky/
│ ├── pre-commit # Runs lint-staged
│ ├── commit-msg # Validates commit format
│ └── pre-push # Validates branch names
├── .github/
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── workflows/pr-checks.yml
│ ├── CODEOWNERS
│ └── QUICK_REFERENCE.md
├── commitlint.config.js
├── .czrc
├── cz.config.js
├── .lintstagedrc.js
├── .prettierrc
├── .prettierignore
└── CONTRIBUTING.mdEvery file is generated with sensible defaults that work together out of the box.
Enforcing Quality Through Constraints
The real power isn't in what the CLI creates—it's in what it prevents.
Commit Message Validation
Every commit must follow the Conventional Commits format:
# This works
git commit -m "feat(auth): add social login support"
# This fails immediately
git commit -m "fixed the thing"No more cryptic commit history. Every commit clearly states what changed and why.
Branch Name Validation
Push attempts are blocked unless your branch follows the naming convention:
# This works
git push origin feature/user-authentication
# This is rejected
git push origin my-branchProtected branches (main, develop, staging, production) can't be pushed to directly—all changes must go through pull requests.
Pre-commit Quality Gates
Before any commit succeeds, lint-staged runs Prettier on your staged files. Inconsistent formatting? Fixed automatically. No debates about code style in PRs.
The Bigger Picture: A Complete Development Framework
RaftStack isn't meant to work alone. It's part of a comprehensive project setup workflow that our senior engineers collaboratively developed:
- Tech Lead Consultation — Discuss and document stack decisions before writing any code
- Repository Initialization — Use Better-T-Stack, Turborepo, or AWS Amplify based on project needs
- Organization Standards — Run
@raftlabs/raftstack init - Environment Management — Secure environment variables with EnvX encryption
- AI Development Setup — Initialize Claude Code with bundled skills for consistent AI-assisted development
This framework gives every engineer a clear, proven path from zero to productive. It's not about restricting creativity—it's about eliminating the boring parts so engineers can focus on solving interesting problems for our clients.
Metrics: Measuring What Matters
The CLI includes a metrics command that helps teams understand their repository health:
pnpm dlx @raftlabs/raftstack metricsThis shows:
- Percentage of commits following Conventional Commits
- Branch naming compliance
- Files that would fail lint checks
- Overall "health score" for the repository
This isn't about policing—it's about visibility. Teams can see where they stand and track improvement over time. It's been particularly useful for onboarding new team members to existing projects, giving them instant insight into the codebase conventions.
The Impact
After rolling this out organization-wide, we've seen:
- Project setup time: 2-3 days → 20 seconds
- Commit message quality: Drastically improved, with clear history across all projects
- PR review time: Reduced because changes are smaller and better documented
- Onboarding time: New engineers get productive faster because every project works the same way
- Code review friction: Eliminated debates about formatting—it's all automated
But the biggest win? Confidence. When I look at any RaftLabs repository now, I know exactly what I'll find. The same hooks, the same commit format, the same branch naming, the same PR templates. It just works.
Try It Yourself
RaftStack is open source and works with any TypeScript project:
# Initialize a new or existing project
pnpm dlx @raftlabs/raftstack init
# Setup GitHub branch protection rules
pnpm dlx @raftlabs/raftstack setup-protection
# Check repository compliance
pnpm dlx @raftlabs/raftstack metricsCheck out the GitHub repository for full documentation, or install it directly from NPM.
Building developer tools that save time is satisfying, but building tools that improve quality across an entire organization? That's a different level of impact.
I'm grateful to work at a company that values engineering excellence enough to invest in internal tooling. RaftLabs gave me the time and trust to build something that benefits every engineer and every client project we deliver.
If your team is growing and noticing similar coordination challenges, consider whether better tooling might help. It's not about discipline—it's about making the right thing the easy thing.
Sometimes the best code you write is the code that writes code.
