{
  "$schema": "./dependencies.schema.json",
  "version": "1",
  "plugin": "design",
  "dependencies": [
    {
      "id": "node",
      "type": "cli",
      "hardness": "hard",
      "check": {
        "command": "node --version",
        "expectExit": 0,
        "minVersion": "20.0.0"
      },
      "install": {
        "preferred": "https://nodejs.org/en/download",
        "darwin": "brew install node@22",
        "linux": "https://nodejs.org/en/download/package-manager"
      },
      "autoInstall": false,
      "usedBy": ["commands/init.md", "commands/browse.md", "dev-server/server.ts"],
      "docsUrl": "https://nodejs.org"
    },
    {
      "id": "git",
      "type": "cli",
      "hardness": "hard",
      "check": {
        "command": "git --version",
        "expectExit": 0
      },
      "install": {
        "darwin": "brew install git",
        "linux": "apt-get install -y git || dnf install -y git"
      },
      "autoInstall": false,
      "usedBy": ["commands/init.md", "dev-server/collab/git-lifecycle.ts"],
      "docsUrl": "https://git-scm.com"
    },
    {
      "id": "bun",
      "type": "cli",
      "hardness": "hard",
      "check": {
        "command": "bun --version",
        "expectExit": 0,
        "minVersion": "1.3.0"
      },
      "install": {
        "preferred": "curl -fsSL https://bun.sh/install | bash",
        "darwin": "brew install oven-sh/bun/bun",
        "win32": "powershell -c \"irm bun.sh/install.ps1 | iex\""
      },
      "autoInstall": false,
      "fallbackBehavior": "dev-server is migrating to Bun authoritatively (DDR-009). Some build steps (bun run build.ts, bun test) require Bun and have no Node fallback.",
      "usedBy": ["dev-server/package.json", "dev-server/build.ts", "dev-server/bin/smoke.sh"],
      "docsUrl": "https://bun.com"
    },
    {
      "id": "agent-browser",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "agent-browser --version",
        "expectExit": 0
      },
      "install": {
        "preferred": "npm i -g agent-browser"
      },
      "autoInstall": true,
      "fallbackBehavior": "Screenshot helpers fall back to `npx playwright` (slower, less reliable). /design:smoke and several critics need agent-browser for full coverage. On the Maude DESKTOP app it is BUNDLED (externalBin, DDR-144) and its Chromium engine is provisioned as chrome-headless-shell by `maude design ensure-browser` — screenshots work zero-install there; this soft/manual note applies to the web `maude design serve` + CLI paths.",
      "usedBy": [
        "commands/screenshot.md",
        "commands/new.md",
        "commands/edit.md",
        "commands/smoke.md",
        "commands/board.md",
        "dev-server/bin/screenshot.sh",
        "dev-server/bin/smoke.sh",
        "dev-server/bin/canvas-rects.sh",
        "agents/design-critic.md",
        "agents/graphic-design-critic.md",
        "agents/a11y-critic.md"
      ],
      "docsUrl": "https://github.com/vercel-labs/agent-browser"
    },
    {
      "id": "playwright",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "npx --no-install playwright --version",
        "expectExit": 0
      },
      "install": {
        "preferred": "npm i -g playwright && npx playwright install chromium"
      },
      "autoInstall": false,
      "fallbackBehavior": "Screenshot scripts use playwright as a fallback when agent-browser is missing. The rendered export formats (PNG/PDF/SVG/HTML/PPTX/Canva) require it outright. NOTE: the `--version` check above only proves the npm package resolves — the Chromium BINARY is a separate install (`npx playwright install chromium`). If it's missing, exports fail at runtime with an actionable message from dev-server/bin/_pw-launch.mjs; screenshot helpers fall back to agent-browser.",
      "usedBy": [
        "dev-server/bin/_pw-launch.mjs",
        "dev-server/bin/_screenshot-playwright.mjs",
        "dev-server/bin/_png-playwright.mjs",
        "dev-server/bin/_pdf-playwright.mjs",
        "dev-server/bin/_svg-playwright.mjs",
        "dev-server/bin/_html-playwright.mjs",
        "dev-server/bin/_pptx-playwright.mjs",
        "dev-server/bin/_enumerate-artboards-playwright.mjs",
        "dev-server/bin/screenshot.sh",
        "dev-server/bin/_canvas-rects-playwright.mjs",
        "dev-server/bin/canvas-rects.sh"
      ],
      "docsUrl": "https://playwright.dev"
    },
    {
      "id": "svg2pptx",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "svg2pptx --version",
        "expectExit": 0
      },
      "install": {
        "preferred": "pip install svg2pptx",
        "darwin": "pipx install svg2pptx || python3 -m pip install svg2pptx",
        "linux": "pipx install svg2pptx || python3 -m pip install svg2pptx"
      },
      "autoInstall": false,
      "fallbackBehavior": "PPTX/Canva export uses svg2pptx (Python) to emit NATIVE, editable PowerPoint shapes + text boxes from the artboard SVG — editable in PowerPoint / Keynote / Canva. Without it (or python3), export falls back to a non-editable PNG-per-slide deck (faithful, universal, Canva-safe). Set MAUDE_SVG2PPTX to a custom svg2pptx executable (e.g. a venv path, or `python3 -m svg2pptx`) when it isn't on PATH. See DDR-069.",
      "usedBy": ["dev-server/exporters/pptx.ts"],
      "docsUrl": "https://github.com/benouinirachid/svg2pptx"
    },
    {
      "id": "maude",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "maude --version",
        "expectExit": 0
      },
      "install": {
        "preferred": "npm i -g @1agh/maude"
      },
      "autoInstall": false,
      "fallbackBehavior": "Slash commands still work; `maude` CLI provides faster scaffolding (init / config / design serve) without going through Claude.",
      "usedBy": ["commands/init.md", "skills/design/SKILL.md"],
      "docsUrl": "https://github.com/1aGh/maude"
    },
    {
      "id": "kg",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "kg version",
        "expectExit": 0,
        "minVersion": "1.5.1"
      },
      "install": {
        "preferred": "Install kgai >= 1.5.1 using https://github.com/kgaidev/kgai installation instructions; reuse the existing trusted store. Classic file workflows need no kgai installation."
      },
      "autoInstall": false,
      "fallbackBehavior": "Design DS/canvas/brand decisions are not recorded to the kgai graph; the classic .ai/ path (via /flow:record-ddr) and on-disk sidecars are unchanged.",
      "usedBy": ["skills/design-system/SKILL.md", "commands/edit.md"],
      "docsUrl": "https://github.com/kgaidev/kgai"
    },
    {
      "id": "jq",
      "type": "system-tool",
      "hardness": "soft",
      "check": {
        "command": "jq --version",
        "expectExit": 0
      },
      "install": {
        "darwin": "brew install jq",
        "linux": "apt-get install -y jq || dnf install -y jq",
        "win32": "winget install jqlang.jq"
      },
      "autoInstall": false,
      "fallbackBehavior": "Slash commands' bash blocks that read .ai/workflows.config.json via jq degrade to inline node one-liners; harder to read but functional.",
      "usedBy": [
        "dev-server/bin/bootstrap-check.sh",
        "dev-server/bin/server-up.sh",
        "dev-server/bin/canvas-rects.sh"
      ]
    },
    {
      "id": "askuserquestion-mcp",
      "type": "mcp",
      "hardness": "soft",
      "check": {
        "mcp": "AskUserQuestion",
        "tool": "ask"
      },
      "fallbackBehavior": "Discovery + critic-panel rounds fall back to numbered-prose chat. Slower, fewer options per round, no preview side-pane.",
      "usedBy": ["skills/design-system/SKILL.md", "commands/setup-ds.md", "commands/new.md"],
      "docsUrl": "https://docs.claude.com/en/docs/claude-code"
    },
    {
      "id": "claude",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "claude --version",
        "expectExit": 0
      },
      "install": {
        "preferred": "npm i -g @anthropic-ai/claude-code",
        "darwin": "brew install --cask claude-code"
      },
      "autoInstall": false,
      "fallbackBehavior": "Phase 31 (DDR-123) — the native ACP chat sidepanel drives the user's OWN installed `claude` CLI on their Pro/Max subscription (never API billing). Without it the panel shows the not-connected explainer ('run `claude` in a terminal and `/login`'); every other design surface is unaffected.",
      "usedBy": ["dev-server/acp/probe.ts", "dev-server/acp/bridge.ts"],
      "docsUrl": "https://docs.claude.com/en/docs/claude-code"
    },
    {
      "id": "whisper-cpp",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "whisper-cli --help",
        "expectExit": 0
      },
      "install": {
        "darwin": "brew install whisper-cpp",
        "linux": "https://github.com/ggml-org/whisper.cpp#quick-start",
        "preferred": "https://github.com/ggml-org/whisper.cpp"
      },
      "autoInstall": false,
      "fallbackBehavior": "feature-ai-media-generation Phase 2 (DDR-164) — `maude design transcribe` uses whisper.cpp for local, no-key, word-timestamped subtitles (the DEFAULT subtitle path). Without it, transcription falls back to cloud STT (ElevenLabs Scribe / Groq Whisper) via a provider key. whisper.cpp also needs a ggml model file (--model / $MAUDE_WHISPER_MODEL); it ships no default and does not auto-download — see https://huggingface.co/ggerganov/whisper.cpp (e.g. ggml-large-v3-turbo.bin).",
      "usedBy": ["dev-server/bin/transcribe.sh", "dev-server/bin/_transcribe.mjs"],
      "docsUrl": "https://github.com/ggml-org/whisper.cpp"
    },
    {
      "id": "ffmpeg",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "ffmpeg -version",
        "expectExit": 0
      },
      "install": {
        "darwin": "brew install ffmpeg",
        "linux": "apt-get install -y ffmpeg || dnf install -y ffmpeg",
        "preferred": "https://ffmpeg.org/download.html"
      },
      "autoInstall": false,
      "fallbackBehavior": "feature-scene-aware-keyframes — the `ffmpeg` tier of `maude design smart-frames` (skill footage-keyframes) uses ffmpeg scene-detection to pick keyframes at real shot cuts. Without it, the extractor falls back to the blind Chromium tier (probe-footage, even-spaced) — still works, just not scene-aware.",
      "usedBy": ["dev-server/bin/smart-frames.sh", "dev-server/bin/_smart-frames.mjs"],
      "docsUrl": "https://ffmpeg.org"
    },
    {
      "id": "mlx-vlm",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "MAUDE_VENV=\"${XDG_CACHE_HOME:+$XDG_CACHE_HOME/maude}\"; MAUDE_VENV=\"${MAUDE_VENV:-$HOME/.maude}/mlx-venv\"; \"$MAUDE_VENV/bin/python3\" -c \"import mlx_vlm\" 2>/dev/null || python3 -c \"import mlx_vlm\"",
        "expectExit": 0
      },
      "install": {
        "darwin": "MAUDE_VENV=\"${XDG_CACHE_HOME:+$XDG_CACHE_HOME/maude}\"; MAUDE_VENV=\"${MAUDE_VENV:-$HOME/.maude}/mlx-venv\"; python3 -m venv \"$MAUDE_VENV\" && \"$MAUDE_VENV/bin/pip\" install -U mlx-vlm",
        "preferred": "https://github.com/Blaizzy/mlx-vlm"
      },
      "autoInstall": false,
      "fallbackBehavior": "feature-scene-aware-keyframes — OPT-IN. The `gemma` tier of `maude design smart-frames` runs a local Gemma-4 MLX scout (Apple Silicon only) to flag semantic action beats. Without it, smart-frames uses Ollama (if a gemma3 vision model is pulled), else the ffmpeg or blind tier — no model download required. The scout also needs a Gemma-4 MLX model (--engine gemma / $MAUDE_GEMMA_MODEL, one-click in Studio Settings → Video).",
      "usedBy": ["dev-server/bin/_smart-frames.mjs"],
      "docsUrl": "https://github.com/Blaizzy/mlx-vlm"
    },
    {
      "id": "ollama",
      "type": "cli",
      "hardness": "soft",
      "check": {
        "command": "which ollama",
        "expectExit": 0
      },
      "install": {
        "darwin": "curl -fsSL https://ollama.com/install.sh | sh && ollama pull gemma3:4b",
        "linux": "curl -fsSL https://ollama.com/install.sh | sh && ollama pull gemma3:4b",
        "preferred": "https://ollama.com/download"
      },
      "autoInstall": false,
      "fallbackBehavior": "feature-scene-aware-keyframes — OPT-IN alternative scout runtime. The `gemma` tier of `maude design smart-frames` can run its semantic-beat scout through a local Ollama server with a vision-capable gemma3 model (`ollama pull gemma3:4b`) instead of mlx-vlm — the simpler install story (one app, no Python; works beyond Apple Silicon). mlx-vlm is preferred when both are present. Without either, smart-frames uses the ffmpeg or blind tier.",
      "usedBy": ["dev-server/bin/_smart-frames.mjs"],
      "docsUrl": "https://ollama.com"
    }
  ]
}
