v0 · in active design

Design system for modern CLIs.

Caret is to terminals what shadcn/ui is to the web. Copy-paste components, a token system, and a spec — so your CLI ships looking like Vercel or Linear built it.

  • inline output
  • NO_COLOR-aware
  • AI-native
  • no runtime dep
deploy.ts
import { prompt, spinner, success } from './caret'

const name = await prompt.text({
  label: 'Project name',
})

await spinner('Deploying', deploy, {
  onSuccess: `${name} is live`,
})
renders
~/projects/my-cli

Every CLI is an island.

  • Colors applied at random, clashing with the user’s terminal theme.
  • Spinners and prompts copy-pasted from five different libraries.
  • Error messages that look nothing like the rest of the tool.
  • No respect for NO_COLOR, non-interactive pipes, or narrow terminals.

The web already solved this. The terminal has no equivalent — until now.

Components

Every primitive a CLI needs. And then some.

Browse all components
banner
prompt
spinner
error
step
progress
table
keyValue
list · message
Showing 9 of 80+ componentsSee the full catalog →
Principles

Every decision comes back to these.

01

You own the code

`npx caret add prompt` copies the component into your repo. Modify, fork, or delete it. Caret is a starting point, not a dependency.

02

Beautiful by default

One strong opinion about how things should look. No configuration needed to ship a CLI that looks like Vercel built it.

03

Never touch the background

Your terminal has a background. Caret does not set it. Ever. Works on every theme because it doesn’t fight the user’s environment.

04

Respect the user’s theme

Foreground uses the terminal’s fg. Semantic colors emit ANSI names so they harmonize. Only the accent is fixed truecolor.

05

AI-native from day one

A caret.md instruction file ships with the project so Cursor, Claude Code, and Copilot produce correct Caret code on the first try.

06

Motion has meaning

Spinners resolve into checkmarks, progress pulses, errors reveal. Bounded to 300ms, inline-safe, disabled under reduced motion.

No provider. No config. No theme object you forgot to pass down.

That’s it. Import and go.

deploy.ts
import { prompt, error, spinner } from './caret'

const name = await prompt.text({
  label: 'Project name',
})

await spinner('Deploying', async () => {
  await deploy(name)
})

error('Deploy failed', {
  hint: 'Check your API key in ~/.config/my-cli',
  see: 'https://my-cli.dev/docs/auth',
})
AI-native

Built for the age of AI-authored CLIs.

Caret ships caret-skills — two manifesto-checked skills your agent can invoke. They turn "write a CLI component" from generic AI output into Caret code on the first try.

/create-caret-component
Author one Caret component end-to-end — tokens, props, render, capability fallbacks, test.
/caret-cli-design
Read an existing CLI repo, output an adoption plan with the exact caret-cli add sequence.
Claude Code·Cursor·OpenCode·Codex·50+ runtimes via npx skills

Give your CLI a design language.

Read the manifesto →