# Mcp Open Design

> Drive the installed Open Design desktop app from the terminal through its `od` CLI and stdio MCP server. Read local design projects and design-systems, reuse them, answer the app's prompts, and commission headless generation runs without using the in-app chat. Wires Open Design's MCP server into opencode or Claude Code. MANDATORY: any UI/design work through Open Design also requires sk-interface-…

- **Type:** Skill
- **Install:** `agentstack add skill-michelkerkmeester-opencode-skilled-agent-loops-with-spec-kit-memory-mcp-open-design`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [MichelKerkmeester](https://agentstack.voostack.com/s/michelkerkmeester)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [MichelKerkmeester](https://github.com/MichelKerkmeester)
- **Source:** https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory/tree/main/.opencode/skills/mcp-open-design

## Install

```sh
agentstack add skill-michelkerkmeester-opencode-skilled-agent-loops-with-spec-kit-memory-mcp-open-design
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Open Design (mcp-open-design)

Drive the installed **Open Design** desktop app (nexu-io/open-design, "the official open-source, local-first Claude Design alternative") from the terminal, so a coding agent (opencode / Claude Code) can read your local design projects and design-systems, reuse them, answer the app's prompts, and commission generation runs **without typing into the in-app chat**. The interface is the `od` CLI plus a stdio MCP server that Open Design exposes; deep operational detail lives in [`references/od_cli_reference.md`](references/od_cli_reference.md).

> ## ⛔ MANDATORY PAIRING — `sk-interface-design`
>
> **This skill is the transport, never the taste.** For ANY UI/design work through Open Design — every generation/`start_run`, and every read that feeds a design decision (grounding in a system, reusing its tokens/components) — you **MUST** load [`sk-interface-design`](../sk-interface-design/SKILL.md) and run its ground → token-system → critique FIRST, then shape the brief and every discovery-form answer with that judgment. **You may never produce or shape an interface from Open Design without it.** Open Design generates; `sk-interface-design` decides. This is a hard precondition, not a recommendation. (Pure transport — wiring the MCP server, bare project listing that feeds no design decision — is exempt because it makes no design decision.)

> **Terminology.** Open Design calls a workspace a **project**, a brand/style a **design system** (DESIGN.md + tokens.css + components.html), a build a **run**, and an output file an **artifact**. The CLI brands itself **`od`** but is `app/prebundled/daemon/daemon-cli.mjs` run under Node - it is NOT the bundled `vela` binary (vela is the cloud auth client).

---

## 1. WHEN TO USE

### Activation Triggers

**Use when** the user:
- Wants a terminal agent to use Open Design's local projects, design-systems, or artifacts.
- Wants to wire Open Design's MCP server into opencode or Claude Code ("connect open design", "od mcp install").
- Wants to ground a design in one of Open Design's ~150 design-systems, or reuse its tokens/components.
- Wants to commission an Open Design generation run headlessly, or answer a run's prompt from the terminal.

**Keyword Triggers**: "open design", "open-design", "od mcp", "od cli", "design system from open design", "drive open design from the terminal".

### Use Cases

**Wire direction (connect the app to your agent).** Register Open Design's stdio MCP server into opencode/Claude Code so its tools appear to the agent.

**Read direction (use local content).** List projects, read the active context, read a design system's `DESIGN.md`/`tokens.css`/`components.html`, search files, fetch artifacts - all read-only.

**Run direction (commission work headlessly).** Generation is multi-turn. `start_run` (or `od run start`) fires turn 1, which returns a discovery question-form and zero files. Answer the form with `od ui respond` (or a follow-up message) to fire the build that writes the design and gives the project a `previewUrl`. Gated. **Mandatory before any of this:** load `sk-interface-design` and shape the brief and form answers with its judgment (see the MANDATORY PAIRING banner above).

### When NOT to Use

**Skip this skill when:**
- The user wants to work in Open Design's in-app chat UI directly (that is the thing this skill replaces, not automates).
- The work is generic app coding with no Open Design content (use `sk-code`).
- The work is the design judgment itself (the look, the anti-default critique) - that is `sk-interface-design`; this skill is the transport.
- Open Design is not installed, or its desktop app is not running (the local daemon, and therefore every tool call, is unavailable).

---

## 2. SMART ROUTING

### Primary Detection Signal

Detect the workflow **direction**, since it selects both the commands and the references to load:

```bash
# Direction detection (pseudo)
echo "$REQUEST" | grep -qiE 'install|wire|connect|hook .* up|mcp add' && DIR="WIRE"
echo "$REQUEST" | grep -qiE 'run|generate|commission|build .* in open ?design|start_run' && DIR="RUN"
echo "$REQUEST" | grep -qiE 'read|list|search|design system|tokens|reuse|ground' && DIR="READ"
# default when only inspecting/listing: READ
```

### Phase Detection

```text
TASK CONTEXT
    |
    +- STEP 0: locate the od CLI + confirm the daemon is reachable
    +- STEP 1: Score intent -> WIRE | READ | RUN
    +- STEP 2 [HARD GATE]: if RUN, or READ that feeds a design decision -> LOAD sk-interface-design and run ground -> token-system -> critique FIRST. No design output without it. (WIRE / bare inventory: exempt.)
    +- Phase 1: Wire (od mcp install , or manual config) [WIRE]
    +- Phase 2: Read (list_projects / get_active_context / get_file / design-systems read) [READ]
    +- Phase 3: Run (turn 1 start_run -> answer discovery form -> build -> get_run / get_artifact, gated) [RUN]
    +- Phase 4: Verify (tools/list reflects what you used, the build wrote files and the project has a previewUrl)
```

### Resource Loading Levels

| Level | When to Load | Resources |
| ----- | ------------ | --------- |
| ALWAYS | Every invocation | `references/od_cli_reference.md` (locate the CLI, daemon model, verb surface) |
| CONDITIONAL | WIRE intent | `references/mcp_wiring.md` (opencode + Claude Code config, manual fallback) |
| CONDITIONAL | READ / RUN intent | `references/tool_surface.md` (the MCP tools, the surface/gate/omit policy) |
| ⛔ MANDATORY (any design step) | ANY generation/RUN, or any READ feeding a design decision (grounding, reusing tokens/components) | `sk-interface-design` — load it and run ground → token-system → critique BEFORE deciding. Hard precondition: a design step without it is blocked. |
| ⛔ MANDATORY (any design step) | Reuse-before-generate / fidelity / handoff | `references/design_parity_transport.md` (Open Design transport for the real-UI loop), applied with `sk-interface-design`'s judgment |

### Smart Router Pseudocode

> Resilience pattern: see [sk-doc smart-router template](../sk-doc/assets/skill/skill_smart_router.md). Guard paths, discover at runtime, derive a routing key, score intents, fall back when unsure.

```python
from pathlib import Path

SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references",)
DEFAULT_RESOURCE = "references/od_cli_reference.md"

INTENT_MODEL = {
    "WIRE": {"keywords": [("install", 4), ("wire", 4), ("connect", 3), ("mcp add", 4)]},
    "READ": {"keywords": [("read", 3), ("list", 3), ("search", 3), ("design system", 4), ("tokens", 3), ("reuse", 3), ("ground", 3)]},
    "RUN":  {"keywords": [("run", 3), ("generate", 4), ("commission", 4), ("start_run", 4), ("artifact", 3)]},
}

RESOURCE_MAP = {
    "WIRE": ["references/mcp_wiring.md", "references/od_cli_reference.md"],
    "READ": ["references/tool_surface.md", "references/od_cli_reference.md"],
    "RUN":  ["references/tool_surface.md", "references/od_cli_reference.md"],
}

# ⛔ HARD COUPLING: any RUN, or any READ that feeds a design decision, is design
# work and MUST load sk-interface-design and run its ground -> token-system ->
# critique BEFORE any design output. mcp-open-design owns the transport; the
# judgment is sk-interface-design's and is non-negotiable. A design step composed
# without it is blocked (see design_gate below). Pure WIRE / bare inventory is exempt.
DESIGN_INTENTS = {"READ", "RUN"}

UNKNOWN_FALLBACK_CHECKLIST = [
    "Confirm the direction: wire the MCP server, read local content, or commission a run",
    "Confirm the Open Design desktop app is running (the daemon hosts every tool call)",
    "Confirm the od CLI path: node \"/Contents/Resources/app/prebundled/daemon/daemon-cli.mjs\"",
    "For RUN or any mutating verb, confirm the user wants a write and name the target project",
]

AMBIGUITY_DELTA = 1

def _guard_in_skill(relative_path: str) -> str:
    resolved = (SKILL_ROOT / relative_path).resolve()
    resolved.relative_to(SKILL_ROOT)            # raises if path escapes the skill
    if resolved.suffix.lower() != ".md":
        raise ValueError(f"Only markdown resources are routable: {relative_path}")
    return resolved.relative_to(SKILL_ROOT).as_posix()

def discover_markdown_resources() -> set[str]:
    docs = []
    for base in RESOURCE_BASES:
        if base.exists():
            docs.extend(p for p in base.rglob("*.md") if p.is_file())
    return {d.relative_to(SKILL_ROOT).as_posix() for d in docs}

def classify_intents(request: str):
    text = (request or "").lower()
    scores = {i: 0 for i in INTENT_MODEL}
    for intent, cfg in INTENT_MODEL.items():
        for kw, w in cfg["keywords"]:
            if kw in text:
                scores[intent] += w
    ranked = sorted(scores.items(), key=lambda kv: kv[1], reverse=True)
    primary, top = ranked[0]
    if top == 0:
        return ("READ", None, scores)
    secondary, second = ranked[1]
    if second > 0 and (top - second)  token-system -> critique;
                                        # RAISE/BLOCK if skipped. Never produce UI without it.

def route_open_design_resources(request: str, feeds_design_decision: bool = False):
    inventory = discover_markdown_resources()
    primary, secondary, scores = classify_intents(request)
    intents = [primary] + ([secondary] if secondary else [])
    design_gate(intents, feeds_design_decision)   # ⛔ blocks any design step missing sk-interface-design
    loaded, seen = [], set()

    def load_if_available(rel: str):
        guarded = _guard_in_skill(rel)
        if guarded in inventory and guarded not in seen:
            load(guarded); loaded.append(guarded); seen.add(guarded)

    load_if_available(DEFAULT_RESOURCE)
    if max(scores.values() or [0]) /api/*`), and the in-app Skills. The HTTP port is **ephemeral and rotates on every daemon restart**, so never hardcode it. Rediscover it from `GET /api/mcp/install-info` (the canonical config source) or the socket. The socket-based `od` CLI is stable across restarts, only the HTTP port moves. Full HTTP detail: [`references/od_cli_reference.md`](references/od_cli_reference.md).

### Wire Direction (od mcp install)

```bash
node "$OD_BIN" mcp install opencode --print --json    # PREVIEW only, writes nothing
node "$OD_BIN" mcp install opencode                    # deep-merges ~/.config/opencode/opencode.json (mcp.open-design)
node "$OD_BIN" mcp install claude --print --json       # PREVIEW
node "$OD_BIN" mcp install claude                       # runs: claude mcp add --scope user open-design ...
```

The installed entry is `{"type":"local","command":["","","mcp"],"enabled":true,"environment":{"OD_DATA_DIR":"...","OD_SIDECAR_IPC_PATH":".../daemon.sock","ELECTRON_RUN_AS_NODE":"1"}}`. The canonical source for this entry is `GET /api/mcp/install-info`, where `command[0]` is the "Open Design Helper" Electron binary, `args` is `[, "mcp"]`, and `daemonUrl` is the live HTTP base. The MCP server re-discovers the live ephemeral daemon URL from the socket on each spawn, so the config stays valid across daemon restarts. Run `--print --json` first and read the exact `command`/`env` it will write. Full detail + manual config: [`references/mcp_wiring.md`](references/mcp_wiring.md).

### Read Direction (the safe default)

After wiring, the agent calls Open Design's MCP tools. The **read-only** tools are always safe: `list_projects`, `get_active_context` (what the user has open now), `get_project`, `get_file`, `search_files`, `list_files`, `get_artifact`, `list_skills`, `list_plugins`, `list_agents`, `get_run`. From the terminal directly: `node "$OD_BIN" tools design-systems read --path ` reads a registered design system's pull-layer files. A design system is a `DESIGN.md` (9-section prose) + a paste-ready `tokens.css` (`:root` block) + an optional `components.html`.

### Run Direction (gated, multi-turn)

Generation is **multi-turn, not one-shot**. A single `start_run` (MCP) or `od run start` (CLI) fires **turn 1 only**, which returns a GenUI discovery question-form (the inner agent asking about fidelity, data, and behaviour, with recommended defaults) and ends `awaiting_input` with **zero files**. A run that stops here produces no design.

> **⛔ MANDATORY before turn 1.** Load `sk-interface-design` and run its ground → token-system → critique on the subject. The brief you pass to `start_run` (`--message`) and every `od ui respond` answer MUST be shaped by that judgment — Open Design generates, it does not decide the design. A run composed without `sk-interface-design` is not permitted.

```bash
# Turn 1: commission the run. Returns a discovery question-form, 0 files, awaiting_input.
node "$OD_BIN" run start --project  --message "" \
  --plugin od-new-generation --agent claude --json
# Answer the form to fire the BUILD that writes the design:
node "$OD_BIN" ui list --run  --json                 # find the surfaceId
node "$OD_BIN" ui respond --run   --value "use the recommended defaults"
#   --value-json  for structured answers, or --skip to accept the defaults.
#   A follow-up message ("use the recommended defaults") works too.
```

The inner agent is `claude` / `codex` / `gemini` (per `od run start --help`). `opencode` also works (verified live) and needs an explicit `--model `, or the run uses opencode's default (shown as `"model":null` in the run's `events.jsonl` start event).

Answering the form fires a **build run** that writes the design files (`index.html` and friends). Only then does the project gain an `entryFile` and a `previewUrl` and actually render. Poll `get_run(runId)` and fetch with `get_artifact`. CLI run verbs: `od run start|watch|cancel|list|info`. Other headless write verbs: `od automation` (schedule or fire routines) and `od media generate`. Every one is **mutating** and a STOP-and-confirm point (see Rules + [`references/tool_surface.md`](references/tool_surface.md)).

> **Adding a file is not creating a design.** `od artifacts create --name  --input ` only **adds one file** to a project. It does NOT create a rendered design and does NOT update the project preview. To create a design that renders, use the multi-turn flow above, never `artifacts create`.

### Verify the live tool set

The `od mcp --help` text lists only a documentation subset (8 tools); the running server registers ~18 (including `write_file`, `create_project`, `start_run`, and destructive `delete_file`/`delete_project`). **Always verify the live `tools/list`** before promising a tool exists or is read-only, and gate every mutating/destructive one.

---

## 4. RULES

### ALWAYS

1. **ALWAYS locate the CLI as `node "/Contents/Resources/app/prebundled/daemon/daemon-cli.mjs"`** (or the `ELECTRON_RUN_AS_NODE=1` form). Never assume a global `od` on PATH, and never hardcode `127.0.0.1:7456` or any HTTP port - the desktop daemon is socket-discovered, and its HTTP port is ephemeral and rotates on every daemon restart. Rediscover it from `GET /api/mcp/install-info` (`daemonUrl`) or the socket.
2. **ALWAYS confirm the Open Design desktop app is running first.** The daemon it hosts answers every tool call. If it is closed, the socket is gone and calls fail.
3. **ALWAYS verify the live `tools/list`** before relying on a tool's name or read-only status. The help text undercounts; the real surface is ~18 tools and includes mutating and destructive ones.
4. **ALWAYS gate every mutating or destructive verb** behind explicit user confirmation, an explicit target project/name, and a one-line rollback note. This covers `create_artifact`, `write_file`, `create_project`, `start_run`, `cancel_run`, `delete_file`, `delete_project`, and the `od artifacts/media/automation/ui/memory/plugin` write verbs.
5. **ALWAYS run `sk-interface-design` BEFORE and THROUGHOUT any design step — a hard precondition.** For any generation/RUN, and any READ that feeds a design decision, load `sk-interface-design`, run ground -> token-system -> critique, and shape the brief and discovery-form answers with it. Thi

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [MichelKerkmeester](https://github.com/MichelKerkmeester)
- **Source:** [MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory](https://github.com/MichelKerkmeester/opencode--skilled-agent-loops-with-spec-kit-memory)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** yes
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-michelkerkmeester-opencode-skilled-agent-loops-with-spec-kit-memory-mcp-open-design
- Seller: https://agentstack.voostack.com/s/michelkerkmeester
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
