CLI & desktop app
The desktop app keeps a folder on your Mac in sync with Statecraft: your states as real .jsx files, your design systems as real YAML. Point Cursor or Claude Code at that folder and they can work on the same project you have open on the canvas. The statecraft CLI is the same daemon without the menubar, for CI and headless machines.
The sync folder
Install the Mac app, sign in, and pick a folder. Everything you can reach in the editor shows up inside it, and edits flow both ways — save a file and the canvas re-renders; drag a component on the canvas and the file changes under your editor.
<sync-folder>/
├── AGENTS.md # how to work in here (CLAUDE.md is a copy)
├── _design-systems/
│ ├── acme-ui.yaml
│ ├── acme-ui.exports.txt # every export the bundle has — copy from this
│ ├── _reference.md # each DS's components, props, snippets
│ └── _status.md # did the last build/import actually work?
└── acme/ # workspace
└── checkout/ # project
├── project.json
└── states/
├── _order.json
├── cart-review.jsx
└── payment-failed.jsx
You don't have to explain any of this to an agent. The daemon writes AGENTS.md (and a CLAUDE.md pointing at it) into the root, listing the file conventions, and _design-systems/_reference.md with every component, prop and snippet the design system offers. The folder documents itself.
To add a state, write <project>/states/<slug>.jsx and append it to states/_order.json. Frame positions aren't persisted — new frames are laid out automatically.
After an agent (or you) changes something, read _design-systems/_status.md and each project's _status.md. They're the canonical answer to "did it render", written after every build, and they name the failure when there was one. A file that saved cleanly can still throw on the canvas.

Command reference
The CLI mirrors the editor's whole CRUD surface, so an agent can create a workspace, a design system and a project without touching a browser.
statecraft ├── sign-in / sign-out / whoami / sign-up ├── sync [<folder>] # start the watcher in the foreground ├── config get|set|unset|list # per-machine settings (e.g. sync-folder) ├── workspace create|list|rename|rm ├── project create|list|update|rm|status ├── design-system create|list|rename|rm ├── live list|build|status|rm # kind: live registrations ├── tokens create|list|revoke # workspace API tokens for CI ├── import # register a kind: live DS from a repo ├── publish # build + upload a bundle (CI) ├── propose # open a GitHub issue with an implementation plan └── export # open a Pull Request of production code
Resource references accept either an id or <workspace-slug>/<resource-slug> anywhere they appear. Two rules are worth knowing before you script anything:
project createrequires--design-system. State JSX renders inside the design system's iframe, so a project without one can't exist. The framework is inherited from the design system — you can't bind a Vue design system to a React project.- There is no
live update. For akind: livedesign system, statecraft.yaml is the source of truth: edit the file and save.
Flags & exit codes
Anything that kicks off work takes --wait, which blocks until the build or render reaches a terminal state and then exits with a meaningful code. Pair it with --json for a single record on stdout instead of streaming progress. That combination is what makes the CLI safe to put in a script:
$ statecraft project status acme/checkout --wait --json
{"status":"error","states":[{"slug":"payment-failed","error":"Card is not defined"}]}
$ echo $?
1| Exit | Meaning |
|---|---|
0 | Success. |
1 | Build or render failure. A classified error lands on stderr, or on stdout under --json. |
3 | Slug, project or workspace not found. |
4 | Someone else rotated the bundle while we were waiting on it. |
124 | Timed out. The default is 15 minutes; --timeout 0 disables it. |
Other global flags: --workspace to set context, --non-interactive to fail rather than prompt (also STATECRAFT_NON_INTERACTIVE=1), and --yes to skip the confirmation on any rm.
Headless machines
The CLI ships as a standalone Linux x86_64 binary — no menubar, same daemon. statecraft config set sync-folder <path> then statecraft sync runs the watcher in the foreground, which is what you want in a container. For publishing a design system from CI, see Publish & PR previews.