Every handoff-app command, grouped, with real flags from the CLI source.
Most commands accept two shared options: -d, --debug (verbose logging) and -f, --force (force
action, meaning varies by command). They're omitted from the tables below. init and init:vercel
are the exceptions: they don't register the shared options at all.
There's no config-path flag. To point the CLI at a different workspace directory, set the
HANDOFF_WORKING_PATH environment variable, config resolution starts from there instead of
process.cwd(), see handoff.config.* resolution.
Interactive wizard (@clack/prompts): project name, Figma project ID + access token, TypeScript/JavaScript config, whether to include example components. Writes a starter handoff.config.*.
scaffold
—
Generates component declaration stubs for components already pulled in via fetch, so you have a .handoff.ts/.js file per Figma component to fill in.
Pulls the raw token/component export from Figma into the project's tokens.json snapshot.
tokens:build
--skip-migrate
Auto-migrates a legacy Figma export into design-system/tokens/ (DTCG), then runs Style Dictionary to produce design-system/dist/{css,scss,tailwind,dtcg}. See Token pipeline.
audit:figma-components
--json, --fail-on-drift
Compares fetched Figma components against locally registered ones; reports Figma-only components and missing/broken figmaComponentId links. --fail-on-drift exits non-zero on any drift (useful in CI).
The local preview command. Builds components, patterns, the main JS and the main CSS, then runs a custom dev server with file watchers and a WebSocket live-reload channel, filesystem-backed (StaticDataProvider). See Local preview.
dev
—
Plain next dev against the materialized app. Builds no components, so the preview renders empty. A debugging escape hatch for the Next.js app itself, not the command you want for previewing a design system.
build:app
--skip-components, --mode dynamic|vercel
Builds the documentation application.
build:components [component]
—
Builds all components, or a single one by name.
validate [component]
--validators <ids>, --json, --ci, --update
Runs configured validators (axe/schema/contrast/custom) against built component data. --ci exits non-zero per config.validation.failOn. --update writes results back into the component's built JSON.
validate:components
--skip-build
Validates components in the design system (legacy path predating the validate validator framework).
OAuth device flow: opens a browser for approval, saves the resulting bearer token to .handoff/cli-auth.json. --no-browser (or CI=1 / HANDOFF_LOGIN_NO_BROWSER=1) skips the browser open and just prints the verification URL.
logout
—
Removes .handoff/cli-auth.json for the resolved deployment.
Pushes local pages + component/pattern declarations + built preview artifacts via POST /api/sync/upload. Selective flags accept repeated or space-separated ids. --dry-run needs no cloud URL/token. -m records a short "why" shown in the changelog.
Full workspace → registry sync: runs every push step in sequence (config → components/pages → theme → navigation → pages → tokens → dtcg → icons → logos → fonts → Figma image fills → image slot specs → refresh DESIGN.md). Any --skip-* flag omits that step. Non-fatal per-step failures are logged and summarized; the command exits non-zero if any step failed.
push:tokens
--skip-figma, --skip-dtcg
Just the Figma token snapshot + DTCG dist push, faster than push:all when only tokens changed.
pull
--dry-run
Pulls remote edits (pages, component declarations, build artifacts, source files) via GET /api/sync/changes into the workspace. --dry-run prints what would change without writing files or updating .handoff/sync-state.json.
sync-status
—
Prints the remote sync cursor vs. local .handoff/sync-state.json.
One-step MCP onboarding: signs in if needed, fetches DESIGN.md, writes/merges a .mcp.json entry, and upserts a "Design System" block into CLAUDE.md. --embed writes the literal token into .mcp.json (auto-gitignored) instead of an env-var reference. See MCP → Onboarding.
mcp-token
--root
Prints only the MCP/sync bearer token to stdout: composes into export HANDOFF_MCP_TOKEN=$(handoff-app mcp-token).
init-claude
--root, --server-name, --token-env
Older, equivalent one-shot wiring for Claude/agents (fetch DESIGN.md, register MCP server, update CLAUDE.md). It doesn't drive the login round-trip itself; expects .handoff/cli-auth.json to already have a token. mcp-init is the current recommended path.
Both commands still work for existing legacy deployments but are slated for removal. Under the
current model, a registry is its own handoff-app deployment and workspaces push content to it
via push:all, see Registry → Deploy.
Command
Flags
What it does
prepare-runtime
--skip-components
[DEPRECATED] Materializes the Next.js app into .handoff/runtime/ for a CI/Vercel deploy of the workspace itself, without running next build.
vercel-build
--skip-components
[DEPRECATED] Materializes the app and runs a full next build in .handoff/runtime/: the legacy Vercel build command for per-project deploys. Auto-skips component builds when HANDOFF_REGISTRY_MODE or DATABASE_URL is set.
init:vercel
--root
Writes a vercel.json + .env.vercel.example for deploying a registry (not a workspace) to Vercel, see Registry → Deploy.