CLI
Primitiv command-line interface reference.
Commands
| Command | Description |
|---|---|
primitiv init [dir] | Detect your project (framework, TypeScript, Tailwind, Figma, Storybook, package manager) and generate primitiv.config.js. Also writes a project-scoped MCP config, refreshes a Primitiv block in AGENTS.md and CLAUDE.md (or creates AGENTS.md if neither exists), installs a verify --strict GitHub Actions workflow on GitHub repos, and drops a /build-component skill for Claude Code. |
primitiv build [config] | Scan sources, resolve conflicts, lint for token misuse, write the contract. With governance.onConflict: "error", exits 2 when pending conflicts remain (the contract is still written). |
primitiv serve [config] | Start the MCP server against the built contract. Hot-reloads when the contract file changes. |
primitiv verify [config] [flags] | Re-run build and exit non-zero if conflicts are unresolved, token misuse is detected, or the contract is stale. Intended for CI. |
All commands accept an optional path argument. If omitted, Primitiv uses the current directory (init) or ./primitiv.config.js (build, serve, verify).
What the codebase scanner extracts
build parses TypeScript/JSX structurally (an AST, not regex), so what lands in the contract reflects the code's actual shape:
- Tokens across nine categories —
colors,spacing,sizes,typography,borderRadius,shadows,zIndex,breakpoints,motion. CSS custom properties and exported theme objects (export const theme = {…}) are both read; Tailwind class strings are rejected (they aren't token values) and scale aliases ({ value: size[100] }) are resolved to their literal. - Components, every one in a file — captured at its definition site, including
forwardRef/memo/styled/ factory wrappers — and classified bykind(component/screen/provider/icon/other). Same-name components across files are surfaced as collisions in the build log rather than silently dropped. - Design-token scale only — component-internal CSS variables (defined inside a component selector, or under a
--pc--style prefix) are separated from the global tokens and reported as an excluded count, so the contract stays the project's real token scale. - Theme modes — theme-variant values (
.dark,[data-theme="dim"],@media (prefers-color-scheme: …)) are captured as a token'smodesmap instead of being dropped or duplicated into-darknames. A token defined only under a theme scope still enters the contract, with its mode value promoted to the default.
Same-source redefinition conflicts
A token defined twice within one source with two different values surfaces as a pending conflict — both provenances are kept, and the suggestedFix names each file:line — instead of one definition silently winning. These are never auto-resolved: a source can't arbitrate itself, so they stay pending under every onConflict value until a definition is removed. (Same-value duplicates stay silent, and legitimate overrides like a responsive @media block are not treated as conflicts.)
Frameworks detected by init
Next, Nuxt, Astro, SvelteKit, Remix, Expo, Qwik, Vite, Solid, React. Meta-frameworks are checked before their underlying libs to avoid mislabelling (SvelteKit, Astro, and Remix all depend on Vite internally, but they aren't reported as Vite). Monorepo workspace recursion is not supported yet — the root package.json drives detection.
Package manager is auto-detected from the lockfile (bun.lock → bunx, pnpm-lock.yaml → pnpm dlx, yarn.lock → yarn dlx, otherwise npx) and used in the generated MCP config.
Flags for verify
| Flag | Effect |
|---|---|
--strict | Escalate stale contract, token misuse, and failed source scans to hard failure (exit 2). |
--json | Emit a machine-readable report to stdout. |
--fast | Use file mtimes for drift detection instead of rebuilding. Faster, but unreliable in CI / fresh clones. |
Exit codes for verify
| Code | Meaning |
|---|---|
0 | Contract is fresh, conflicts resolved, no token misuse |
1 | Stale contract OR token misuse detected (warning level, default) |
2 | Unresolved conflicts, OR --strict escalation of stale / token misuse / failed source scans |
3 | No config or contract found, or the contract is malformed |
Exit codes for build
| Code | Meaning |
|---|---|
0 | Contract written — a failed optional source is recorded in the contract's sourceStatuses and the build continues |
1 | Build failed (bad config, or the governance.sourceOfTruth / a source marked optional: false failed to scan — no contract written) |
2 | Pending conflicts with governance.onConflict: "error" — the contract is still written first |
See Verify in CI for a worked example with token-misuse output and how to suppress false positives, and Failed sources for how scan failures are recorded.