{
  "id": "rust-cli",
  "name": "Rust CLI/TUI: clap + Ratatui + dist",
  "use_cases": [
    "Fast native developer tools",
    "parsers and analyzers",
    "shipped terminal applications"
  ],
  "choose_when": [
    "Need native performance or reuse of Rust libraries",
    "Want ownership/type checks around complex transformations"
  ],
  "avoid_when": [
    "Disposable automation would be simpler in Python or shell",
    "Build latency and cross-toolchains outweigh runtime needs"
  ],
  "tools": [
    {
      "job": "Command parsing",
      "default": "clap",
      "alternatives": [
        "A simple std::env argument parser for tiny internal tools"
      ],
      "reason": "Typed commands plus a mature terminal widget/rendering ecosystem.",
      "limits": "Keep domain code separate from rendering and support non-TTY output; restore terminal on errors and interruption.",
      "source_urls": [
        "https://docs.rs/clap/latest/clap/",
        "https://ratatui.rs/"
      ]
    },
    {
      "job": "Terminal UI",
      "default": "Ratatui only for interactive screens",
      "alternatives": [
        "Line-oriented output when no interactive screen is needed"
      ],
      "reason": "Typed commands plus a mature terminal widget/rendering ecosystem.",
      "limits": "Keep domain code separate from rendering and support non-TTY output; restore terminal on errors and interruption.",
      "source_urls": [
        "https://docs.rs/clap/latest/clap/",
        "https://ratatui.rs/"
      ]
    },
    {
      "job": "HTTP client",
      "default": "reqwest",
      "alternatives": [
        "No network dependency for offline tools"
      ],
      "reason": "Reusable typed HTTP client APIs.",
      "limits": "Choose blocking or async deliberately; configure timeouts, TLS and response bounds. Never call blocking client inside an async runtime indiscriminately.",
      "source_urls": [
        "https://docs.rs/reqwest/latest/reqwest/"
      ]
    },
    {
      "job": "Persistence and migrations",
      "default": "None for stateless tools",
      "alternatives": [
        "SQLx with SQLite when local relational state is a real requirement"
      ],
      "reason": "Start without a database; add schema ownership only for persistent products.",
      "limits": "SQLite feature/driver and migration setup require target testing; durable local state is not shared distributed workflow state.",
      "source_urls": [
        "https://docs.rs/sqlx/latest/sqlx/",
        "https://github.com/transact-rs/sqlx/blob/main/sqlx-cli/README.md"
      ]
    },
    {
      "job": "Configuration",
      "default": "Serde-backed settings + config",
      "alternatives": [
        "std::env for a small fixed settings set"
      ],
      "reason": "Typed settings plus structured events/spans.",
      "limits": "Set precedence explicitly; validate semantics; install a tracing subscriber; never log secrets.",
      "source_urls": [
        "https://docs.rs/config/latest/config/",
        "https://doc.rust-lang.org/std/env/fn.var.html",
        "https://docs.rs/tracing/latest/tracing/"
      ]
    },
    {
      "job": "Application logging",
      "default": "tracing + configured subscriber",
      "alternatives": [],
      "reason": "Typed settings plus structured events/spans.",
      "limits": "Set precedence explicitly; validate semantics; install a tracing subscriber; never log secrets.",
      "source_urls": [
        "https://docs.rs/config/latest/config/",
        "https://doc.rust-lang.org/std/env/fn.var.html",
        "https://docs.rs/tracing/latest/tracing/"
      ]
    },
    {
      "job": "Tests and static checks",
      "default": "cargo test; rustfmt; Clippy; cargo audit",
      "alternatives": [],
      "reason": "Compiler, style, behavior and known-advisory checks complement each other.",
      "limits": "Audit coverage is advisory-driven; compile success does not establish behavior or security. Test supported feature combinations rather than blindly enabling incompatible features.",
      "source_urls": [
        "https://doc.rust-lang.org/cargo/commands/cargo-test.html",
        "https://github.com/rust-lang/rustfmt",
        "https://doc.rust-lang.org/clippy/usage.html",
        "https://rustsec.org/",
        "https://docs.rs/assert_cmd/latest/assert_cmd/"
      ]
    },
    {
      "job": "Executable behavior tests",
      "default": "assert_cmd",
      "alternatives": [
        "clap-linked snapshot tools for stable help output"
      ],
      "reason": "Tests real exit codes, stdout/stderr and command contracts.",
      "limits": "Snapshot changes need review; also test actual error and side-effect behavior.",
      "source_urls": [
        "https://docs.rs/assert_cmd/latest/assert_cmd/",
        "https://docs.rs/clap/latest/clap/"
      ]
    },
    {
      "job": "Durable work",
      "default": "Delegate to a durable service; retain resumable job identity",
      "alternatives": [
        "Local checkpoints for explicitly local resumable work"
      ],
      "reason": "CLI lifetime does not own remote work lifetime.",
      "limits": "Checkpoint schema, atomic persistence and external idempotency must be designed; async execution alone adds no durability.",
      "source_urls": [
        "https://docs.rs/restate-sdk/latest/restate_sdk/"
      ]
    },
    {
      "job": "Distribution",
      "default": "dist (formerly cargo-dist) + Cargo release builds",
      "alternatives": [
        "Manual artifacts for one internal target"
      ],
      "reason": "Generates multi-platform release pipelines and installers.",
      "limits": "Review generated CI before tags can publish; test installers and target-native dependencies. Signing and notarization are separate platform work.",
      "source_urls": [
        "https://github.com/axodotdev/cargo-dist",
        "https://doc.rust-lang.org/cargo/commands/cargo-build.html"
      ]
    },
    {
      "job": "Machine-readable output",
      "default": "serde_json",
      "alternatives": [
        "Preserve an existing compatible project choice"
      ],
      "reason": "Stable JSON output lets scripts consume commands without parsing terminal text",
      "limits": "Add an explicit --json/output mode and document schema/exit codes; reserve stdout for results, stderr for diagnostics, and disable interactive/color output for pipelines.",
      "source_urls": [
        "https://docs.rs/serde_json/latest/serde_json/"
      ]
    },
    {
      "job": "Cancellation and shutdown",
      "default": "Tokio signal handling for async commands",
      "alternatives": [
        "Existing synchronous shutdown strategy in synchronous Rust tools"
      ],
      "reason": "User interrupts should cancel outbound work and leave terminal/files usable",
      "limits": "Propagate cancellation through work; bound cleanup time and test interrupts during writes. Avoid adding an async runtime to a synchronous Rust CLI solely for signals.",
      "source_urls": [
        "https://docs.rs/tokio/latest/tokio/signal/index.html"
      ]
    }
  ],
  "setup_steps": [
    "Create source in a local development workspace with cargo new tool; enter tool; run cargo add clap --features derive.",
    "Resolve Ratatui and its supported terminal backend only if interactive rendering is required; add reqwest only if network access is needed.",
    "Implement typed commands, injected/configured settings, stable output/exit codes and domain logic independent of terminal rendering.",
    "Add tests with cargo add --dev assert_cmd; cover missing files, invalid input, stdin, cancellation, stdout/stderr and terminal cleanup.",
    "Install a selected dist release and run dist init; review target list and generated CI. Lock dependencies/toolchain; no release tags or publication were executed."
  ],
  "verification_commands": [
    "cargo fmt --all -- --check",
    "cargo clippy --workspace --all-targets --locked -- -D warnings",
    "cargo test --workspace --locked",
    "cargo audit",
    "cargo build --release --locked"
  ],
  "evidence_status": "documentation-reviewed",
  "sources": [
    {
      "url": "https://docs.rs/clap/latest/clap/",
      "title": "clap",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://ratatui.rs/",
      "title": "Ratatui",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/reqwest/latest/reqwest/",
      "title": "reqwest",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/sqlx/latest/sqlx/",
      "title": "SQLx",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://github.com/transact-rs/sqlx/blob/main/sqlx-cli/README.md",
      "title": "SQLx CLI",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/config/latest/config/",
      "title": "Rust config crate",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://doc.rust-lang.org/std/env/fn.var.html",
      "title": "Rust environment variables",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/tracing/latest/tracing/",
      "title": "Rust tracing",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://doc.rust-lang.org/cargo/commands/cargo-test.html",
      "title": "Cargo test",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://github.com/rust-lang/rustfmt",
      "title": "rustfmt",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://doc.rust-lang.org/clippy/usage.html",
      "title": "Clippy usage",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://rustsec.org/",
      "title": "RustSec",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/assert_cmd/latest/assert_cmd/",
      "title": "assert_cmd",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/restate-sdk/latest/restate_sdk/",
      "title": "Restate Rust SDK",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://github.com/axodotdev/cargo-dist",
      "title": "dist binary distribution",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://doc.rust-lang.org/cargo/commands/cargo-build.html",
      "title": "Cargo build",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/serde_json/latest/serde_json/",
      "title": "Rust JSON API",
      "checked_date": "2026-10-10"
    },
    {
      "url": "https://docs.rs/tokio/latest/tokio/signal/index.html",
      "title": "Rust signal API",
      "checked_date": "2026-10-10"
    }
  ],
  "open_questions": [
    "Which terminals, non-TTY consumers and OS/architectures must be supported?",
    "What output schema, cancellation and configuration precedence will consumers rely on?",
    "Which native dependencies, signing/notarization and update channels are required?"
  ],
  "title": "Rust CLI + TUI",
  "language": "Rust",
  "group": "Tools & automation",
  "kind": [
    "cli"
  ],
  "ui": "terminal",
  "host": "binary",
  "summary": "Portable command-line tools with explicit memory and resource control.",
  "shape": "Clap · Ratatui when needed · Cargo",
  "tradeoff": "Cross-compilation and native dependencies still need target-specific qualification.",
  "research_file": "go-rust.json",
  "reviewed": "2026-10-10",
  "best_practices": [
    "Keep parsing separate from domain behavior. Test malformed input, pipes, errors and exit codes.",
    "Use interactive UI only when a terminal is available and the user has requested it.",
    "Bound resource use and retain error context rather than panicking on expected failures.",
    "Build with the committed lockfile and verify each supported release target."
  ],
  "research_freshness": {
    "core_guidance_checked_on": "2026-10-13",
    "sources": [
      "https://docs.rs/clap/latest/clap/",
      "https://ratatui.rs/"
    ],
    "scope": "Core framework roles, current setup/agent documentation and cited-source availability rechecked; not a reimplementation or exhaustive semantic audit of every third-party dependency."
  },
  "guide_url": "/stacks/rust-cli/",
  "markdown_url": "/stacks/rust-cli/guide.md",
  "json_url": "/stacks/rust-cli/record.json",
  "architecture_and_migration": {
    "id": "rust-cli",
    "version_scope": "Reviewed clap 4.6.7 and Rust std 1.99.0 documentation; Serde, Ratatui and current axodotdev cargo-dist book. Pin rust-toolchain.toml/Cargo.lock and dist version/config. The older opensource.axo.dev book path failed; no target install or release workflow was executed.",
    "operating_model": "Recommendation: clap derives/parses a stable command interface, domain operations return Result, and the entry point converts errors to streams/status after cleanup. Serde owns a versioned machine format; Ratatui is an optional terminal client. Cargo/dist prepare artifacts for explicitly supported targets and update channels.",
    "architecture": [
      "Recommendation: use a library crate or modules for application operations and a thin binary adapter. Keep clap parsing errors separate from business errors; prefer explicit main ExitCode mapping when the contract requires more than generic failure.",
      "Recommendation: Serde input/output types carry schema versions. Separate strict user configuration from forward-compatible result reading; deny_unknown_fields is an intentional policy, not universal compatibility.",
      "Recommendation: encapsulate raw-mode/alternate-screen lifetime and restore the terminal on errors and panics. Share domain operations between Ratatui and a noninteractive JSON mode; interactive render state is not durable application state.",
      "Recommendation: bounded Rayon/Tokio work is selected by CPU versus I/O needs, with explicit cancellation and effect receipts. A compiled binary reduces interpreter deployment needs but does not remove database, TLS or platform dependencies."
    ],
    "developer_workflow": [
      "Recommendation: start from existing Cargo manifest, consumers and rust-toolchain.toml. For a new local package, cargo new tool and cargo add clap --features derive are optional initial steps; add serde --features derive and serde_json only when a machine/config format is required.",
      "Recommendation: cargo fmt --check, cargo clippy --all-targets -- -D warnings and cargo test --locked verify source checks in the selected feature matrix. Exercise subprocess stdout/stderr/status and panic/interrupt terminal restoration on supported OSs.",
      "Recommendation: cargo build --release --locked builds one selected target. Inspect its native/TLS dependencies and execute on clean target hosts; --target compilation alone does not qualify distribution.",
      "Recommendation: with a pinned dist tool, run dist init and review generated configuration/workflows before committing; init can overwrite manual workflow edits. dist plan --output-format=json previews artifact/announcement intent; actual target builds, installers and upgrade/downgrade checks remain required."
    ],
    "avoid": [
      "Avoid treating debug-formatted Result errors as a stable machine API; define error codes and schema deliberately.",
      "Avoid process::exit in cleanup-sensitive paths; terminal restoration and destructors need normal control flow.",
      "Avoid enabling raw terminal mode for piped/noninteractive invocations; they need predictable streams and no prompts.",
      "Avoid hand-editing generated dist workflows without recording how customization survives regeneration."
    ],
    "transitions": [
      {
        "capability": "cli",
        "existing_contract": "Record current commands, option defaults, exit codes, stdout/stderr, JSON field names and shell completions consumed by callers.",
        "coexistence": "Recommendation: keep an old command adapter and explicit schema version while migrating parsing to clap. Preserve old names/aliases and map new domain errors into the established protocol.",
        "target": "Recommendation: clap plus typed result/error JSON and main ExitCode mapping. clap usage failures use status 2 while help/version uses success; application failures need their own documented policy.",
        "benefits": [
          {
            "benefit": "Typed parsing and a stable output envelope make command automation explicit.",
            "prerequisites": "Contract fixtures cover old callers; result schemas and error/status mapping are versioned; help/completion behavior is checked.",
            "tradeoffs": "Parser defaults can change compatibility; numeric status meanings are not universal across platforms; Rust error types do not define the public protocol."
          }
        ],
        "checks": [
          "Verify help/version succeed and invalid arguments use the intended stream/code without effects.",
          "Execute legacy scripts and compare stdout/stderr/status exactly where promised.",
          "Validate empty, partial and failed JSON results against the advertised schema."
        ],
        "rollback": "Recommendation: return consumers to the previous binary/schema while retaining old option adapters. Keep version selection explicit so a rollback does not silently alter JSON meaning.",
        "sources": [
          "https://docs.rs/clap/latest/clap/",
          "https://docs.rs/clap/latest/clap/error/struct.Error.html",
          "https://doc.rust-lang.org/std/process/struct.ExitCode.html"
        ],
        "id": "cli-1"
      },
      {
        "capability": "data",
        "existing_contract": "Inventory configuration file locations, schema versions, defaults, permissions and old binaries' ability to read newer files.",
        "coexistence": "Recommendation: read old config into a versioned internal model and migrate only through an explicit command with backup. Keep concurrent writer ownership explicit; read-only startup must not silently rewrite files.",
        "target": "Recommendation: Serde-tagged/versioned configuration and documented unknown-field handling. Validate a temporary representation before replacing the live file; platform atomicity, permissions and crash behavior require implementation checks.",
        "benefits": [
          {
            "benefit": "Explicit config migration decouples executable upgrades from accidental data loss.",
            "prerequisites": "Old/new fixtures and semantic transforms exist; backup/restore works; unsupported versions fail before write.",
            "tradeoffs": "Strict Serde unknown-field rejection can prevent mixed-version use; deny_unknown_fields does not compose with flatten; replacing a file is not a complete durability protocol."
          }
        ],
        "checks": [
          "Load old config and compare effective settings after migration.",
          "Verify unsupported versions and malformed values leave the source unchanged.",
          "Downgrade the binary with its preserved config and confirm paths/permissions on each target OS."
        ],
        "rollback": "Recommendation: restore the preserved old config and binary as a pair. Reconcile new-only fields before using an old reader; avoid destructive in-place downgrade guesses.",
        "sources": [
          "https://serde.rs/container-attrs.html"
        ],
        "id": "data-1"
      },
      {
        "capability": "jobs",
        "existing_contract": "Preserve ordering, per-item effects, timeout and interrupt semantics for batch/network subcommands.",
        "coexistence": "Recommendation: retain sequential mode while qualifying bounded parallel work using dry-run/fixtures. Store item operation IDs and completion receipts before enabling resume against live systems.",
        "target": "Recommendation: a bounded executor selected for CPU or async I/O with cooperative stop, tracked joins and cleanup. Started blocking work needs its own stop protocol or process boundary; do not label a task timeout as effect cancellation.",
        "benefits": [
          {
            "benefit": "Bounded parallel execution can overlap independent work without unlimited task creation.",
            "prerequisites": "Independent item semantics; capacity/budget limits; stable effect IDs; tested cancellation and resume contract.",
            "tradeoffs": "Speed is unmeasured; running blocking tasks may continue; a cancelled remote write can have an ambiguous outcome."
          }
        ],
        "checks": [
          "Interrupt a batch and verify no new items start, joins are bounded and terminal state restores.",
          "Simulate a remote success with a lost acknowledgement; resume reconciles rather than duplicating the effect.",
          "Verify CPU tasks cannot starve I/O and the executor respects the declared capacity."
        ],
        "rollback": "Recommendation: use sequential mode with the same receipt format and reconcile unknown outcomes. A previous executable must be able to read checkpoint versions or an explicit converter is required.",
        "sources": [
          "https://tokio.rs/tokio/topics/shutdown",
          "https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html",
          "https://ratatui.rs/recipes/apps/panic-hooks/"
        ],
        "id": "jobs-1"
      },
      {
        "capability": "operations",
        "existing_contract": "Capture existing target triples, libc/native dependencies, install path, package metadata and update/downgrade contracts.",
        "coexistence": "Recommendation: prepare dist artifacts beside the previous release; review generated CI and installers, and use a prerelease or test channel for target qualification. Do not promise all platforms merely because dist generates a matrix.",
        "target": "Recommendation: pinned dist configuration and Cargo.lock with release artifacts/installers for exercised targets. Keep signing/attestation, system dependency baselines and update channel ownership explicit.",
        "benefits": [
          {
            "benefit": "Generated release plans coordinate binary artifacts and installers across targets.",
            "prerequisites": "dist version is pinned; generated workflow is reviewed; native dependencies and every advertised target are exercised.",
            "tradeoffs": "dist init may replace generated workflows; OS signing and Linux libc compatibility remain separate obligations; a plan is not build/publication evidence."
          }
        ],
        "checks": [
          "Inspect dist plan --output-format=json for expected target triples and artifact names.",
          "Install downloaded artifacts on clean target hosts, including the oldest promised Linux baseline.",
          "Exercise upgrade/downgrade, PATH behavior, checksum verification and preserved versioned config."
        ],
        "rollback": "Recommendation: restore the previous verified package/update channel and retain older installers/checksums. Review data/config compatibility before allowing downgrade; never change a public channel based only on a plan.",
        "sources": [
          "https://axodotdev.github.io/cargo-dist/book/workspaces/simple-guide.html",
          "https://axodotdev.github.io/cargo-dist/book/reference/config.html",
          "https://doc.rust-lang.org/cargo/commands/cargo-build.html"
        ],
        "id": "operations-1"
      }
    ],
    "sources": [
      {
        "url": "https://docs.rs/clap/latest/clap/",
        "title": "clap 4.6.7",
        "claim": "Parser/derive command definition supports a typed command boundary."
      },
      {
        "url": "https://docs.rs/clap/latest/clap/error/struct.Error.html",
        "title": "clap errors",
        "claim": "Usage errors generally print to stderr with code 2; help-like output uses stdout and success."
      },
      {
        "url": "https://doc.rust-lang.org/std/process/struct.ExitCode.html",
        "title": "Rust ExitCode",
        "claim": "ExitCode can be returned by main; arbitrary numeric code meanings are platform-specific."
      },
      {
        "url": "https://serde.rs/container-attrs.html",
        "title": "Serde container attributes",
        "claim": "deny_unknown_fields rejects unknown inputs and is incompatible with flatten; version policy is application-owned."
      },
      {
        "url": "https://ratatui.rs/recipes/apps/panic-hooks/",
        "title": "Ratatui panic hooks",
        "claim": "Terminal restoration must be arranged around error/panic paths."
      },
      {
        "url": "https://tokio.rs/tokio/topics/shutdown",
        "title": "Tokio shutdown",
        "claim": "Track/notify/await tasks for planned completion."
      },
      {
        "url": "https://docs.rs/tokio/latest/tokio/task/fn.spawn_blocking.html",
        "title": "Tokio blocking tasks",
        "claim": "Started blocking tasks cannot be aborted; capacity is a separate concern."
      },
      {
        "url": "https://axodotdev.github.io/cargo-dist/book/workspaces/simple-guide.html",
        "title": "dist simple application guide",
        "claim": "init generates config/workflows, can overwrite manual edits, and plan previews artifacts."
      },
      {
        "url": "https://axodotdev.github.io/cargo-dist/book/reference/config.html",
        "title": "dist configuration reference",
        "claim": "Targets, installers and CI/download/update settings are configured explicitly."
      },
      {
        "url": "https://doc.rust-lang.org/cargo/commands/cargo-build.html",
        "title": "Cargo build",
        "claim": "Locked and target-specific builds have defined semantics; build success is not target execution."
      }
    ],
    "reviewed_at": "2026-10-11",
    "evidence": "documentation-reviewed"
  },
  "rewrite_url": "/rewrite/guide.md",
  "migration_contracts_url": "/rewrite/contracts.json",
  "agent_workflow": [
    "Read README, dependency manifests, lockfiles, runtime pins and the maintained project workflow before changing anything. Preserve an existing stack unless reconsidering it is part of the request.",
    "Use this guide to select tools by requirement. Resolve compatible versions from official and installed-version documentation; record the actual lockfile and runtime versions.",
    "Create a plan for schema changes, identity, authorization, external effects and deployment. A library choice does not complete its integration.",
    "Run relevant checks after configuration. Exercise the real interface, failure paths and packaged artifact on the intended target. Report commands, versions, results and untested behavior.",
    "On failure, retain the command and diagnostic, fix the failing prerequisite and resume there. Do not regenerate over existing work or suppress failures to make a check green."
  ],
  "selection": {
    "native_ui": false,
    "static_hosting": false,
    "offline_client_candidate": false
  },
  "coverage_note": "Tools are curated starting points for this application role. Exact versions, integrations and offline behavior require project-specific qualification."
}
