dynamic-cli
A powerful Rust framework for creating configurable CLI and REPL applications via YAML/JSON files.
Define your command-line interface in a configuration file, not in code. β¨
English | FranΓ§ais
π― Features
- π Configuration-Driven : Define commands, arguments and options in YAML/JSON
- π CLI, REPL & Batch Modes : Command-line, interactive, and scripted batch execution
- β Automatic Validation : Built-in type checking and constraint validation
- π¨ Rich Error Messages : Colorful and informative messages with suggestions
- π Plugin System : Granular static plugins (help, version, exit, sysinfo, env, config β compose only what you need) and sandboxed WASM plugins (loaded at runtime)
- π Well Documented : Complete API documentation and examples
- π§ͺ Thoroughly Tested : Extensive test coverage
- β‘ Performance : Zero-cost abstractions with efficient parsing
π Quick Start
Installation
Add to your Cargo.toml:
[]
= "0.7.0"
# Optional β sandboxed WASM plugins (see Plugin System below)
# dynamic-cli = { version = "0.7.0", features = ["wasm-plugins"] }
Basic Example
1. Create a configuration file (commands.yaml):
metadata:
version: "1.0.0"
prompt: "myapp"
prompt_suffix: " > "
commands:
- name: greet
aliases:
description: "Greet someone"
required: false
arguments:
- name: name
arg_type: string
required: true
description: "Name to greet"
validation:
options:
- name: loud
short: l
long: loud
option_type: bool
required: false
description: "Use uppercase"
choices:
implementation: "greet_handler"
global_options:
Note :
The proper syntax for the configuration file is available in the project repository.
2. Implement your command handlers:
use *;
// Define your application context
// Implement the command handler
;
3. Run your application:
# CLI mode
# REPL mode
Batch mode β run a whole file of commands, one per line (blank lines and
#-prefixed comments are skipped):
let outcome = app.run_script?;
println!;
The same file can also be loaded from inside an already-running REPL
session with :load commands.txt.
π Plugin System
Extend an application with handlers that do not live in your own crate,
without modifying dynamic-cli itself. Two mechanisms are available:
| Mechanism | When to use it | Cost |
|---|---|---|
Static plugins (Plugin trait) |
Compiled into your binary | No unsafe, no extra dependency |
WASM plugins (WasmPlugin) |
Distributed and loaded independently, sandboxed | wasmtime dependency, opt-in via features = ["wasm-plugins"] |
dynamic-cli ships SystemPlugin out of the box β help, version, and
exit in one call:
use SystemPlugin;
new
.config_file
.context
.register_plugin
.register_sync_handler
.build?
.run
Each of help/version/exit is also available as its own independent
plugin (HelpPlugin, VersionPlugin, ExitPlugin) β register only the one
you need instead of the bundle. Three more, feature-gated, cover common
introspection needs: SysInfoPlugin (sysinfo-plugin, OS/architecture/
parallelism), EnvPlugin (env-plugin, filtered environment variables β
sensitive-looking ones hidden by default), and ConfigPlugin
(config-plugin, show/re-validate the loaded YAML config without
restarting):
use ;
new
.config_file
.context
.register_plugin
.register_plugin
.build?
.run
WASM plugins run in a wasmtime sandbox, with no unsafe code on the host
side:
new
.config_file
.context
.register_wasm_plugin?
.build?
.run
Static and WASM plugins, and directly-registered handlers, all coexist in the same application β the YAML configuration remains the single source of truth for command definitions either way.
Full Plugin Guide β (FranΓ§ais) β the complete WASM ABI contract for third-party plugin authors, a worked example, and the architecture decision behind it (DD-021).
π Documentation
- API Reference - Complete API documentation
- Examples - Working examples and code samples
- Contributing Guide - How to contribute to the project
π Examples
The examples directory contains complete examples:
- simple_calculator.rs - Basic arithmetic calculator
- rpn_calculator.rs - Reverse Polish Notation calculator
- advanced_rpn_calculator.rs - HP-41CX-flavored RPN calculator with scientific functions, memory registers,
SysInfoPlugin/ConfigPlugin, and batch/:loadexecution - file_manager.rs - File operations with validation
- task_runner.rs - Task management application
- async_token_demo.rs - Async command handler demo
Run any example:
# advanced_rpn_calculator needs its two feature flags:
π Architecture
dynamic-cli is organized into focused modules:
- config - Configuration loading and validation
- context - Execution context trait
- executor - Command execution engine
- registry - Command and handler registry
- parser - CLI and REPL argument parsing
- validator - Argument validation
- interface - CLI and REPL interfaces
- error - Error types and display
- builder - Fluent API for building applications
- help - Dynamic
--helpgeneration - plugin - Granular static plugins (
plugin::builtin: help, version, exit, sysinfo, env, config) and sandboxed WASM (wasm-pluginsfeature) extension mechanisms
π§ͺ Tests
# Run all tests (default features)
# Run all tests, across every feature flag
# Run with coverage
# Check code quality
Current test statistics:
- 500+ unit tests β
- 230+ documentation tests
- 12 integration tests (static + WASM plugins, full public API chain)
- 80-90% code coverage (not re-measured for v0.7.0 β
cargo-llvm-covwasn't run this sprint) - Zero clippy warnings, confirmed across
--all-features(wasm-plugins,sysinfo-plugin,env-plugin,config-plugincombined)
π€ Contributing
We welcome contributions from everyone! Here's how you can help:
Ways to Contribute
- π Report bugs - Found a bug? Open an issue
- π‘ Suggest features - Have an idea? Start a discussion
- π Improve documentation - Fix typos, clarify, add examples
- π§ Submit code - Fix bugs, implement features, improve performance
- π§ͺ Add tests - Increase coverage, add edge cases
Getting Started
# Fork and clone
# Create a branch
# Make your changes and test
# Commit and push
Development Guidelines
Before submitting a pull request:
- Code follows Rust style guidelines (
cargo fmt) - All tests pass (
cargo test --all-features) - No clippy warnings (
cargo clippy --all-features -- -D warnings) - Documentation is updated
- New tests added for new features
- Commit messages are clear and descriptive
Code of Conduct
This project follows a Code of Conduct to ensure a welcoming environment:
- β Be respectful to others
- β Welcome newcomers and help them learn
- β Constructive criticism helps us move forward and improveβlet's embrace it
- β Focus on what's best for the community
- β No harassment, trolling or personal attacks
Read the complete contributing guide β
π License
Licensed under your choice of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
Contribution Licensing
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
π Acknowledgments
- Rust Community - For the amazing tools and libraries developed
- Contributors - Everyone who has contributed to this project
- clap - Inspiration for CLI design
- rustyline - REPL functionality
- serde - Serialization support
π Support
Need help?
- π Check the API documentation
- π¬ Open a discussion
- π Report an issue
- π§ Contact the maintainers
Found a security vulnerability?
Please report it privately to the maintainers.
π Show Your Support
If you find dynamic-cli useful, please:
- β Star the repository on GitHub
- π’ Share it with others who might find it useful
- π Write a blog post or tutorial!
Last updated: 2026-08-23