CLI and projects
npm i -g @mozaik/cli opens a store as a file-tree project: design as files an agent can read, diff and edit with ordinary tools, synced against the server draft under CAS. The full command table is generated at /reference/cli; this page is the working loop.
The loop
mozaik login --token mzk_… # once per machine
mozaik open st_mystore # Tree v2 + mozaik.json + AGENTS.md + .mcp.json
# edit design/ with anything
mozaik push # validate server-side, save as the workspace draft (CAS)
mozaik preview # stable preview URL of the workspace draft
mozaik propose --title "…" # agent tokens: submit the open proposal for review
open is idempotent (≈ pull); dev watches design/, pushes on change and keeps the preview URL live; status and diff compare the tree against the lock, the server draft or the live design. Catalog data has its own arm: mozaik catalog export|plan|apply (catalog) round-trips catalog/*.jsonl as idempotent commands, and cmd runs any single command through the bus: for an Ajan token, recorded as a proposal item like every mutation.
Tree v2
mozaik.json project manifest (format 2, store, workspace, pinned CLI): no secrets
.mozaik/base.lock last-sync state (platform build, draft rev/hash, file hashes)
AGENTS.md how agents should work here (CLAUDE.md = @AGENTS.md)
.mcp.json MCP wiring: hosted admin MCP + local dev-mcp, both pinned
design/ the store design as files (assembled hash == server hash)
theme.json theme state: installed theme ref + kit, core tokens, theme variables, preset, history
custom.css owner CSS (same attribute-selector grammar as skins, ≤20 KB)
zones.json owner-placed extension blocks per storefront zone
composites/*.json store-private composite sections (c.<name>@N)
regions.json · pages/ · navigation.json · seo.json · locale.json · settings.json
catalog/*.jsonl optional catalog export
media/manifest.json media inventory
theme/ reserved for a theme package (skin authoring, T1.6)
Tree v1 projects (format 1, a bare theme.json of tokens) are read by the platform forever (the server upgrades them in memory) but the CLI writes format 2; a CLI older than the platform's minCli gets HTTP 426 / exit 3.
The design/ tree assembles to exactly the server draft (same hash) so "what would change" is always answerable locally. validate runs the server-side bundle checks (validate.bundle) without saving anything.
Credentials never live in the project
The token sits in ~/.config/mozaik/credentials.json (0600) or MOZAIK_API_TOKEN: never under the project root. mozaik.json, .mozaik/ and .mcp.json contain zero secret material (the .mcp.json uses env substitution), so a project tree is always safe to commit, zip or hand to another agent.
.mcp.json wiring
open writes an .mcp.json that gives any MCP-aware editor or agent two servers, both pinned to the project's CLI version:
- admin MCP:
https://api.mozaik-dev.com/mcpwith the bearer from the environment: the store's tools, live. - dev MCP:
mozaik dev-mcp(dev-mcp) over stdio: docs search, schema introspection and validators for the current platform build. No auth, no store access.
AGENTS.md in the tree carries the store-specific working notes; Claude Code reads it via CLAUDE.md = @AGENTS.md.
Exit codes
| code | meaning |
|---|---|
| 0 | ok |
| 1 | error |
| 2 | usage |
| 3 | version/format refusal (HTTP 426): npm i -g @mozaik/cli, then upgrade |
| 4 | conflict: the draft moved (HTTP 409); re-read, rebase your edit, push again. The server never merges. |
Everything the CLI does is the public API: the same commands, routes and version discipline as every other client; there is nothing the CLI can do that your own HTTP calls cannot.