CLI-Core
CLI-Core is a Rust library for implementation-first command dispatch with an instance-owned runtime.
The architecture is intentionally small and portable:
- commands are registered as a tree of implementations
Commandowns command metadata and an internal strategy handleCommandStrategyowns behavior for the selected command only- routing nodes forward subcommands; leaf strategies consume the parsed invocation
- help output is generated from command metadata through a pluggable
HelpRenderer
Core concepts
Command model
Command is the unit of registration. It contains:
metadata: CommandMetaData- an internal strategy handle
CommandMetaData includes required and optional help-facing fields:
- required:
name,description - optional:
usage,long_description,examples,options,aliases
Use CommandMetaData::new(...) and builder-style metadata methods such as with_usage(...), with_examples(...), and with_options(...).
Strategy model
CommandStrategy defines one method:
CliCore resolves argv[1] as the command name and parses the remaining tokens into:
options: bare flags such as--verbosearguments: flag/value pairs such as--path ./tmpsubcommands: the remaining command chain for nested routing
Only the final selected command strategy receives the parsed invocation. Intermediate routing commands can ignore flags and options.
Help rendering
Help is rendered from registered command metadata via HelpRenderer.
Default behavior uses PlainTextHelpRenderer, configured in CoreConfig::new().
You can inject a custom renderer with CoreConfig::with_help_renderer(...).
Quick start
1. Define a strategy
use HashMap;
use ;
;
2. Register commands
use ;
let core = new;
core.register;
For nested commands, build a tree and let the runtime route to the leaf:
use HashMap;
use ;
;
let app = command
.subcommand
.build;
3. Run dispatch
core.run_with_commands;
Or use crate-level helpers:
run_with_commands;
4. Run with explicit args (tests/embedding)
use CliCoreError;
5. Pass parsed flags and values
let args = vec!;
core.try_run_from_args?;
Configuring the runtime
CoreConfig is runtime-owned and immutable after CliCore::create(config).
use ;
let config = new
.with_lock_poison_policy;
let core = create;
Custom help rendering
use ;
;
Use it with CoreConfig::with_help_renderer(...).
Proc macro (#[cli])
The #[cli] macro lives in the separate cmdkit-macros crate. Add it alongside cli-core and import it from that package:
use HashMap;
use StrategyError;
use cli;
This generates ListFiles with ListFiles::new() and a list_files_strategy() factory.
If you do not want the macro crate, you can still build commands directly with Command::new(...) or Command::from_fn(...).
Error model
- routing errors:
CliCoreError - strategy errors:
StrategyErrorwith kindsInvalidArgumentsExecutionInternal
CliCoreError::StrategyExecutionretains the original strategy error as source
Notes
- command lookup is flat by command name at the runtime boundary
- help is metadata-driven and can recursively traverse registered subcommand trees
- routing commands only forward nested subcommands; leaf strategies consume parsed flags and values
- the runtime is instance-owned, so the architecture stays portable and does not depend on process-global state