Your first CLI
This page walks through scaffolding a new CLI, prompting the user, running an async task with a spinner, and printing a structured error. About five minutes end-to-end.
Scaffold
npx caret-cli init deploy-cli
cd deploy-cli
npm installinit writes package.json, tsconfig.json, src/index.ts, and a caret.md AI-instruction file. The starter src/index.ts is a working CLI you can run with npm run dev immediately.
Add the components you need
The starter ships with no components yet — pull only what you use.
npx caret-cli add prompt
npx caret-cli add spinner
npx caret-cli add errorFiles land under caret/. Each add prints the runtime dependencies the component declares — install them once.
Write the deploy command
Replace src/index.ts with this. Three primitives, no provider, no theme object.
import { prompt, spinner, error, success } from './caret'
async function main() {
const project = await prompt.text({
label: 'Project name',
validate: (v) => v.length > 0 ? null : 'Required',
})
const env = await prompt.select({
label: 'Environment',
options: [
{ value: 'staging', label: 'Staging' },
{ value: 'prod', label: 'Production' },
],
default: 'staging',
})
await spinner(`Deploying ${project} to ${env}`, async () => {
await fakeDeploy(env)
}, { onSuccess: `${project} is live` })
success('Done')
}
async function fakeDeploy(env: string) {
await new Promise((r) => setTimeout(r, 1500))
if (env === 'prod' && Math.random() < 0.2) {
throw new Error('Health check failed')
}
}
main().catch((e) => {
error('Deploy failed', {
body: e instanceof Error ? e.message : String(e),
hint: 'Check the deploy logs and re-run.',
see: 'https://caret.dev/docs/cli',
})
process.exit(1)
})Run it
npm run devYou'll see a prompt for the project name, then a select for the environment, then a braille spinner that resolves into either a green ✓ or — about one in five times in production — a Rust-style error block with hint and see.
NO_COLOR. You don't enable any of this — it's the manifesto's "Correctness is not opt-in" rule.Next
- Principles — the rules every Caret decision comes back to.
- CLI reference — every command, flag, and exit code.
- Component catalog — what else you can
add.