A comprehensive CLI tool discovery and automation framework that extracts structured information from command help text. Transform any CLI tool's help output into machine-readable data for automation, scripting, documentation generation, and IDE integration.
- Structured Parsing: Extracts options, arguments, subcommands, and usage patterns from help text
- Multi-Format Support: Handles various help text formats (clap, GNU, custom)
- Recursive Discovery: Automatically discovers nested subcommands and builds complete command trees
- Smart Caching: Caches probe results for performance with automatic version detection
- Automatic Help Flag Detection: Intelligently tries common help flags (
--help,-h,help, etc.) when none are provided
- Enhanced Options: Extracts option types (boolean, string, number, choice), defaults, and descriptions
- Argument Analysis: Identifies required/optional arguments, types (path, URL, email, number), and variadic patterns
- Environment Variables: Discovers environment variable mappings and defaults
- Validation Rules: Extracts validation constraints (ranges, patterns, choices)
- Examples: Parses example commands from help text
- Shell Completion: Generate completion scripts for Bash, Zsh, Fish, PowerShell, and NuShell
- Command Builders: Generate type-safe command builder code in Rust, Python, JavaScript, and TypeScript
- API Documentation: Generate documentation in Markdown, HTML, OpenAPI, and JSON Schema formats
- Command Validation: Validate command invocations against discovered specifications
- Type Checking: Verify argument types and option values
- Error Detection: Identify missing required options/arguments, unknown flags, and type mismatches
git clone <repository-url>
cd helpprobe
cargo build --releaseThe binary will be available at target/release/helpprobe.
cargo install --path .Probe a command's help text. The program automatically detects and uses appropriate help flags:
helpprobe -- ls
helpprobe -- docker
helpprobe -- git
helpprobe -- cargoYou can also explicitly provide help flags:
helpprobe -- ls --help
helpprobe -- docker -hGet structured JSON output:
helpprobe --json -- ls --helpGenerate completion scripts that enable tab completion for commands in your shell. These scripts provide intelligent suggestions when you press Tab, showing available options, subcommands, and arguments.
What are completion scripts?
- They are shell-specific scripts (
.shfor bash,.ps1for PowerShell,.nufor NuShell, etc.) that tell your shell how to complete commands - When you type a command and press Tab, the script suggests valid completions (options, subcommands, arguments)
- Each shell (bash, zsh, fish, etc.) has its own format
Example: After loading a completion script for docker, typing docker <TAB> will show all available subcommands (build, run, ps, etc.), and docker run --<TAB> will show all available options.
How to use them:
- Generate the script:
helpprobe --generate-completion <shell> --output <file> -- <command> - Load it:
- Temporary (current session only):
source <file>(bash/zsh) or. <file>(PowerShell) - Permanent (all future sessions): Add it to your shell's configuration file (see examples below)
- Temporary (current session only):
- Test: Type the command and press Tab to see completions
The --output flag is recommended (works in all shells, prompts if file exists):
# Bash
# Step 1: Generate the completion script (creates docker-completion.sh)
helpprobe --generate-completion bash --output docker-completion.sh -- docker
# Step 2: Load it in your current session (enables tab completion)
source docker-completion.sh
# Step 3: Test it - type "docker <TAB>" to see subcommands, or "docker run --<TAB>" for options
# To make it permanent, add to ~/.bashrc:
# echo "source $(pwd)/docker-completion.sh" >> ~/.bashrc
# Zsh
helpprobe --generate-completion zsh --output _cargo -- cargo
# Add to fpath: mv _cargo ~/.zsh/completions/ && echo 'fpath=(~/.zsh/completions $fpath)' >> ~/.zshrc
# Then reload: source ~/.zshrc
# Fish
helpprobe --generate-completion fish --output ~/.config/fish/completions/git.fish -- git
# Fish automatically loads completions from ~/.config/fish/completions/
# PowerShell
helpprobe --generate-completion powershell --output podman-completion.ps1 -- podman
# Load in current session: . .\podman-completion.ps1
# Or add to PowerShell profile for persistence: Add-Content $PROFILE ". .\podman-completion.ps1"
# NuShell
helpprobe --generate-completion nushell --output ~/.config/nushell/cargo-completion.nu -- cargo
# Add to config.nu: echo 'source ~/.config/nushell/cargo-completion.nu' >> ~/.config/nushell/config.nuNote: Instead of --output, you can use shell redirection: helpprobe --generate-completion bash -- docker > docker-completion.sh (in NuShell, use | save instead of >).
### Generate Command Builders
Generate type-safe command builder code that provides a fluent API for programmatically constructing CLI commands:
```bash
# Rust
helpprobe --generate-builder rust --output docker_builder.rs -- docker
# Python
helpprobe --generate-builder python --output git_builder.py -- git
# JavaScript/TypeScript
helpprobe --generate-builder typescript --output cargo_builder.ts -- cargo
Use Case Example:
Instead of manually constructing command strings, use the generated builder for type-safe, IDE-autocompleted command construction:
# Before: Manual command construction (error-prone, no autocomplete)
import subprocess
subprocess.run(["docker", "run", "-d", "--name", "myapp", "-p", "8080:80", "nginx"])
# After: Using generated builder (type-safe, autocompleted)
from docker_builder import DockerBuilder
# Fluent API with autocomplete and type safety
result = DockerBuilder() \
.run() \
.detach() \
.name("myapp") \
.publish("8080:80") \
.image("nginx") \
.execute()
print(result.stdout)// Rust example
use docker_builder::DockerBuilder;
let output = DockerBuilder::new()
.run()
.detach()
.name("myapp")
.publish("8080:80")
.image("nginx")
.execute()?;This is especially useful for:
- Automation scripts - Build commands programmatically from configuration
- Testing - Construct test commands with compile-time safety
- Wrappers - Create higher-level APIs around CLI tools
- Configuration management - Generate commands from config files
Generate API documentation in various formats:
# Markdown
helpprobe --generate-api-docs markdown -- docker --help > docker.md
# HTML
helpprobe --generate-api-docs html -- git --help > git.html
# OpenAPI 3.0
helpprobe --generate-api-docs openapi -- cargo --help > cargo-openapi.json
# JSON Schema
helpprobe --generate-api-docs jsonschema -- kubectl --help > kubectl-schema.jsonValidate command invocations:
helpprobe --validate -- docker run --image nginx
helpprobe --validate -- git commit --message "test"Discover all subcommands recursively:
helpprobe --discover-all -- docker --help
helpprobe --discover-all --max-depth 3 -- git --helpCache is enabled by default. Control caching behavior:
# Disable cache
helpprobe --no-cache -- ls --help
# Clear cache for a command
helpprobe --clear-cache -- ls --help
# Use custom cache directory
helpprobe --cache-dir /tmp/my-cache -- docker --helpUse helpprobe as a library in your Rust projects. Add it to your Cargo.toml:
[dependencies]
helpprobe = "0.1.0"
tokio = { version = "1", features = ["full"] }
anyhow = "1.0"use helpprobe::{probe_command, ProbeConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Use default configuration
let config = ProbeConfig::default();
// Probe a command (help flag is automatically detected if missing)
let result = probe_command("ls", &[], &config).await?;
println!("Found {} options", result.options.len());
println!("Found {} subcommands", result.subcommands.len());
println!("Found {} arguments", result.arguments.len());
// Access parsed data
for option in &result.options {
println!("Option: {:?}", option.long_flags);
}
Ok(())
}use helpprobe::{probe_command, ProbeConfig, CacheConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ProbeConfig {
timeout_secs: 10,
require_help_flag: false,
cache: Some(CacheConfig {
cache_dir: helpprobe::cache::default_cache_dir(),
enabled: true,
max_age_secs: Some(86400 * 7), // 7 days
}),
};
let result = probe_command("docker", &["--help".to_string()], &config).await?;
// Subsequent calls will use cached results
Ok(())
}use helpprobe::{probe_command, generate_shell_completion, Shell, ProbeConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ProbeConfig::default();
let result = probe_command("git", &[], &config).await?;
// Generate Bash completion script
let bash_completion = generate_shell_completion(&result, Shell::Bash);
println!("{}", bash_completion);
// Generate Zsh completion script
let zsh_completion = generate_shell_completion(&result, Shell::Zsh);
println!("{}", zsh_completion);
Ok(())
}use helpprobe::{probe_command, generate_command_builder, Language, ProbeConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ProbeConfig::default();
let result = probe_command("docker", &[], &config).await?;
// Generate Rust builder code
let rust_builder = generate_command_builder(&result, Language::Rust);
println!("{}", rust_builder);
// Generate Python builder code
let python_builder = generate_command_builder(&result, Language::Python);
println!("{}", python_builder);
Ok(())
}use helpprobe::{probe_command, validate_command, ProbeConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ProbeConfig::default();
let result = probe_command("docker", &[], &config).await?;
// Validate a command invocation
let validation = validate_command(
&result,
"docker",
&["run", "--image", "nginx", "--port", "8080"]
);
if validation.is_valid {
println!("Command is valid!");
} else {
println!("Validation errors:");
for error in &validation.errors {
println!(" - {}: {}", error.error_type, error.message);
}
}
Ok(())
}use helpprobe::{discover_all_subcommands, ProbeConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ProbeConfig::default();
// Recursively discover all subcommands
let tree = discover_all_subcommands("git", &config, Some(3)).await?;
println!("Command: {}", tree.command);
println!("Total commands: {}", tree.total_commands);
println!("Root options: {}", tree.options.len());
// Traverse subcommand hierarchy
fn print_subcommands(subcommands: &[helpprobe::SubcommandSpec], depth: usize) {
for subcmd in subcommands {
let indent = " ".repeat(depth);
println!("{}{} - {}", indent, subcmd.full_path,
subcmd.description.as_deref().unwrap_or(""));
print_subcommands(&subcmd.subcommands, depth + 1);
}
}
print_subcommands(&tree.subcommands, 0);
Ok(())
}use helpprobe::{probe_command, generate_api_docs, DocFormat, ProbeConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = ProbeConfig::default();
let result = probe_command("kubectl", &[], &config).await?;
// Generate Markdown documentation
let markdown = generate_api_docs(&result, DocFormat::Markdown);
println!("{}", markdown);
// Generate OpenAPI specification
let openapi = generate_api_docs(&result, DocFormat::OpenAPI);
println!("{}", openapi);
Ok(())
}Commonly used types are re-exported at the crate root for convenience:
- Core API:
probe_command,discover_all_subcommands,discover_subcommand_hierarchy,ProbeConfig - Models:
ProbeResult,OptionSpec,ArgumentSpec,SubcommandSpec,CommandTree,OptionType,ArgumentType - Completion:
generate_shell_completion,Shell - Builder:
generate_command_builder,Language - API Docs:
generate_api_docs,DocFormat - Validation:
validate_command,ValidationResult,ValidationError,ValidationErrorType - Cache:
CacheConfig,read_cache,write_cache,clear_cache
Additional modules available:
helpprobe::parser- Lower-level parsing functions for help texthelpprobe::runner- Command execution utilities
USAGE:
helpprobe [OPTIONS] -- <COMMAND> [ARGS...]
OPTIONS:
--cache-dir <DIR> Cache directory path (default: ~/.cache/helpprobe)
--clear-cache Clear cache for the specified command
--discover-all Recursively discover all subcommands
--force Run command even when no help flag is present
--generate-api-docs <FORMAT> Generate API documentation (markdown, html, openapi, jsonschema)
--generate-builder <LANGUAGE> Generate command builder code (rust, python, javascript, typescript)
--generate-completion <SHELL> Generate shell completion script (bash, zsh, fish, powershell, nushell)
--output <FILE> Output file for completion/builder/docs (prompts if exists, use --force to skip)
--json Emit JSON instead of human-readable text
--max-depth <DEPTH> Maximum depth for recursive discovery (default: 5)
--no-cache Disable caching of probe results
--timeout-secs <SECS> Timeout in seconds for the target command (default: 3)
--validate Validate a command invocation
--verbose Show raw stdout/stderr from the command
-h, --help Print help information
-V, --version Print version information
The JSON output includes:
- Command Information: Command name, arguments, exit code
- Options: Short/long flags, descriptions, types, defaults, choices
- Arguments: Names, types, required/optional, variadic, descriptions
- Subcommands: Names, descriptions, full paths, parent relationships
- Environment Variables: Names, descriptions, option mappings, defaults
- Validation Rules: Types, patterns, ranges, messages
- Examples: Command examples with descriptions and tags
- Raw Output: Original stdout/stderr for reference
Generate completion scripts for any CLI tool automatically.
Provide autocomplete and validation for CLI commands in IDEs.
Validate command invocations before execution in test suites.
Auto-generate up-to-date documentation from help text.
Create type-safe wrappers around CLI tools.
Discover environment variables and generate config templates.
Validate and construct commands programmatically in automation scripts.
helpprobe --generate-completion bash -- docker --help > /etc/bash_completion.d/dockerif helpprobe --validate -- docker run --invalid-flag; then
echo "Command is valid"
else
echo "Command has errors"
exit 1
fihelpprobe --generate-builder python -- git --help > git_builder.py
# Then use it:
python -c "
from git_builder import GitBuilder
cmd = GitBuilder().add().file('test.txt').build()
print(cmd)
"helpprobe --discover-all --json -- docker --help | jq '.total_commands'See CHANGELOG.md for a detailed list of changes, new features, and bug fixes.
If you're developing a CLI tool and want to ensure optimal compatibility with helpprobe, see HELP_PROBE_SPEC.md for guidelines on formatting help output. This specification covers:
- Usage line formatting
- Options and flags formatting
- Subcommands formatting
- Arguments formatting
- Section headers and organization
- Best practices for maximum discoverability
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please make sure to:
- Add tests for new features
- Update documentation as needed
- Follow existing code style
- Run
cargo fmtandcargo clippybefore submitting
This project is dual-licensed under:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
You may choose either license for your use. This dual-licensing approach is common in the Rust ecosystem and provides maximum flexibility for users and contributors.
Built with Rust for performance and reliability. Uses heuristic parsing to handle the wide variety of help text formats in the wild.