TL;DR: go-tool-base’s generator doesn’t just scaffold a project once and walk away. It keeps a .gtb/manifest.yaml that describes your CLI’s command tree — names, flags, hierarchy — and regenerate rebuilds the wiring code to match it. Edit the manifest, regenerate, and the boilerplate follows. It turns CLI structure into something you design in one readable file rather than something you hand-assemble across a dozen.
Where does a CLI’s structure actually live?
Picture a CLI tool with twenty commands, some nested under others. Where, precisely, does its structure live? Not the logic of each command, the structure: which commands exist, what they’re called, which flags they take, what’s nested under what.
In a typical project, the honest answer is “smeared across the codebase.” It’s in twenty cmd.go files. It’s in the AddCommand calls that stitch them together. It’s in the flag registrations. To understand the shape of the tool you have to read all of it and assemble the picture in your head, because the picture exists nowhere as a single artefact.
That’s a strange state of affairs for the single most important design fact about a CLI. The command tree is the tool’s interface — it’s the thing users actually touch — and it has no home.
The manifest gives it one
go-tool-base’s generator gives that structure a home: .gtb/manifest.yaml. The manifest is a single readable file describing the command tree. Every command, its name, its short description, its flags, its place in the hierarchy, whether it carries assets or an initialiser. The shape of the whole tool, in one place you can open and read top to bottom.
And the manifest isn’t documentation about the project. It’s the thing the project’s wiring is generated from. When you run regenerate project, the generator reads the manifest and rebuilds the boilerplate to match it: the command constructors’ registration, the AddCommand wiring, the flag definitions. The manifest is the source of truth, and the Go wiring is its output.
Design-first, when you want it
This unlocks a workflow that the smeared-across-the-codebase approach can’t offer. You can design the interface first, in the manifest, and let the code follow.
Want to rename a command? Edit one line in the manifest, run regenerate, and the rename propagates through every wiring file that referenced it. Want to move a subcommand under a different parent? Change its place in the manifest hierarchy and regenerate. Want to add a flag to three related commands? Add it in the manifest, in three obvious places, and regenerate, instead of hunting down three flag-registration blocks scattered across the tree.
You’re editing the tool’s interface as a design, in the file whose entire job is to hold that design, and the generator does the mechanical work of making the code reflect it. The thing you change is the thing that describes the structure. The code is downstream.
If that shape sounds familiar, it should. It’s the same instinct behind spec-driven and test-driven development: write down what the thing should be before you assemble how it works, and keep that statement-of-intent as a first-class, living artefact rather than a comment that rots. The manifest is a spec for your command tree, and regenerate is what keeps the implementation honest to it.
It doesn’t trap you
A reasonable worry about any generated-from-a-manifest system is the obvious one: am I now locked into editing the manifest? What if I just want to open a Go file and write Go?
You can. The generator is careful not to own everything. It owns the wiring — the registration and structural boilerplate — and it leaves your command logic alone. The RunE function where your command actually does its work is yours; the manifest has no opinion about it. And the generator tracks the files it produces by content hash, so if you do hand-edit something it generated, regeneration notices and asks before overwriting rather than steamrolling you. (That mechanism has its own post.)
So the manifest is an option, not a cage. Design-first via the manifest when that suits the change. Drop into Go directly when that suits it better. The two stay in sync because regeneration reconciles them, rather than because one has been forbidden.
Pulling it together
A CLI’s command tree is its most important design surface, and in most projects it has no single home — it’s reconstructed in your head from twenty scattered files. go-tool-base gives it one: .gtb/manifest.yaml, a readable description of the whole tree that the generator rebuilds the wiring code from. Edit the manifest, run regenerate, and the boilerplate follows.
It makes CLI structure something you design in one place, in the spirit of spec-driven development, while still leaving you free to write Go directly when that’s the better tool. The manifest is the spec for your interface. The generator keeps the code faithful to it.