| name | cli-building |
| description | Use when building TypeScript CLIs. Guides command structure, interactive prompts, tab completion, and terminal UI niceties (spinners, progress, inline regions) using citty, `@clack/prompts`, `@bomb.sh/tab`, and `@bomb.sh/tty` — and shipping them: CI gates, versioning (Changesets / release-please), and npm or single-binary release. |
Citty CLI
Quick Start
npm install citty `@bomb.sh/tab` `@clack/prompts`
Minimal command:
import { defineCommand, runMain } from 'citty';
export default defineCommand({
meta: { name: 'greet', description: 'Say hello' },
args: { name: { type: 'string', description: 'Your name', required: true } },
run({ args }) { console.log(`Hello, ${args.name}!`); },
});
Critical Rules
- Every command exports default
defineCommand() — no exceptions
- Lazy-load subcommands —
() => import('./cmd').then(m => m.default)
- Check
isCancel() after every @clack/prompts call — never skip
- Citty handles all arg parsing — no external parsers
- Architecture is opt-in — only suggest
cli/ structure when the user asks for project layout or scaffolding. Single-file CLIs are valid.
- Gate
tab() behind process.argv[2] === 'complete' — the adapter eagerly resolves lazy subcommands, defeating rule 2 on every startup
Architecture (only when user asks for structure)
See architecture for the full cli/ layout with commands, prompts, and lib directories. Do not impose this structure unless the user explicitly asks for scaffolding or project organization.
Workflow
- Define commands — commands
- Add prompts if interactive — prompts
- Add spinners/progress for long-running work — tty-ui
- Wire tab completion — tab-completion
- Scaffold
cli/ if multi-command — architecture
- Configure bin entry — sidecar setup
- Verify — run with
--help to confirm command registration
- Ship it — CI gates, versioning, npm or binary release — release
References
- Architecture — Structure and responsibilities
- Entrypoint — runMain + tab completion wiring
- Commands — defineCommand, args, subcommands
- Prompts —
@clack/prompts reusable modules
- Tab Completion —
@bomb.sh/tab citty adapter, completion protocol, per-shell install (compinit ordering, fish autoload), lazy-loading gate
- TTY UI — spinners and progress:
@clack/prompts spinner first, @bomb.sh/tty inline regions and layout for richer feedback
- Sidecar Setup — bin entry, build config
- Citty API — Resolvable, plugins, CLIError
- Release — CI gates, Changesets/release-please, npm + binary distribution
- Versioning — named schemes (SemVer/CalVer), 0.x vs 1.0, pre-releases, which bump, decision matrix, recording the policy
- Update Command — ask-first self-update: install-mode routing, streaming download (stall timeout, resumable retry), checksum-verified atomic swap, passive banner