domain-cli

Use when building CLI tools. Keywords: CLI, command line, terminal, clap, structopt, argument parsing, subcommand, interactive, TUI, ratatui, crossterm,…

INSTALLATION
npx skills add https://github.com/actionbook/rust-skills --skill domain-cli
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

CLI Domain

Layer 3: Domain Constraints

Domain Constraints → Design Implications

Domain RuleDesign ConstraintRust Implication
User ergonomicsClear help, errorsclap derive macros
Config precedenceCLI > env > fileLayered config loading
Exit codesNon-zero on errorProper Result handling
Stdout/stderrData vs errorseprintln! for errors
InterruptibleHandle Ctrl+CSignal handling

Critical Constraints

User Communication

RULE: Errors to stderr, data to stdout

WHY: Pipeable output, scriptability

RUST: eprintln! for errors, println! for data

Configuration Priority

RULE: CLI args > env vars > config file > defaults

WHY: User expectation, override capability

RUST: Layered config with clap + figment/config

Exit Codes

RULE: Return non-zero on any error

WHY: Script integration, automation

RUST: main() -> Result<(), Error> or explicit exit()

Trace Down ↓

From constraints to design (Layer 2):

"Need argument parsing"

    ↓ m05-type-driven: Derive structs for args

    ↓ clap: #[derive(Parser)]

"Need config layering"

    ↓ m09-domain: Config as domain object

    ↓ figment/config: Layer sources

"Need progress display"

    ↓ m12-lifecycle: Progress bar as RAII

    ↓ indicatif: ProgressBar

Key Crates

PurposeCrate
Argument parsingclap
Interactive promptsdialoguer
Progress barsindicatif
Colored outputcolored
Terminal UIratatui
Terminal controlcrossterm
Console utilitiesconsole

Design Patterns

PatternPurposeImplementation
Args structType-safe args#[derive(Parser)]
SubcommandsCommand hierarchy#[derive(Subcommand)]
Config layersOverride precedenceCLI > env > file
ProgressUser feedbackProgressBar::new(len)

Code Pattern: CLI Structure

use clap::{Parser, Subcommand};

#[derive(Parser)]

#[command(name = "myapp", about = "My CLI tool")]

struct Cli {

    /// Enable verbose output

    #[arg(short, long)]

    verbose: bool,

    #[command(subcommand)]

    command: Commands,

}

#[derive(Subcommand)]

enum Commands {

    /// Initialize a new project

    Init { name: String },

    /// Run the application

    Run {

        #[arg(short, long)]

        port: Option<u16>,

    },

}

fn main() -> anyhow::Result<()> {

    let cli = Cli::parse();

    match cli.command {

        Commands::Init { name } => init_project(&name)?,

        Commands::Run { port } => run_server(port.unwrap_or(8080))?,

    }

    Ok(())

}

Common Mistakes

MistakeDomain ViolationFix
Errors to stdoutBreaks pipingeprintln!
No help textPoor UX#[arg(help = "...")]
Panic on errorBad exit codeResult + proper handling
No progress for long opsUser uncertaintyindicatif

Trace to Layer 1

ConstraintLayer 2 PatternLayer 1 Implementation
Type-safe argsDerive macrosclap Parser
Error handlingResult propagationanyhow + exit codes
User feedbackProgress RAIIindicatif ProgressBar
Config precedenceBuilder patternLayered sources

Related Skills

WhenSee
Error handlingm06-error-handling
Type-driven argsm05-type-driven
Progress lifecyclem12-lifecycle
Async CLIm07-concurrency
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card