Expand description
§Module :: unilang
Zero-overhead command framework with compile-time command registration
§Table of Contents
Getting Started
- Value Proposition - Why unilang?
- Architecture Overview - How it works
- Getting Started (60 Seconds) - Quick start
- Troubleshooting - Common issues & solutions
- Quick Start: Build-Time Registration - Detailed guide
Understanding Performance
- Performance Comparison - Benchmarks & methodology
- Comparison to Alternatives - vs clap/structopt/argh
Core Concepts
- User Guide: Integration Decisions - Design choices
- Command Definition Format - YAML structure
- Command Execution Patterns - Usage patterns
- Help System - Three access methods
Advanced Topics
- CLI Aggregation - Multi-tool consolidation
- Migration from Runtime to Build-Time - Upgrade guide
- Performance Optimization Guidelines - Tuning
- WebAssembly Support - Browser deployment
Reference
- Usage Guide (usage.md) - Complete syntax reference
- Feature Configuration - Feature flags
- Examples and Learning Path - Code examples
§Value Proposition
unilang processes command definitions at compile-time, generating optimized static command registries that provide O(1) command lookups with zero runtime overhead and zero additional dependencies for downstream crates. This approach delivers:
- 50x faster command resolution compared to runtime HashMap lookups (~80ns vs ~4,000ns)
- Compile-time validation of all command definitions and arguments
- Smaller binary size through static analysis and dead code elimination
- SIMD acceleration for parsing with 4-25x performance improvements
- Zero memory allocations for command lookup operations
§Architecture Overview
§Build-Time Processing (Happens Once)
Developer writes YAML
|
v
unilang.commands.yaml
- name: ".greet"
description: "..."
arguments: [...]
|
v
build.rs (automatic)
- Discovers YAML files
- Validates definitions
- Generates static command map
|
v
OUT_DIR/static_commands.rs
static STATIC_COMMANDS: [...]
// Static commands with O(1) lookups
|
v
Binary compiled
(zero-overhead ready)§Runtime Execution (Every Command)
User: ".greet name::Alice"
|
v
Parser
(SIMD accelerated)
|
v
Static Registry Lookup
O(1) static map access
~80ns (no hashing!)
|
v
Semantic Analyzer
- Validate types
- Apply defaults
- Check constraints
|
v
Command Routine
Execute business logic
|
v
Output ResultKey Benefits:
- ⚡ Build-time: Validation catches errors before deployment
- 🚀 Runtime: O(1) lookups with zero allocations (~80ns)
- 📦 Binary: Smaller size via static analysis
- 🔒 Type-safe: Impossible to register invalid commands
§Getting Started (60 Seconds)
-
Add dependency:
[dependencies] unilang = "0.35" -
Create
unilang.commands.yamlin project root:- name: ".greet" description: "Greeting command" arguments: - name: "name" kind: "String" attributes: optional: true default: "World" -
Run example:
cargo run --example static_01_basic_compile_time
What just happened? Commands auto-discovered from YAML, compiled into zero-overhead static registry, ready for O(1) lookups.
Next: See detailed guide for production setup.
§Troubleshooting
Common issues and solutions for new users:
§❌ “Command not found” error
Symptom: Error: Command '.greet' not found in registry
Cause: Command name missing dot prefix
Solution:
# ❌ Wrong
- name: "greet"
# ✅ Correct
- name: ".greet"All command names MUST start with . (dot prefix)
§❌ “Type mismatch” error during build
Symptom: Type hint warnings during cargo build
Cause: YAML default values quoted when they shouldn’t be
Solution:
# ❌ Wrong - quoted values
arguments:
- name: "dry"
kind: "Boolean"
attributes:
default: 'false' # String, not Boolean!
# ✅ Correct - unquoted primitives
arguments:
- name: "dry"
kind: "Boolean"
attributes:
default: false # Boolean typeRule: Boolean, Integer, Float values must NOT be quoted in YAML
§❌ Build fails with “could not find static_commands.rs”
Symptom: error: couldn't read .../static_commands.rs: No such file or directory
Cause: Wrong feature flag or missing build-time approach
Solution:
# Ensure you have a build-time approach enabled
[dependencies]
unilang = "0.35" # Default includes approach_yaml_multi_buildCheck that you have at least one .yaml file with commands, or enable a different build-time approach feature.
§❌ Performance not improved after migration
Symptom: Lookups still slow after switching to build-time approach
Cause: Using runtime registration in production CLI (10-50x performance penalty)
Solution:
// ❌ Wrong for production CLIs - 10-50x slower than static registration
// ✅ Appropriate for REPL/plugins/prototyping where flexibility > performance
let registry = CommandRegistry::new();
// ✅ Correct - using static registry
let registry = StaticCommandRegistry::from_commands(&STATIC_COMMANDS);Verify you’re using StaticCommandRegistry, not CommandRegistry::new().
§❌ “Unknown parameter” error
Symptom: Error: Unknown parameter 'nam'
Cause: Typo in parameter name
Solution: Check error message for “Did you mean…?” suggestion:
Error: Unknown parameter 'nam'. Did you mean 'name'?
Use '.greet ??' for helpParameter names are validated strictly - use ?? operator to see valid parameters.
§🔍 Still having issues?
- Check examples: Run
cargo run --example static_01_basic_compile_time - Enable verbose logging: Set
RUST_LOG=debug - Verify feature flags: Run
cargo tree -f "{p} {f}" - Review usage.md for detailed syntax rules
§Usage Guide
For comprehensive usage patterns, best practices, and quick reference: See usage.md for concise guide covering:
- Command naming conventions and structure
- Argument types and validation
- Parameter syntax and quoting rules
- Help system (3 access methods)
- Error handling patterns
- REPL implementation
- CLI aggregation
- Testing and performance
- Security considerations
§Quick Start: Build-Time Registration (Recommended)
§Step 1: Define Commands
Create unilang.commands.yaml:
- name: ".greet" # RECOMMENDED: Show full command name
namespace: "" # Leave empty for root-level commands
description: "High-performance greeting command"
arguments:
- name: "name"
kind: "String"
attributes:
optional: true
default: "World"YAML Command Naming:
- Recommended:
name: ".greet"withnamespace: ""- shows exact command users will type - Alternative:
name: "greet"withnamespace: ".session"- requires understanding concatenation - Always include the dot prefix in either
nameornamespace
§Step 2: Configure Cargo.toml
The default configuration already enables build-time YAML processing:
[dependencies]
# Multi-YAML build-time approach is enabled by default
unilang = "0.35"For single-file YAML approach, use:
[dependencies]
unilang = { version = "0.35", default-features = false, features = [
"enabled",
"approach_yaml_single_build" # Single YAML file at compile-time
]}§Step 3: Build Script (Do You Need build.rs?)
Decision Tree:
Using default multi-YAML approach?
├─ YES → ✅ No build.rs needed (auto-discovery)
└─ NO → Using single-file YAML?
├─ YES → ✅ Add minimal build.rs below
└─ NO → ✅ Custom approach - implement discovery logicFor Single-File YAML Only (approach_yaml_single_build):
fn main()
{
// Rebuild if YAML file changes
println!( "cargo:rerun-if-changed=unilang.commands.yaml" );
// Static registry generation happens automatically
}Default Multi-YAML: No build.rs needed - automatic discovery of all .yaml files!
§Step 4: Zero-Cost Execution
use unilang::prelude::*;
// Include compile-time generated commands (created automatically by build system)
include!( concat!( env!( "OUT_DIR" ), "/static_commands.rs" ) );
fn main() -> Result< (), unilang::Error >
{
// StaticCommandRegistry requires approach_yaml_single_build,
// approach_yaml_multi_build, or other build-time approach feature
let registry = StaticCommandRegistry::from_commands( &STATIC_COMMANDS );
let pipeline = Pipeline::new( registry );
// O(1) lookup - no hashing overhead
let result = pipeline.process_command_simple( ".greet name::Alice" );
println!( "Output: {}", result.outputs[ 0 ].content );
Ok( () )
}§Performance Comparison
| Approach | Lookup Time | Memory Overhead | Binary Size |
|---|---|---|---|
| Build-Time (Static) | ~80ns | Zero | Smaller |
| Runtime (HashMap) | ~4,000ns | Hash tables + allocations | Larger |
Benchmark Results:
- Static lookups: ~80-100ns (static map + zero allocations)
- Runtime lookups: ~4,000-5,000ns (HashMap + semantic analysis)
- Performance gain: 50x faster command resolution
§Benchmark Methodology
Hardware: AMD Ryzen 9 5950X, 64GB RAM, NVMe SSD
Framework: benchkit - specialized benchmarking framework for unilang
Test Scenario: Lookup 100 commands from registry of 1,000 commands
Iterations: 10,000 runs per approach, median reported
Tool: cargo run --example static_03_performance_comparison
What’s measured:
- Static: Static map lookup + CommandDefinition retrieval
- Runtime: HashMap lookup + CommandDefinition retrieval
- Excludes parsing (measured separately with SIMD benchmarks)
Run benchmarks yourself:
cargo run --release --example static_03_performance_comparisonSee /examples/static_03_performance_comparison.rs for full benchmark implementation.
§Comparison to Alternatives
How unilang differs from popular Rust CLI frameworks:
| Feature | unilang | clap | structopt | argh |
|---|---|---|---|---|
| Command Lookup | O(1) static | Runtime HashMap | Runtime | Runtime |
| Definition Style | YAML/JSON/Rust DSL | Rust builder API | Derive macros | Derive macros |
| Modality Support | CLI, REPL, Web API | CLI only | CLI only | CLI only |
| Multi-file Organization | Auto-discovery | Manual | Manual | Manual |
| Runtime Registration | Hybrid (10-50x slower†) | No | No | No |
| Build-time Validation | Yes | No | Yes (compile) | Yes (compile) |
| REPL Support | Built-in | Manual | Manual | Manual |
| Help Generation | Auto + 3 operators | Auto | Auto | Auto |
| Performance | ~80ns lookup | ~200-500ns | ~200-500ns | ~100-300ns |
| CLI Aggregation | Built-in | Manual | Manual | Manual |
| Learning Curve | Medium | Low | Low | Very Low |
† Runtime registration appropriate for REPL applications, plugin systems, and prototyping. Not recommended for production CLIs due to performance penalty.
§When to Choose unilang
Choose unilang if you need:
- ✅ REPL or interactive shell interfaces
- ✅ Multi-modality support (CLI + Web API + TUI)
- ✅ Runtime plugin/command discovery (hybrid mode)
- ✅ Maximum performance with static dispatch
- ✅ CLI aggregation across multiple crates
- ✅ Declarative YAML/JSON command definitions
Choose alternatives if:
- ❌ You only need basic CLI arg parsing (use
argh- simplest) - ❌ You prefer pure-Rust derive macros (use
structopt/clap) - ❌ You need mature ecosystem with extensive plugins (
claphas most) - ❌ You want minimal learning curve (
arghis fastest to learn)
§Philosophy Differences
unilang:
- “Define once, use everywhere” - single command definition for all modalities
- Optimized for command-rich applications (100s of commands)
- Build-time optimization and validation
clap/structopt/argh:
- “CLI-first” - specialized for argument parsing
- Optimized for applications with 1-20 commands
- Runtime flexibility, simpler mental model
§User Guide: Integration Decisions
§Decision 1: How Should I Define Commands?
⚠️ IMPORTANT: Opinionated Defaults
unilang ONLY enables Approach #2 by default. To use any other approach, you must explicitly enable its feature flag in Cargo.toml.
10 approaches are currently implemented (see full comparison):
| # | Approach | Feature Flag | Default | Lookup Speed | When to Use |
|---|---|---|---|---|---|
| 1 | YAML file → Build-time static | approach_yaml_single_build | ❌ | ~80ns | Single-file projects, compile-time validation |
| 2 | Multi-YAML files → Build-time static | approach_yaml_multi_build | ✅ DEFAULT | ~80ns | Modular projects, best DX, auto-discovery |
| 3 | YAML file → Runtime loading | approach_yaml_runtime | ❌ | ~4,200ns | Plugin configs, runtime loading |
| 4 | JSON file → Build-time static | approach_json_single_build | ❌ | ~80ns | JSON-first projects, API generation |
| 5 | Multi-JSON files → Build-time static | approach_json_multi_build | ❌ | ~80ns | Large JSON projects, modular organization |
| 6 | JSON file → Runtime loading | approach_json_runtime | ❌ | ~4,200ns | Runtime config loading, dynamic commands |
| 7 | Rust DSL (builder API) | (always available) | ✅ | ~4,200ns | Core API, prototyping, type-safe definitions |
| 8 | Rust DSL (const fn + static) | approach_rust_dsl_const | ❌ | ~80ns | High-performance DSL, compile-time |
| 18 | Hybrid (static + runtime) | approach_hybrid | ❌ | Mixed | Base CLI + plugin system |
Why Approach #2 is Default:
- Best developer experience with auto-discovery of command files
- Optimal for modular projects splitting commands across multiple files
- Compile-time validation catches errors before runtime
- Zero overhead with static registry generation
See full comparison: 21 approaches documented including planned features like declarative macros, proc macros, TOML, RON, Protobuf, GraphQL, OpenAPI.
§Decision 2: How Do I Execute Commands?
// CLI applications: Avoids shell quoting issues
let result = pipeline.process_command_from_argv( &std::env::args().collect() );
// REPL/interactive applications: String-based parsing
let result = pipeline.process_command_simple( ".greet name::Alice" );§Decision 3: What Are the Naming Rules?
✅ Commands should start with a dot:
.greet name::Alice # Recommended
greet name::Alice # Not recommended§Decision 4: What Features Should I Enable?
Choose Your Configuration:
| Use Case | Configuration | What You Get |
|---|---|---|
| Production (Recommended) | unilang = "0.35" | Multi-YAML + SIMD + Enhanced REPL |
| Custom Approach | unilang = { version = "0.35", default-features = false, features = ["enabled", "approach_json_single_build"] } | Switch to specific approach |
| Minimal (Core API Only) | unilang = { version = "0.35", default-features = false, features = ["enabled"] } | Rust DSL only, no build-time |
| Full (Development/Testing) | unilang = { version = "0.35", features = ["full"] } | All 21 approaches available |
Most users: Just use unilang = "0.35" and you’re done.
Feature Architecture:
The framework uses approach-based feature flags:
- Each CLI definition approach has its own feature (e.g.,
approach_yaml_multi_build) - Approach features automatically enable required infrastructure (
static_registry,yaml_parser, etc.) - Only Approach #2 enabled by default for optimal performance and minimal binary size
- See Feature Flags Documentation for complete list
§Decision 5: How Does Help Work?
Three methods available:
.command ? # Traditional operator (bypasses validation)
.command ?? # Modern parameter
.command.help # Auto-generated help command§Decision 6: Error Handling
Unknown parameters are always detected with Levenshtein distance suggestions. This cannot be disabled and ensures command correctness.
§Decision 7: Advanced Use Cases
- REPL applications: Use
enhanced_replfeature for history, completion, secure input - WASM deployment: Full framework support in browsers with SIMD acceleration
- Interactive arguments: Prompt for missing required arguments in REPL mode
§Advanced Topics
The following sections cover advanced usage patterns, migration strategies, and specialized deployments. New users should start with the Getting Started section above.
§CLI Aggregation: Unifying Multiple Tools
⚠️ Feature Required: multi_file (automatically enabled by default approach_yaml_multi_build)
unilang excels at aggregating multiple CLI tools into a single unified command interface. This is essential for organizations that want to consolidate developer tools while maintaining namespace isolation.
§Real-World Aggregation Scenario
// Requires: approach_yaml_multi_build (default) or manually enable 'multi_file' feature
use unilang::multi_yaml::CliBuilder;
// Aggregate multiple CLI tools into one unified command
let unified_cli = CliBuilder::new()
.static_module_with_prefix( "database", "db", database_commands )
.static_module_with_prefix( "filesystem", "fs", file_commands )
.static_module_with_prefix( "network", "net", network_commands )
.static_module_with_prefix( "build", "build", build_commands )
.detect_conflicts( true )
.build_static();
// Usage: unified-cli .db.migrate, unified-cli .fs.copy src dest§Compile-Time Aggregation Benefits
Before Aggregation:
# Separate tools requiring individual installation and learning
db-cli migrate --direction up
file-cli copy --src ./source --dest ./target --recursive
net-cli ping google.com --count 10
build-cli compile --target releaseAfter Aggregation:
# Single unified tool with consistent interface
unified-cli .db.migrate direction::up
unified-cli .fs.copy source::./source destination::./target recursive::true
unified-cli .net.ping host::google.com count::10
unified-cli .build.compile target::release§Key Aggregation Features
§Namespace Isolation
Each CLI module maintains its own command space with automatic prefix application:
Database commands become .db.migrate, .db.backup
File commands become .fs.copy, .fs.move
Network commands become .net.ping, .net.trace
No naming conflicts between modules§Conflict Detection
let registry = CliBuilder::new()
.static_module_with_prefix( "tools", "tool", cli_a_commands )
.static_module_with_prefix( "utils", "tool", cli_b_commands ) // Conflict!
.detect_conflicts( true ) // Catches duplicate prefixes at build time
.build_static();§Help System Integration
# All aggregated commands support unified help
unified-cli .db.migrate.help # Detailed help for database migrations
unified-cli .fs.copy ?? # Interactive help during command construction
unified-cli .net.ping ? # Traditional help operator§Advanced Aggregation Patterns
§Conditional Module Loading
let registry = CliBuilder::new()
.conditional_module( "docker", docker_commands, &[ "feature_docker" ] )
.conditional_module( "k8s", kubernetes_commands, &[ "feature_k8s" ] )
.build_static();
// Only includes modules when features are enabled§Multi-Source Aggregation
use std::path::PathBuf;
// Combine static commands (in-memory) and dynamic YAML loading
let registry = CliBuilder::new()
.static_module_with_prefix( "core", ".core", core_commands )
.dynamic_module_with_prefix( "plugins", PathBuf::from( "plugins.yaml" ), ".plugins" )
.build_hybrid();
// Key differences:
// - static_module_with_prefix(name, prefix, Vec<CommandDefinition>)
// → Commands already in memory, fast O(1) lookup (~80-100ns)
// - dynamic_module_with_prefix(name, PathBuf, prefix)
// → Commands loaded from YAML file at runtime (~4,000ns, 50x slower)§Performance Characteristics
| Approach | Lookup Time | Memory Overhead | Conflict Detection |
|---|---|---|---|
| Build-Time | O(1) static | Zero | Build-time |
| Runtime | O(log n) | Hash tables | Runtime |
Aggregation Scaling:
- 10 modules, 100 commands each: ~80-100ns lookup regardless of module count
- Single static map: All 1,000 commands accessible in constant time with O(1) complexity
- Namespace resolution: Zero runtime overhead with compile-time prefixing
§Complete Example
See examples/practical_cli_aggregation.rs for a comprehensive demonstration showing:
- Individual CLI module definitions
- Runtime and compile-time aggregation approaches
- Namespace organization and conflict prevention
- Unified command execution patterns
- Performance comparison between approaches
# Run the complete aggregation demo
cargo run --example practical_cli_aggregationThis example demonstrates aggregating database, file, network, and build CLIs into a single unified tool while maintaining type safety, performance, and usability.
§Command Definition Format
§Basic Command Structure
- name: ".command_name" # Required: Command identifier (must start with dot)
namespace: "" # Optional: Hierarchical organization (e.g., "math", "file")
description: "What it does" # Required: User-facing description
arguments: # Optional: Command parameters
- name: "arg_name"
kind: "String" # String, Integer, Float, Boolean, Path, etc.
attributes:
optional: false # Required by default
default: "value" # Default value if optional§Supported Argument Types
- Basic Types: String, Integer, Float, Boolean
- Path Types: Path, File, Directory
- Complex Types: Url, DateTime, Pattern (regex)
- Collections: List, Map with custom delimiters
- Special Types: JsonString, Object, Enum
§Validation Rules
arguments:
- name: "count"
kind: "Integer"
validation_rules:
- Min: 1
- Max: 100
- name: "email"
kind: "String"
validation_rules:
- Pattern: "^[^@]+@[^@]+\\.[^@]+$"
- MinLength: 5§Common Pitfalls (Type Defaults)
⚠️ YAML permits type coercion, but unilang enforces strict typing. The build system now emits type hints for these common mistakes:
❌ WRONG - Quoted defaults for typed arguments:
- name: "dry"
kind: "Boolean"
attributes:
default: 'false' # String literal, not boolean
- name: "verbosity"
kind: "Integer"
attributes:
default: '2' # String literal, not integer✅ CORRECT - Unquoted defaults matching argument type:
- name: "dry"
kind: "Boolean"
attributes:
default: false # Boolean value
- name: "verbosity"
kind: "Integer"
attributes:
default: 2 # Integer value💡 Type Hint Detection: The build system analyzes argument definitions and emits non-blocking hints during cargo build when it detects potential type mismatches. To suppress hints for intentional cases (e.g., version strings like “1.0”), add suppress_type_hint: true to the argument’s attributes.
Help Generation:
auto_help_enabled: true # Default: true. Controls auto-generation of .command.help
# Set to false to prevent .command.help creation
# Help still available via ? and ?? operators§Command Execution Patterns
§Standard Execution
let result = pipeline.process_command_simple( ".namespace.command arg::value" );
if result.success
{
println!( "Success: {}", result.outputs[ 0 ].content );
}§Batch Processing
let commands = vec!
[
".file.create name::test.txt",
".file.write name::test.txt content::data",
".file.list pattern::*.txt",
];
let batch_result = pipeline.process_batch( &commands, ExecutionContext::default() );
println!( "Success rate: {:.1}%", batch_result.success_rate() * 100.0 );§Error Handling
match pipeline.process_command_simple( ".command arg::value" )
{
result if result.success =>
{
// Process successful execution
for output in result.outputs
{
println!( "Output: {}", output.content );
}
}
result =>
{
if let Some( error ) = result.error
{
eprintln!( "Command failed: {}", error );
}
}
}§Help System
unilang provides comprehensive help with three access methods:
§Traditional Help Operator
.command ? # Instant help, bypasses validation§Modern Help Parameter
.command ?? # Clean help access
.command arg1::value ?? # Help with partial arguments§Auto-Generated Help Commands
.command.help # Direct help command access
.namespace.command.help # Works with namespaced commands§Feature Configuration
§Core Features
[dependencies]
unilang = "0.10" # Default: enhanced_repl + simd + enabled§Performance Optimized
[dependencies]
unilang = { version = "0.10", features = ["simd", "enhanced_repl"] }§Minimal Footprint
[dependencies]
unilang = { version = "0.10", default-features = false, features = ["enabled"] }§Available Features
enabled- Core functionality (required)simd- SIMD optimizations for 4-25x parsing performanceenhanced_repl- Advanced REPL with history, completion, secure inputrepl- Basic REPL functionalityon_unknown_suggest- Fuzzy command suggestions
§Examples and Learning Path
§🚀 Start Here: Recommended Learning Path
1. Quick Start (Runtime, Educational Only)
00_quick_start.rs- Get something working in 5 minutes (⚠️ runtime registration, slow)01_basic_command_registration.rs- Understand the runtime API (⚠️ 50x slower than build-time)
2. Production Approach (Build-Time, Recommended)
static_01_basic_compile_time.rs- READ THIS FIRST - Explains proper YAML + build.rs patternstatic_02_yaml_build_integration.rs- Multi-YAML file aggregationstatic_03_performance_comparison.rs- Benchmark compile-time vs runtime (proves 50x speedup)static_04_multi_module_aggregation.rs- Organize commands across modules
3. Advanced Type System
02_argument_types.rs- String, Integer, Float, Boolean, Path, etc. (⚠️ requiresjson_parser)03_collection_types.rs- Lists, Maps with custom delimiters14_advanced_types_validation.rs- Complex validation rules (⚠️ requiresjson_parser)
4. Help & User Experience
06_help_system.rs- Comprehensive help system18_help_conventions_demo.rs- Three help access methods (?, ??, .help)
5. REPL Applications
12_repl_loop.rs- Basic REPL implementation15_interactive_repl_mode.rs- Interactive arguments + secure input (⚠️ requiresenhanced_repl)17_advanced_repl_features.rs- History, completion, recovery (⚠️ requiresenhanced_repl)
6. Complete Applications
full_cli_example.rs- Full-featured CLI with all concepts integratedpractical_cli_aggregation.rs- Real-world multi-tool aggregation (⚠️ requiresmulti_file)
§⚠️ Feature Requirements Legend
- No marker = Works with default features
- ⚠️
json_parser= Requires JSON support feature - ⚠️
enhanced_repl= Requires advanced REPL features - ⚠️
multi_file= Requires multi-file aggregation (default includes this)
§WebAssembly Support
unilang provides full WebAssembly compatibility for browser deployment:
cd examples/wasm-repl
wasm-pack build --target web --release
cd www && python3 -m http.server 8000WASM Features:
- Complete framework functionality in browsers
- SIMD acceleration where supported
- Optimized bundle size (800KB-1.2MB compressed)
- Seamless Rust-to-JavaScript integration
§Migration from Runtime to Build-Time
⚠️ PERFORMANCE NOTICE: Runtime command registration (CommandRegistry::new() and command_add_runtime()) has 10-50x slower performance than compile-time registration.
When to use runtime registration:
- ✅ REPL applications - Commands defined interactively
- ✅ Plugin systems - Commands loaded dynamically at runtime
- ✅ Prototyping - Rapid development iteration
When to use compile-time registration:
- ⚡ Production CLIs - Performance-critical applications
- ⚡ Large command sets - 100+ commands benefit from ~80ns PHF lookups
- ⚡ Embedded systems - Zero-overhead static dispatch
This section helps migrate performance-critical code from runtime to compile-time registration for 50x speedup.
Migrate from runtime registration (10-50x slower) to build-time registration (⚡ 50x faster) in 4 steps when performance matters.
§Step 1: Extract Command Definitions to YAML
Before (Runtime, in main.rs): ⚠️ NOT RECOMMENDED FOR PRODUCTION CLIs (10-50x slower)
let mut registry = CommandRegistry::new();
let greet_cmd = CommandDefinition {
name: ".greet".to_string(),
namespace: String::new(),
description: "Greeting command".to_string(),
hint: "Say hello".to_string(),
arguments: vec![
ArgumentDefinition {
name: "name".to_string(),
kind: Kind::String,
description: "Person's name".to_string(),
hint: "Name".to_string(),
attributes: ArgumentAttributes {
optional: true,
default: Some("World".to_string()),
..Default::default()
},
validation_rules: vec![],
aliases: vec![],
tags: vec![],
}
],
// ... other fields
status: "stable".to_string(),
version: "1.0.0".to_string(),
aliases: vec![],
tags: vec![],
permissions: vec![],
idempotent: true,
deprecation_message: String::new(),
http_method_hint: String::new(),
examples: vec![],
routine_link: None,
auto_help_enabled: false,
};
registry.command_add_runtime(&greet_cmd, greet_routine)?;After (Build-Time, in unilang.commands.yaml):
- name: ".greet"
namespace: ""
description: "Greeting command"
hint: "Say hello"
status: "stable"
version: "1.0.0"
tags: []
aliases: []
permissions: []
idempotent: true
deprecation_message: ""
http_method_hint: ""
auto_help_enabled: false
examples: []
arguments:
- name: "name"
kind: "String"
description: "Person's name"
hint: "Name"
attributes:
optional: true
default: "World"
multiple: false
interactive: false
sensitive: false
validation_rules: []
aliases: []
tags: []
routine_link: null§Step 2: Update Cargo.toml
Add feature flag:
[dependencies]
# Enable single-file YAML compile-time approach
unilang = { version = "0.35", features = ["approach_yaml_single_build"] }
# Or use default (multi-file auto-discovery)
unilang = "0.35"§Step 3: Configure Build Script (Single-File Only)
For approach_yaml_single_build, create build.rs:
fn main()
{
// Rebuild if YAML file changes
println!("cargo:rerun-if-changed=unilang.commands.yaml");
// Static registry generation happens automatically
// No manual code needed - the feature flag handles it
}Note: With default approach_yaml_multi_build, no build.rs needed - auto-discovery handles everything!
§Step 4: Update Code to Use Static Registry
Before (Runtime): ⚠️ 10-50x SLOWER (not recommended for production)
use unilang::prelude::*;
fn main() -> Result<(), unilang::Error> {
let mut registry = CommandRegistry::new();
// Manual registration (10-50x slower than static)
registry.command_add_runtime(&greet_cmd, greet_routine)?;
let pipeline = Pipeline::new(registry);
let result = pipeline.process_command_simple(".greet name::Alice");
Ok(())
}After (Build-Time):
use unilang::prelude::*;
// Include build-time generated commands (auto-generated by build system)
include!(concat!(env!("OUT_DIR"), "/static_commands.rs"));
fn main() -> Result<(), unilang::Error> {
// Zero-cost static registry (~80ns lookup vs ~4,000ns runtime)
let registry = StaticCommandRegistry::from_commands(&STATIC_COMMANDS);
let pipeline = Pipeline::new(registry);
let result = pipeline.process_command_simple(".greet name::Alice");
Ok(())
}§Step 5: Measure Performance Improvement
Run benchmarks:
cargo run --example static_03_performance_comparisonExpected results:
- Runtime registration: ~4,000ns per command lookup
- Compile-time registration: ~80-100ns per command lookup
- Performance gain: 50x faster
§Performance Optimization Guidelines
§Compile-Time Best Practices
- Use static command definitions for all known commands
- Leverage multi-module aggregation for organization
- Enable SIMD features for maximum parsing performance
- Utilize conflict detection during build process
§Runtime Considerations
- Reserve runtime registration for truly dynamic scenarios
- Minimize command modifications during execution
- Use batch processing for multiple commands
- Implement proper error handling and recovery
§Design Rules Compliance Notice
CRITICAL: This codebase must follow strict design rules. Before making changes, review:
$PRO/genai/code/rules/code_design.rulebook.md- Core design patterns and architecture rules$PRO/genai/code/rules/code_style.rulebook.md- Code formatting and style requirements
Key Rules Summary:
- Testing: All tests MUST be in
tests/directory, NOT insrc/asmod tests - Benchmarking: Use
benchkitframework ONLY - no custom timing code in tests - Performance Tests: NEVER mix benchmarks with unit tests - separate concerns
- Test Documentation: Every test file MUST have Test Matrix documentation
- Directory Structure:
tests/for tests,benches/for benchmarks (if using benchkit)
Common Violations to Avoid:
❌ Custom std::time::Instant timing code in test files
❌ Performance/benchmark tests in tests/ directory
❌ Missing file-level documentation with Test Matrix in test files
❌ Using anything other than benchkit for performance measurement
§Feature Flags
Unilang supports multiple feature flags to customize functionality and dependencies:
§Core Features
enabled- Core functionality (included indefault)full- All features enabled for maximum functionality
§REPL Features
-
repl- Basic REPL functionality with standard I/O- Provides interactive command execution
- Basic command history tracking
- Cross-platform compatibility
- No additional dependencies
-
enhanced_repl⭐ Enabled by Default - Advanced REPL with rustyline integration- Enables: All features from
replplus: - Arrow Key Navigation: ↑/↓ for command history browsing
- Tab Auto-completion: Command and argument completion
- Interactive Prompts: Secure password input with masking
- Session Persistence: History saved across sessions
- Terminal Detection: Auto-fallback to basic REPL in non-interactive environments
- Dependencies:
rustyline,std::io::IsTerminal
- Enables: All features from
§Performance Features
simd- SIMD optimizations for parsing and JSON processing- Enables:
simd-json(4-25x faster JSON), SIMD string operations - Automatic: Included in
defaultfor maximum performance - Disable with:
cargo build --no-default-features --features enabled
- Enables:
§Optional Features
on_unknown_suggest- Fuzzy command suggestions (requirestextdistance)
Note: Benchmarking tools are available in the separate unilang_benchmarks workspace crate
§Usage Examples
Basic REPL (minimal dependencies):
[dependencies]
unilang = { version = "0.10", features = ["repl"] }Default (Enhanced REPL included):
[dependencies]
unilang = "0.10" # Enhanced REPL enabled by defaultPerformance-optimized CLI:
[dependencies]
unilang = { version = "0.10", features = ["enhanced_repl", "simd", "on_unknown_suggest"] }Embedded/minimal:
[dependencies]
unilang = { version = "0.10", default-features = false, features = ["enabled"] }§Feature Compatibility
enhanced_replautomatically includesreplfullincludes all features except development-only ones- All features work together without conflicts
- Enhanced REPL gracefully falls back to basic REPL when needed
Re-exports§
pub use super::private::TypeAnalyzer;pub use super::private::TypeHint;pub use super::private::Severity;pub use super::private::HintGenerator;pub use super::aggregator;pub use super::builder;pub use super::type_analyzer;pub use super::hint_generator;pub use super::private::TypeAnalyzer;pub use super::private::TypeHint;pub use super::private::Severity;pub use super::private::HintGenerator;pub use unilang_parser as parser;pub use super::prelude::*;pub use super::prelude::*;
Modules§
- build_
helpers - Build-time helper utilities for type analysis and hint generation.
Provides tools for detecting type issues in YAML command definitions during build.
Requires feature:
yaml_parserBuild-time helper utilities for static registry generation - command_
validation - Command validation utilities. Command registration validation and utilities.
- config_
extraction - Config value extraction utilities.
Generic extractors for
HashMap<String, (JsonValue, S)>config maps. Requires feature:json_parser - data
- Core data structures and types.
- error
- Error handling utilities.
- exposed
- Exposed namespace of the module.
- help
- Help generation system.
- interner
- String interning system for performance optimization. String Interning System
- interpreter
- Command execution interpreter.
- loader
- Configuration loading from YAML/JSON.
Functions gated by
yaml_parserandjson_parserfeatures. - multi_
yaml - Multi-YAML build system for compile-time aggregation.
Requires feature:
multi_fileMulti-YAML Build System and Ergonomic Aggregation APIs - orphan
- Orphan namespace of the module.
- own
- Own namespace of the module.
- pipeline
- High-level pipeline API.
- prelude
- Prelude to use essentials:
use my_module ::prelude :: *. - registry
- Command registry management. Some functions gated by approach features.
- semantic
- Semantic analysis and validation.
- simd_
json_ parser - SIMD-optimized JSON parsing for 4-25x performance improvements.
Requires features:
simd-jsonANDjson_parser - simd_
tokenizer - SIMD-optimized tokenization for 3-6x performance improvements. SIMD-optimized tokenization for high-performance string processing.
- static_
data - Static data structures for compile-time commands.
Requires feature:
static_registry - types
- Value types and type system.
- validation_
core - Core validation logic shared between runtime and build.rs. This module can be included in build.rs via include!() since it has no dependencies. Core validation logic shared between runtime and build.rs.
Structs§
- Aggregation
Config - Re-export key aggregator types Re-export key aggregator types Configuration for multi-YAML aggregation
- Argument
Attributes - Holds attributes and configuration for a specific argument within a command.
- Argument
Definition - Defines an argument within a command, including its name, type, and constraints.
- Batch
Result - Result of processing multiple commands through the pipeline.
- CliBuilder
- Re-export key builder types Re-export key builder types Ergonomic CLI builder for simple and complex aggregation scenarios
- CliConfig
- Re-export key builder types Re-export key builder types Global CLI configuration
- Command
Definition - Type-safe command definition with validated newtypes and private fields.
- Command
Definition Builder - Type-state builder for
CommandDefinitionthat enforces required fields at compile time. - Command
Name - A validated command name that guarantees the dot prefix convention.
- Command
Registry - Runtime command registration. Consider compile-time alternatives for better performance. Runtime command registration. Consider compile-time alternatives for better performance. Runtime command registration. Consider compile-time alternatives for better performance.
- Command
Registry Builder - A builder for constructing
CommandRegistryinstances with a fluent API. - Command
Result - Result of processing a single command through the pipeline.
- Conditional
Module - Re-export key builder types Re-export key builder types Conditional module based on feature flags
- Conflict
Report - Re-export key aggregator types Re-export key aggregator types Report of detected conflicts
- Dynamic
Command Map - Optimized dynamic command storage with intelligent caching
- Dynamic
Module - Re-export key builder types Re-export key builder types Dynamic YAML module configuration for ergonomic APIs
- EnvConfig
Parser - Re-export key aggregator types Re-export key aggregator types Environment variable configuration parser
- Error
Data - Represents an error that occurred during command execution
- Execution
Context - The execution context for a command.
- Fast
Json Value - Performance-optimized JSON value for applications that need maximum parsing speed with minimal allocations.
- Help
Display Options - Global configuration for help output display.
- Help
Generator - Generates help information for commands.
- Interner
Stats - Statistics about the string interner’s current state.
- Interpreter
- The interpreter for Unilang commands.
- Module
Config - Re-export key aggregator types Re-export key aggregator types Configuration for a single module
- Multi
Yaml Aggregator - Re-export key aggregator types Re-export key aggregator types Multi-YAML aggregation system for compile-time command processing
- Namespace
- Represents a namespace within the command system.
- Namespace
Isolation - Re-export key aggregator types Re-export key aggregator types Namespace isolation configuration
- Namespace
Type - A validated namespace that guarantees correct naming conventions.
- NotSet
- Marker type indicating a required field has not been set.
- Output
Data - Represents the output of a successfully executed command.
- Performance
Metrics - Performance metrics for command registry operations.
- Pipeline
- A high-level pipeline processor that combines parsing, semantic analysis, and execution.
- SIMD
Json Parser - High-performance JSON parser using SIMD optimizations.
- SIMD
Tokenizer - SIMD-optimized tokenizer for splitting strings by delimiters. SIMD-optimized tokenizer for splitting strings by delimiters.
- Semantic
Analyzer - The semantic analyzer, responsible for validating the parsed program.
- Set
- Marker type indicating a required field has been set.
- Static
Argument Attributes - Static, const-compatible version of
ArgumentAttributes. - Static
Argument Definition - Static, const-compatible version of
ArgumentDefinition. - Static
Command Definition - Static, const-compatible version of
CommandDefinition. - Static
Command Map - Wrapper for static command maps with zero-overhead compile-time lookup.
- Static
Command Registry - High-performance static command registry with zero-cost compile-time lookup. High-performance static command registry with zero-cost compile-time lookup. High-performance static command registry with zero-cost compile-time lookup.
- Static
Module - Re-export key builder types Re-export key builder types Static module configuration for ergonomic APIs
- String
Interner - Thread-safe string interner that caches strings and returns ’static references.
- Type
Error - An error that can occur during type parsing or validation.
- Verified
Command - Represents a command that has been verified against the command registry.
- Version
Type - A validated version string.
Enums§
- Aggregation
Mode - Re-export key builder types Re-export key builder types Ergonomic CLI aggregation modes
- Command
Status - Command status indicating lifecycle stage and availability.
- Conflict
Resolution Strategy - Re-export key aggregator types Re-export key aggregator types Conflict resolution strategies for handling duplicate commands
- Conflict
Type - Re-export key aggregator types Re-export key aggregator types Types of conflicts that can be detected
- Error
- The main error type for the Unilang framework.
- Error
Code - Standard error codes for command execution failures
- Help
Verbosity - Help verbosity levels controlling output detail.
- Kind
- Represents the data type and structure of an argument or value.
- Module
Source - Re-export key builder types Re-export key builder types Module source type for aggregation
- Registry
Mode - Registry operation mode for hybrid command lookup optimization
- Static
Kind - Static, const-compatible version of Kind.
- Static
Validation Rule - Static, const-compatible version of
ValidationRule. - Unilang
Error - Structured error types for better API consistency and error handling.
- Validation
Rule - Validation rule for argument values.
- Value
- Represents a parsed and validated value of a specific kind.
Traits§
- Command
Registry Trait - Common trait for command registries to enable interoperability.
Functions§
- aggregate_
cli_ complex - Re-export key aggregator types Re-export key aggregator types More complex aggregate_cli simulation
- aggregate_
cli_ simple - Re-export key aggregator types Re-export key aggregator types Convenience function for zero-boilerplate static aggregation (aggregate_cli! macro simulation)
- compute_
full_ name_ core - Computes full command name from namespace and name.
- create_
aggregated_ registry - Re-export key aggregator types Re-export key aggregator types Runtime multi-YAML aggregation with environment variable support.
- extract_
bool - Extract
boolvalue from config. - extract_
f64 - Extract
f64value from config. - extract_
i32 - Extract
i32value from config. - extract_
i64 - Extract
i64value from config. - extract_
string - Extract
Stringvalue from config. - extract_
string_ array - Extract array of strings from config.
- extract_
u8 - Extract
u8value from config. - extract_
u16 - Extract
u16value from config. - extract_
u32 - Extract
u32value from config. - extract_
u64 - Extract
u64value from config. - global_
interner - Returns a reference to the global string interner instance.
- intern
- Convenience function to intern a string using the global interner.
- intern_
command_ name - Convenience function to intern command names using the global interner.
- is_
help_ command - Checks if command name ends with “.help” suffix.
- is_
simd_ enabled - Returns true if SIMD optimizations are available and enabled. Returns true if SIMD optimizations are available and enabled.
- load_
command_ definitions_ from_ json_ str - Loads command definitions from a JSON string.
- load_
command_ definitions_ from_ yaml_ str - Loads command definitions from a YAML string.
- make_
help_ command_ name - Builds help command name from command name.
- parse_
cargo_ metadata - Re-export key aggregator types Re-export key aggregator types Parse Cargo.toml metadata for build configuration
- parse_
value - Parses a raw string input into a
Valuebased on the specifiedKind. - process_
single_ command - Convenience function to process a single command with a registry.
- resolve_
routine_ link - Resolves a routine link string to a
CommandRoutine. - simd_
support_ info - CPU feature detection for SIMD optimization selection. CPU feature detection for SIMD optimization selection.
- validate_
command_ definition_ core - Validates a complete command definition at build time.
- validate_
command_ for_ registration - Validates entire command definition for registration.
- validate_
command_ name - Validates command name follows dot-prefix naming convention.
- validate_
command_ name_ core - Validates command name follows dot-prefix naming convention.
- validate_
full_ name_ core - Validates the full name (namespace + name combination).
- validate_
namespace - Validates namespace follows dot-prefix naming convention.
- validate_
namespace_ core - Validates namespace follows dot-prefix naming convention.
- validate_
parameter_ storage_ types - Validates parameter storage types match their multiple attribute.
- validate_
single_ command - Convenience function to validate a single command with a registry.
- validate_
version_ core - Validates version string is non-empty.
Type Aliases§
- Command
Routine - Type alias for a command routine.
A routine takes a
VerifiedCommandand anExecutionContext, and returns aResultofOutputDataorErrorData. - Config
Map - Type alias for configuration maps with any source type.