An Internal CLI Is the Cheapest Compounding Tool You Can Build
The highest-leverage internal tool is a CLI that scaffolds every new app the same way. Here is why an internal CLI compounds harder than any shared library.
If I could keep only one internal tool, I would keep the CLI that scaffolds a new app. Type one command and I get a project wired to shared auth, shared billing, the design tokens, the deploy pipeline, and the standard folder layout, correct on the first commit. That is the tool that turns a shared foundation from a library you have to assemble into a paved road you can drive. A CLI is cheap to build and it compounds every single time I start something new.
The reason it compounds so hard is that scaffolding is the moment mistakes get baked in. Get the first commit wrong and every later decision inherits the wrong shape. A CLI makes the correct setup the default and the wrong setup extra work. That is the whole trick.
Why a CLI beats a starter template
Most teams reach for a template repo instead. You clone it and start editing. Templates are better than nothing, but they have a fatal flaw: they are a snapshot. The day you clone, the template stops improving your app. Six months later every app cloned from it has drifted, and the fixes you made to the template never reach them. I wrote about this exact trap in starter template vs a living foundation.
A CLI is not a snapshot. It is a program. It can pull the current versions, wire the current auth flow, and generate against the foundation as it exists today, not as it existed the day someone made the template. The scaffold stays fresh because the tool stays maintained. That is the difference between copying the foundation and connecting to it.
What the CLI should actually do
Keep the scope tight. An internal CLI earns its keep with a handful of commands, not a hundred.
newscaffolds an app: correct structure, shared dependencies pinned, auth and billing wired, deploy config generated. This is how I spin up a new app in a day instead of a week.generatestamps out the repetitive units inside an app: a new API route with the standard error handling, a new page with the layout already correct, a migration with the naming convention baked in.checkruns the same lint, type, and convention checks every app runs, so "does this follow the paved road" is one command, not a code review.deploywraps the pipeline so every app ships the same way. This is where owning your deploy pipeline turns into muscle memory.
Notice what is not here: config for cases you do not have, plugins, a framework. An internal CLI that tries to be a platform becomes a second product you have to maintain. Keep it a thin layer over the foundation.
The CLI is how the paved road gets paved
I have argued that the paved road beats a free-for-all. The CLI is how you actually pave it. A paved road that lives only in a docs page is a suggestion. A paved road you get by typing new is the default. People, and agents, follow defaults. If the correct path is also the easiest path, you do not have to enforce conventions in review, because the tool already applied them.
This matters most for consistency across a portfolio. When every app was scaffolded by the same CLI, they share a shape. You can move between them without relearning where things live. A runbook works across twenty apps precisely because the CLI made those twenty apps structurally similar. Divergence is a choice you make on purpose, not entropy you accumulate by accident.
Building it is a weekend, maintaining it is the job
The first version is small. A script that copies a structure, runs a few replacements, and installs the shared packages. You can build that in a weekend and feel the payoff on the next new app. The ongoing work is keeping it in step with the foundation: when auth changes, the new command has to wire the new auth. When a convention changes, generate has to stamp the new convention.
That maintenance is the price, and it is worth it because the CLI is a force multiplier on every other foundation investment. Better tokens, better shared libraries, a better deploy pipeline all reach new apps faster because the CLI carries them there on day one.
I run scaffolding and generation through the same build workflow I use at Bootspring, so a new product starts fully wired to the foundation instead of half-assembled by hand. If you have a shared foundation and no CLI on top of it, you are making people, and agents, assemble the foundation by hand every time. Build the tool that does it for them. It is the cheapest thing on the shelf that keeps paying you back.