Skip to main content
The CLI drives 21st AI end to end: kick off a generation, watch it build, refine the draft you like, and pull its code. It’s the same engine as the web app and MCP.

Check AI access

CLI 1.17.1 adds 21st usage --json. Older versions show the same AI access in the 21st AI generation line. The MCP get_usage tool reports it as aiGenerationEnabled. generate and iterate require aiGenerationEnabled: true and available AI credits. Read credits.balance for the current balance, credits.resetsAt for its reset time, and credits.scope for personal/team usage. Builder and Team start with AI off; a base subscription does not enable generation. When aiGenerationEnabled is false, use 21st search and 21st get to retrieve components, then adapt them with your own coding agent. If a generation call returns ai_subscription_required, use this workflow instead of retrying.

Start a generation

Starts a 21st AI sketch generation and opens a browser preview so you can watch the drafts build. Returns a projectId you use with the commands below. Use --wait --no-open --json for an agent or script. Non-interactive output waits automatically without opening the browser. A timeout exits with code 4 and retains the accepted project UUID: check 21st generation later rather than generating again. Not signed in exits with code 3; blocked AI access or credits exits with code 2. --models <comma-separated-keys>, --theme <slug> and --remix <demo-id|author/component> select explicit inputs. CLI includes .21st/design.json automatically when present; --context none skips it.

List the drafts

Lists the “takes” (drafts) of a generation with their take numbers and ready state. Free.

Refine a take

Edits one take in natural language. Without --take it refines the default take; pass --take N to target a specific one. Use --wait to wait for the accepted refinement job and --base-version N to choose the saved source version. Versions are one-based. Sketch and Code refinements run as durable server jobs with the same producer as the web editor. Code uses the exact saved source snapshot and preserves file scopes and locks. An older base appends a branch and preserves newer versions. --part and --lock take stable addresses from a pulled version, with comma-separated lists. A new --note attaches to each selected part, or the whole take when no part is selected. --scope every-take submits independent jobs and waits for each; a failed take does not hide the others. Each accepted refinement uses the same owner, credit, scope and lock guards as the web editor.

Grab the code

By default take prints a paste-ready copy-prompt you can drop into your editor or agent to recreate the UI in your own stack. Use --code to print the raw HTML. Free. Always use the full project UUID. Takes and versions are one-based; --version N retrieves exactly that saved version. Code returns saved private source snapshots and dependencies when available, including when the preview is asleep. --files refuses an existing directory. take --latest suggests a recent handoff for confirmation and does not automatically retrieve its source. The existing Remix trial take-out wall applies to every export format. --part fetches only selected saved source fragments. Code accepts stable addresses, exact file paths, or src/App.tsx:10-20. Shared CSS and imports may need the full take. --elements includes stable addresses with rect: null until a live preview supplies geometry. --tokens reports declared CSS custom properties, not computed styles. Empty, missing and oversized selections are rejected rather than replaced with an entire take.

Free edits

Pull the exact current saved take before editing. 21st take-edit <projectId> --take 2 --version 3 --ops '[{"type":"duplicate","target":"card"}]' clones that saved subtree after the original with fresh addresses. To move it into a saved container, use --ops '[{"type":"move","target":"card","anchor":"main","position":"into"}]'. The same deterministic edit path saves with zero credits. Static Code JSX requires one tree and an unlocked source and destination; dynamic expressions, handlers or imported components need an explicit note. Unsupported edits never start paid generation automatically. Save and pull again before addressing a new clone. Sketch style operations accept "media":"phone", for example --ops '[{"type":"style","target":"title","property":"font-size","value":"18px","media":"phone"}]'. This changes the exact unlocked target only at widths up to 639px, preserving its desktop inline styles. An empty value removes that Phone override. Omit media for the usual inline edit. Code Phone styles are saved as actual media CSS in React source only when the server proves a static default App and one literal main/index entry render. Dynamic or reused components, unknown imports, ambiguous targets and locks are rejected without starting AI. An empty value removes the exact Phone override and keeps its desktop style.

Notes, changes and outcomes

Note status can be in_progress, done or wont_do; the last requires a one-line summary. Add --status sent|open|all when reading notes, and --files src/App.tsx,src/Menu.tsx when reporting actual changed files. Attach up to eight references to a note with iterate --note "Match this reference" --refs '[{"kind":"link","url":"https://example.com/reference"}]'. Supported references are HTTP(S) links or images, an exact saved {"kind":"take","take":2,"version":3,"id":"hero"} in the same project, and {"kind":"component","slug":"author/component"}. References provide context; they do not claim a component was installed or an image was fetched. To save notes without generating, use take-edit <projectId> --take 2 --version 3 --notes '[{"id":"pricing-note","target":"pricing","text":"Use annual pricing","refs":[]}]'. The server stamps the creator and validates referenced access. Supplied authors are discarded; existing creators remain intact when notes are edited. --since pulled uses your latest successful CLI or agent retrieval, including a historical version. It also includes notes changed after that retrieval on the same version. A web copy does not move this cursor. Without a previous pull, fetch the take first; --since N selects an explicit saved version. Outcomes are landed, adapted or abandoned, with separate agent/user attribution and observed build checks. Abandoned requires a reason. The server accepts an outcome only after that exact version was taken out recently. Forward feedback only at the user’s explicit request, in their words. In a script, one outcome reminder per day goes to stderr after a successful take-out. JSON and source output on stdout stay unchanged. If a saved login expires within 24 hours, the CLI also warns once a day to run 21st login. JSON results include takeState from the persisted attempt and producer lease. failed, stopped and blocked end a wait immediately; unknown historical model or credit amounts remain null. Reuse the accepted project after a timeout.
generate and iterate consume credits. Listing existing drafts (generation) and taking their code (take) are free and remain available without AI enabled.

Typical flow