I stopped hand-writing CLI glue code

Making structure explicit and generating code and docs from the same source.

Every time I build a command-line tool, the same pattern repeats.

I sketch the commands on paper.
I wire them up in code.
I add flags, options, help text.
Then I add documentation.
Then the docs drift.
Then the CLI changes again.

None of that work is hard. It’s just fragile and repetitive.

What bothered me most wasn’t the boilerplate — it was the fact that the structure of the tool existed only implicitly, scattered across code, docs, and conventions.

So I started experimenting with a different idea:

What if the structure itself was explicit, validated, and the single source of truth?

A schema-first approach

I built a small tool called arb around a simple principle:

  • define the shape of a tool using a schema
  • describe a specific tool instance as data
  • generate everything deterministically from that

That “everything” includes:

  • a working CLI
  • help output
  • documentation
  • man pages

The schema enforces what’s allowed.
The data describes what exists.
Templates turn that into real artifacts.

No runtime magic. No reflection. Just generation.

A concrete example: a real Rust CLI

To make sure this wasn’t theoretical, I included a Rust example that generates a Clap-based CLI with:

  • global flags
  • leaf commands
  • nested subcommands (remote add, remote list)
  • correct help output at every level

All of that structure comes from data — not handwritten Rust.

arb compile --package packages/cli-rust \
  --data packages/cli-rust/examples/data.nested.yaml \
  --out out
cd out
cargo run -- remote add foo https://example.com

The generated code is boring — and that’s the point.

Documentation from the same source

Because the schema already knows about commands, arguments, and examples, documentation becomes another output.

The same data that defines the CLI also generates:

  • Markdown command reference docs
  • a man page

Documentation doesn’t drift, because it’s not handwritten.

Why this exists

This project isn’t trying to replace existing CLI libraries or frameworks.

It’s an experiment in making structure explicit and letting code and docs fall out of that structure automatically.

It’s pre-alpha, intentionally small, and focused on correctness and clarity rather than features.

If you’re interested, the repository is here:
https://github.com/arbopa/arb

Feedback is welcome — especially from people who’ve felt the same friction building tools like this.

← Back to Blog