maude CLI
The npm-published binary that scaffolds the .ai/ workspace, edits workflows.config.json, and boots the design dev server.
npm i -g @1agh/maude # installs `maude` (legacy alias: `mdcc`; also installs `claude-design-server`)
# or:
npx @1agh/maude <cmd>maude is intentionally small. Mechanical scaffolding and config. That's it. The interesting setup happens inside Claude Code via /flow:init, which calls maude init as step one.
Subcommands: init, config, doctor, cache, design (serve · init · export · link/adopt/unlink/status), hub (serve · token · status · deploy), version / help. Pure ESM, Node 20+. Thin dependency surface — Ajv for config-linting, plus the per-platform dev-server binary pulled in via optionalDependencies.
maude init
Scaffold the .ai/ second-brain workspace into the current repo.
maude init [--name <project>] [--force] [--dry-run]--name <project>. Project slug for the<project>placeholder used by flow templates (e.g..ai/<project>-prd.md). Defaults to the current directory basename.--force. Overwrite existing files. Off by default;initis idempotent.--dry-run. Print what would be written without touching the filesystem.
The skeleton lives at plugins/flow/templates/ai-skeleton/. maude init does string templating during the copy:
- Replaces
PROJECT_NAMEplaceholders with--name's value. - Rewrites the
$schemaref inworkflows.config.jsonfrom a relative path to the absolute GitHub raw URL (so it resolves afternpm install).
Does not write CLAUDE.md. Use Claude Code's built-in /init for that.
maude config
Read or write keys in .ai/workflows.config.json from the terminal.
maude config show
maude config get <dotted.key>
maude config set <dotted.key> <value>show. Pretty-print the whole config.get. Print a single key. Dotted path:maude config get motion.complex.set. Write a key. Values that parse as JSON (numbers, booleans, arrays, objects) are stored typed:
maude config set platforms '["web-desktop","web-mobile"]'
maude config set motion.complex 1200
maude config set theme darkmaude config does no schema validation — it's a typed read/write, nothing more. To lint the config against the flow plugin's config.schema.json, run maude doctor.
maude doctor
One umbrella diagnostic for the workspace. In a single pass it reports missing plugin dependencies (per-plugin), .ai/workflows.config.json schema errors, stack drift, and missing quality-gate declarations.
maude doctor [--plugin <design|flow>] [--fix] [--json]--plugin. Scope the dependency section to one plugin. The config section is always global.--fix. Apply safe auto-fixes — per-dep install prompts, drop unknown config keys, apply detected drift, add missing quality gates. Never silent, and existing user values are never overwritten.--json. Machine-readable envelope.
This is where config validation lives — maude config itself does none. (DDR-058.)
maude cache
Inspect and manage the sidecar cache the orchestration uses to skip repeated research, codebase-intelligence, and design-context work.
maude cache list # layers with entry counts, sizes, last write
maude cache stats # hit/miss counters + hit-rate per layer
maude cache inspect <layer> [key] # list entries in a layer, or print one
maude cache clear [layer[/key]] # wipe one entry, one layer, or everything
maude cache get <layer> <key> # print a fresh value (exit 1 on miss/stale)
maude cache put <layer> <key> [file] # write a value from a file or stdinLayers: research/domain, research/project, codebase-intelligence, design-context, security, scenario, validate. (DDR-061.)
maude studio / maude design serve
Boot the canvas studio (the design dev server) in the current repo.
maude studio [--port N] [--root <path>]
# equivalent:
maude design serve [--port N] [--root <path>]maude studio is a top-level alias for maude design serve — the verb matches the studio's home under apps/studio/. Both are equivalent, and both also match invoking claude-design-server directly (the second bin shipped by @1agh/maude). All remaining args are forwarded to the server.
--port. Listen on a specific port (default4399; falls back to a random free port if taken).--root. Serve a different repo. By default uses$CLAUDE_PROJECT_DIR, thenprocess.cwd().
The server fails loud if launched from a directory without a .design/ folder. That's deliberate. It stops you from accidentally serving the wrong project.
maude design init
Non-interactive scaffold helper for the design plugin. Writes Core files from the design-system-inspiration library into .design/ in the current repo.
maude design init [--name <slug>] [--ds <name>] [--force] [--dry-run]
[--no-discovery | --discovery-payload <path>]Refuses to run interactively. Full discovery requires Claude Code. Use /design:setup-ds <name> there. The CLI helper exists for CI / scripted contexts:
--no-discovery. Scaffold Core only (~10 files: README, INDEX, config.json, tokens, specimens) with a deliberately neutral skeleton — system fonts, achromatic grayscale, light theme, a single neutral-graphite accent. It's intentionally unfinished so you're nudged to run real discovery instead of unconsciously shipping a default aesthetic (DDR-043).--discovery-payload <path>. Read pre-computed answers and tokens from JSON and scaffold Core + derived specimens deterministically. This is the path skilldesign-system(bootstrap mode) uses when shelling out from Claude Code.--name <slug>. Project name token. Defaults to the current directory basename.--ds <name>. Design system name (kebab-case). Defaults toproject(single-DS convention).--force. Overwrite an existingsystem/<ds>/. Off by default.
# Quick CI scaffold (Core only)
maude design init --no-discovery --name acme
# Re-bootstrap an existing DS
maude design init --no-discovery --name acme --force
# Skill-driven scaffold from a payload file
maude design init --discovery-payload /tmp/discovery.json --name acmeFor everything beyond a Core scaffold (audience-specific specimens, platform-conditional adds, brand-color discovery), use /design:setup-ds inside Claude Code.
maude design export
Drive the same export endpoint the dev-server UI uses (⌘E). Requires a running server — the port is auto-detected from .design/_server.json.
maude design export <png|pdf|svg|html|pptx|canva|zip> \
[--scope selection|artboard|canvas-as-separate|project-raw] \
[--out <path>] [--option key=value ...]The response body is written to --out (default: current dir, server-supplied filename). canva emits a PPTX payload plus a .canva-handoff.md artifact; zip bundles the whole project.
maude design link / adopt / unlink / status
Pair a clone with a self-hostable sync hub so .design/ mirrors bidirectionally. Claude Code still reads and writes plain files — it never sees Yjs.
maude design link <url> --token <hex> [--adopt] [--force]
maude design adopt <url> --token <hex> # alias for: link --adopt
maude design unlink [--keep-token]
maude design status [--json]The linkedHub pointer lands in committed .design/config.json; the token is stored per-machine in ~/.config/maude/hubs.json (mode 0600, never committed). The first link to a non-loopback hub asks for confirmation — a linked hub gets write access to your .design/. See Linking peers.
maude hub
Run or deploy the self-hostable Yjs sync hub that backs linked mode.
maude hub serve [--port N] [--data PATH] [--secret HEX] [--dev]
maude hub token generate --label <name> [--scope '*']
maude hub token rotate --label <name>
maude hub status [URL] [--json]
maude hub deploy <fly|docker> [--name N] [--region R] [--out DIR]serve. Boot the hub (default port1234). On an empty hub it prints a one-time bootstrap link to claim admin; the/adminUI then mints invite tokens and rotates them without shelling into the host.token generate. Mint amau_<hex>token (HMAC-hashed at rest). Pass--scope '*'for a peer that syncs canvases — this is what the/admin"Generate invite" button does.deploy. Emit Fly or Docker templates with placeholders filled, then print the exact commands to run. It does not runfly/dockerfor you. See Deploy a hub.
maude version / maude help
What they say on the tin.
maude version
maude helpWhere the source lives
cli/bin/maude.mjs(legacy alias:cli/bin/mdcc.mjs). Argv parser and subcommand dispatch.cli/commands/{init,config,doctor,cache,design,hub,help,version}.mjs. One file per subcommand (preflight+scenario-reportare internal helpers).
Pure ESM, Node 20+ — Ajv is the only library dependency (config-linting); the dev-server binary ships via optionalDependencies. PRs welcome at github.com/1aGh/maude.