Most Rust CLIs today are built with clap—and for good reason. It’s powerful, flexible, and deeply integrated with Rust.
But there’s another approach worth exploring.
Two ways to define a CLI
clap (code-first)
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
You define your CLI structure directly in Rust.
tkucli (config-first)
[[resource]]
name = "users"
[[resource.operation]]
verb = "list"
You define your CLI as a schema, and the framework generates the rest.
Key differences
| clap | tkucli | |
|---|---|---|
| Definition | Rust code | cli.toml |
| Structure | Command tree | Resource → operation |
| Changes | Edit code | Edit config |
| Boilerplate | Manual | Generated |
| TUI | External | Built-in |
What this changes
With clap, your CLI is part of your code.
With tkucli, your CLI becomes data that drives your code.
That enables:
- clearer separation between interface and logic
- easier structural changes
- a shared definition for CLI and TUI
When each works well
clap
- You want full control in Rust
- Your CLI is stable
- You prefer explicit code
tkucli
- Your CLI evolves frequently
- You want a declarative structure
- You like separating interface from implementation
Takeaway
These aren’t competing so much as different design choices:
- clap → code-first CLI
- tkucli → schema-driven CLI
If you’ve only used one style, it’s worth trying the other—you might find it fits certain projects better.
Top comments (0)