Opinionated starting point for building small and medium Rust command line applications.
This template exists to remove the repeated setup work for a new CLI project. It ships with:
figue+facetbased argument parsing using Teamy's published forks- top-level output rendering with
text,json, andcsvformats --helpand--versionsupport, including git repository URL, branch, revision, worktree status, and local-time build timestamp in version output- structured logging to stderr with optional NDJSON log files
- Windows app resources wired through
build.rs - CLI roundtrip fuzz tests
initscaffolding command for creating new Teamy Rust CLI repositories- PowerShell helpers for running the full quality gate and temporarily supporting the legacy initializer
- cancellation signals and linked execution scopes from
teamy-cancellation
Scaffold the template into another repository:
cargo run -- init ../my-new-cliThen update the obvious placeholders in the destination repository:
- package metadata in
Cargo.toml - environment variable names in
src/paths/mod.rs - repository URL in
src/lib.rs - README text and examples
The initializer creates the destination directory if needed, excludes .git,
target, the template initialization skill, and the legacy init-other-repo.ps1
script, and preserves an existing destination README.md or LICENSE.
Existing generated files are not overwritten unless --force is passed:
cargo run -- init ../my-existing-cli --forceFor transition, init-other-repo.ps1 remains in this repository as a
compatibility entrypoint, but new documentation and automation should use
teamy-rust-cli init.
Inspect the generated CLI surface:
cargo run -- --helpShow the resolved application home directory:
cargo run -- home showRender the same command as JSON:
cargo run -- --output-format json home showShow the resolved cache directory:
cargo run -- cache showWrite structured logs to disk while still logging to stderr:
cargo run -- --log-file .\logs home showCommands that return structured data render through a shared top-level output layer.
- Use
--output-format text,--output-format json, or--output-format csvto choose the format explicitly. - If
--output-formatis omitted, the CLI defaults totextin an interactive terminal andjsonwhen stdout is redirected. - Commands that only perform side effects, such as
openandclean, return no structured stdout payload.
JSON and text output stream to the writer under the invocation's cancellation scope. JSON also checks cancellation during traversal and scalar encoding. CSV currently buffers its rendered document, then uses bounded cancellation-aware writes. All formats check cancellation while writing and before flushing, keeping the original cancellation reason and respecting protected scopes. Cancellation or an output failure can leave a partial document; synchronous checks cannot interrupt a blocked underlying write or flush.
The template currently recognizes these environment variables:
APP_HOME_DIR: overrides the resolved application home directoryAPP_CACHE_DIR: overrides the platform-derived cache directoryRUST_LOG: provides a tracing filter when--log-filteris not supplied
These names are placeholders and should be renamed in the generated project.
The canonical Rust names alias TeamDman's independent published forks:
facetandfacet-prettyuse theirteamy-facet-* =0.50.0-rc.7packages.facet-csvusesteamy-facet-csv =0.50.0-rc.8.facet-jsonusesteamy-facet-json =0.50.0-rc.8; the sharedteamy-facet-formatdependency also uses=0.50.0-rc.8.figueusesteamy-figue =6.0.0-rc.4, withteamy-figue-attrs =6.0.0-rc.3.teamy-cancellation =0.6.0supplies matching Figue arguments, cancellation execution scopes, and synchronous I/O checkpoints.
These are forks, not the upstream Facet or Figue releases. The mixed Facet versions are deliberate: the JSON/format release adds cooperative cancellation and direct writer output while retaining the matching Facet rc.7 core types.
The process owns a shared CancellationToken for Ctrl-C and stop-after requests.
Invocation receives a bounded CancellationScope; its linked cancellable future
checks cancellation at poll boundaries. Pass that supplied scope into new async
operations, and use its nested scope helpers rather than starting an independent
root. Synchronous work still needs explicit checkpoints or yields. Enable
teamy-cancellation's deferral feature for operations that must finish a
submitted mutation and related cleanup in a bounded protected scope. Asynchronous
shutdown owners should use a cooperative scope and retain their required child
work.
Run the standard validation flow with:
./check-all.ps1That script runs formatting, linting, build, and tests
For Tracy profiling, run:
./run-profiler.ps1 home show. # Some files omitted
├── build.rs # Adds exe resources and embeds git repository/build metadata
├── Cargo.toml # Package metadata, dependencies, lint policy
├── check-all.ps1 # Formatting, linting, build, tests
├── init-other-repo.ps1 # Legacy initializer kept temporarily during CLI migration
├── resources # Windows resources used by build.rs
├── src # Rust source code
├── tests # CLI roundtrip fuzz tests
└── update.ps1 # Convenience install helper
