Files
msd-core/docs/how-to/install-on-your-runtime.md
Jakub Zych 6cfa0c55d2 refactor: drop 12 runtimes, keep Claude, Codex, OpenCode, Cursor, ZCode, Antigravity
Removes kilo, kimi, kimi-code, copilot, windsurf, augment, trae, qwen, hermes,
cline, codebuddy and pi end to end: capability descriptors, installer branches
and converters (bin/install.js 14.9k -> 11.2k lines), TypeScript converters,
hook surfaces and runtime homes, review lanes qwen/kimi-code, the two pi
migrations, Kimi payload normalization in the hook guards, dead hostBehaviors
vocabulary, launcher home probes, fixtures, runtime-specific tests and the
prose that presented them as supported.

Installer output for the six kept runtimes is byte-identical to before the
prune. The Kimi tool-vocabulary tests in workflow-guard, read-guard and
read-injection-scanner are left in place pending a decision.
2026-10-06 20:02:40 +02:00

357 lines
23 KiB
Markdown

# How to install MSD Core on your runtime
Install MSD Core (`@golem15/msd-core`) into the AI coding runtime you use every day. This guide gives you the standard installer path for each supported runtime, then covers the manual path for machines without Node.js.
**What you need:** Node.js 18+ and npm (or npx). If you do not have Node.js, jump to [Installing without Node.js](#installing-without-nodejs).
---
## Why the installer is required
MSD Core ships agent and command files in Claude Code's native frontmatter format. Each supported runtime expects a different schema, directory layout, and command-invocation syntax. The installer performs the necessary transformations — for example, converting tool lists and colour values for OpenCode and writing TOML agent entries for Codex.
**Do not copy files from `agents/` or `commands/` directly.** Doing so bypasses the transformations and produces schema-validation errors or missing commands.
---
## Standard install
Run the installer from any directory. It prompts for your runtime and whether to install globally (all projects) or locally (this project only).
```bash
npx @golem15/msd-core@latest
```
That is the only command you need for a fresh install or to re-run the installer after switching runtimes.
---
## Per-runtime instructions
### Claude Code
```bash
npx @golem15/msd-core@latest --claude --global
```
Skills land in `~/.claude/`. Commands appear as `/msd-*` slash commands in your next Claude Code session. Restart Claude Code to pick them up.
**Installing at both `--global` and `--local`.** This is a supported configuration (different projects sometimes need different customizations), but Claude Code's own trigger-resolution rules — personal scope overrides project scope, and a skill overrides a same-named command — both point the same direction: the global skill always wins the `/msd-<name>` trigger over the local command. MSD Core detects this and prints which scope is winning right after install completes (and surfaces the identical fact from `/msd-health` as diagnostic `W028`); it is an advisory, not a failure — the install itself still succeeds. At **global** scope, the winning skill's workflow-spec reference resolves at runtime against your working directory first, so a project with its own `.claude/msd-core/` still gets its own specs even though the global skill is what Claude Code invokes — see [Interpret install-shadow warnings](interpret-install-shadow-warnings.md) for what the warning means, how to read which scope wins, and the limits of that resolution (it does not extend to the skill's `references/`/`templates/` includes).
**Override the install directory:**
```bash
CLAUDE_CONFIG_DIR=~/.claude-alt npx @golem15/msd-core@latest --claude --global
```
**Hook coverage**
MSD registers the following Claude Code hook events automatically on install:
| Event | Hook | Purpose |
|---|---|---|
| `SessionStart` | `msd-check-update.js`, `msd-session-state.sh` | Update check, session orientation |
| `PostToolUse` | `msd-context-monitor.js`, `msd-read-injection-scanner.js`, `msd-phase-boundary.sh`, `msd-graphify-update.sh` | Context monitoring, read-time scan, phase boundary detection |
| `PreToolUse` | `msd-prompt-guard.js`, `msd-read-guard.js`, `msd-workflow-guard.js`, `msd-worktree-path-guard.js`, `msd-agent-isolation-guard.js`, `msd-secret-read-guard.js`, `msd-validate-commit.sh` | Prompt guard, read-before-edit, workflow + worktree safety, agent-dispatch isolation, secret-file read protection, commit validation |
| `SubagentStop` | `msd-context-monitor.js` | Context headroom tracking after subagent completion |
| `Stop` | `msd-context-monitor.js` | Context headroom tracking before model stop |
| `PreCompact` | `msd-context-monitor.js` | Context awareness before conversation compaction |
| `FileChanged` (matcher: `config.json`) | `msd-config-reload.js` | Hot-reloads `.planning/config.json` context mid-session when you edit your MSD config — no session restart required |
The `FileChanged` hook is always-on and a no-op when `.planning/config.json` does not exist in the project. Editing that file while a session is running injects an `additionalContext` summary of the new configuration so the agent picks up model overrides, workflow toggles, and hook settings immediately.
---
### Claude Code — native plugin install
MSD Core ships a `.claude-plugin/plugin.json` manifest, which enables installation and lifecycle management through the Claude Code plugin system. This path is **additive** — the npm installer above remains fully supported, and the two approaches differ in namespace and lifecycle.
**Install-time config does not apply here.** The native plugin path (this section, the skills-dir load below, and marketplace discovery) materializes the repository tree directly — there is no install step. Install-time config that the npm installer bakes into generated artifact files at install time (confirmed for `agent_tools`; the same applies architecturally to `model_overrides` and other install-time-only keys) is never applied on this path, and running `claude plugin update` does not change that. If your setup relies on install-time config, use the npm installer above.
**Install paths**
*Option A — marketplace or git install (once listed):*
```bash
claude plugin install msd-core
```
*Option B — zero-friction skills-dir load:* Claude Code automatically discovers any directory under `~/.claude/skills/` that contains a `.claude-plugin/plugin.json` as a plugin. To use msd-core this way, place (or symlink) the msd-core package directory there:
```bash
# Example: place the package under ~/.claude/skills/msd-core/
# Claude Code loads it as msd-core@skills-dir on the next session start.
# No explicit install step required.
```
**Command namespace**
Plugin commands are namespaced as `/msd-core:<command>` — for example, `/msd-core:plan-phase`. This is distinct from the classic npm/file-copy installer, which exposes commands as `/msd:<command>`. Use whichever namespace corresponds to your install method.
**Lifecycle**
```bash
claude plugin enable msd-core
claude plugin disable msd-core
claude plugin update msd-core
```
**Hooks**
The plugin wires msd-core's always-on guard and update hooks automatically via `hooks/hooks.json`. No manual hook registration is required.
**Prerequisites**
The `msd-tools` binary (installed as part of the `@golem15/msd-core` npm package) must be available on your `PATH` for msd commands to execute their backing logic. The plugin delivers the command, agent, and hook surface; the npm package delivers the runtime CLI.
Node.js (`node`) must also be available on your `PATH`. The plugin's always-on guard hooks (wired in `hooks/hooks.json`) are invoked as `node "${CLAUDE_PLUGIN_ROOT}/hooks/<script>"`. Some Claude Code distributions ship as a standalone binary and do not expose a `node` executable on `PATH`; in those environments the plugin's hooks will not run. Verify with `node --version` before relying on the plugin hooks.
**Runtime build (self-healing).** The runtime CLI's compiled modules under `msd-core/bin/lib/*.cjs` are build artifacts (ADR-457): they are compiled from `src/*.cts` by `npm run build:lib` and shipped prebuilt in the npm tarball. A plugin-marketplace or git-clone install materializes the repository tree directly and never runs that build step, so those files are initially absent. The CLI heals this automatically: the first `msd-tools` invocation detects the missing output and compiles it once (using the bundled `typescript` devDependency), then proceeds normally. You may see a one-time `msd: runtime library not built — compiling once…` notice on stderr; subsequent commands are unaffected. If auto-build cannot run (for example `node_modules` was pruned to production-only and `typescript` is unavailable), the CLI prints an actionable message telling you to run `npm install && npm run build:lib` in the plugin directory.
#### Claude plugin marketplace discovery (ZCODE and compatible runtimes)
MSD Core also ships a `.claude-plugin/marketplace.json` marketplace manifest (sibling to `plugin.json`). Runtimes that implement the Claude plugin marketplace contract — such as ZCODE — can discover and install MSD Core from a custom marketplace source without a manual clone:
1. In your runtime's plugin UI, add a custom marketplace source pointing at `golem15/msd-core` (GitHub `owner/repo` form).
2. MSD Core appears in the catalog and can be installed directly from the UI.
This path is **additive** and changes nothing about the Claude Code plugin install above (`.claude-plugin/plugin.json` is unchanged). The marketplace entry's `source` is `./`, so it reuses `plugin.json`'s `commands` / `skills` / `hooks` mapping. The catalog version tracks `package.json` (it lives at `plugins[0].version` and is stamped by the release version-sync), so the version you see in the marketplace matches the npm release.
---
### OpenCode
```bash
npx @golem15/msd-core@latest --opencode --global
```
The installer writes four surfaces under `~/.config/opencode/` (XDG) or `~/.opencode/`: flat slash commands in `commands/` (plural — the directory OpenCode discovers slash commands from, #2329), file-based subagents in `agents/`, on-demand skills in `skills/<name>/SKILL.md`, and a native plugin in `plugins/msd-core.js`. It converts agent frontmatter to OpenCode's schema — removing the `tools:` field and converting colour values to hex — and emits each skill with spec-compliant frontmatter (`name` matching the skill directory plus a `description`). Skills are loaded on demand via OpenCode's native skill tool; commands remain invokable as `/msd-*`. See [Installing without Node.js — OpenCode transformations](#opencode--required-transformations) if you need to understand what changes.
**MSD safety hooks on OpenCode.** OpenCode does not register lifecycle hooks the way Claude Code does (its `hooksSurface` is `none`), so MSD's prompt-injection guard, read-before-edit guard, injection scanner, and context monitor would otherwise be inert. The bundled plugin (`plugins/msd-core.js`) closes that gap: OpenCode auto-discovers `plugins/*.{ts,js}` files under its config directory at startup and the adapter bridges OpenCode's event bus (`tool.execute.before`/`after`, `session.created`, `file.edited`) onto MSD's existing hook scripts, spawning them as subprocesses. No `opencode.json` entry is needed — the plugin is loaded by directory auto-discovery (the config `plugin` array is for npm packages only). A blocking hook aborts the tool call; an advisory hook surfaces its message without blocking.
**Your plugin directory is pinned to CommonJS (accepted trade-off, #2544).** MSD's adapter is a CommonJS `.js` file, and Node decides a `.js` file's module type by walking up for the nearest `package.json`. So the installer writes a minimal `{"type":"commonjs"}` marker into the plugin directory itself — `plugins/package.json` on OpenCode. It is written only when MSD actually stages its adapter there, it never overwrites a `package.json` MSD did not write, and uninstall removes only its own.
The trade-off: that marker shadows your config root for **every** `.js` file in that directory, not just MSD's. If you author your own plugins as ESM `.js` and rely on a `"type": "module"` at the config root, they will stop resolving as ESM. This is deliberate — it is strictly narrower than the pre-#2544 behavior, which wrote the marker over `<configRoot>/package.json` itself and destroyed whatever was there — but it is a real constraint rather than a pure improvement, which is why it is stated here.
**Mitigation:** author your own plugins as `.ts`. OpenCode compiles plugin TypeScript with Bun, and a `package.json` `type` field does not affect `.ts` resolution — so a `.ts` plugin is unaffected by the marker. Failing that, keep ESM plugins outside the auto-discovered directory and load them as npm packages via the config `plugin` array.
**Override the install directory:**
```bash
OPENCODE_CONFIG_DIR=~/.config/opencode-alt npx @golem15/msd-core@latest --opencode --global
```
---
### Codex
```bash
npx @golem15/msd-core@latest --codex --global
```
Skills land in `~/.codex/skills/msd-*/SKILL.md`. Agents are written as standalone `~/.codex/agents/msd-*.toml` files, which Codex auto-discovers — that is the sole registration source for each role; `config.toml` only carries the shared `[agents]` dispatch-tuning scalar (`max_depth`), not a per-role table (#2406). Restart Codex (or run `codex --reload`) after install.
**Minimum supported version:** Codex CLI 0.130.0. Earlier versions had additional skill-root scanning that can produce duplicate listings.
**Hook coverage**
MSD registers the following Codex hook event automatically on install (requires Codex CLI 0.137.0+ for the stable hook-event schema):
| Event | Hook | Purpose |
|---|---|---|
| `SessionStart` | `msd-check-update.js` | Update check at session open; Windows installs also emit a `commandWindows` field pointing to the `.cmd` shim so Codex picks the correct executor on Windows without requiring per-OS config regeneration |
**Context warnings are not supported on Codex (#2586).** Earlier revisions of MSD also registered `SubagentStart`/`Stop`/`PostToolUse` (plus, briefly, six more events) against `msd-context-monitor.js` for context-headroom tracking. That hook only produces a warning by reading a remaining-context-percentage bridge file that `msd-statusline.js` — Claude Code's own statusline mechanism — writes; Codex never installs a statusline writer, so every one of those registrations fired as a guaranteed silent no-op, every invocation, with no exceptions. MSD no longer copies or registers `msd-context-monitor.js` on a fresh Codex install; a reinstall over an older MSD install removes the stale registrations and the now-unreferenced script automatically. Agent-facing context warnings and MSD phase/lifecycle display remain unsupported capabilities on Codex (see `capabilities/codex/capability.json`) until a real metrics producer exists for this runtime — native Codex `/statusline` configuration is a separate, not-yet-implemented surface.
All registered hooks are managed by MSD and are removed cleanly on `--uninstall`.
---
### Cursor
```bash
npx @golem15/msd-core@latest --cursor --global
```
Artifacts land in `~/.cursor/`. MSD installs skills (`~/.cursor/skills/msd-*/SKILL.md`), agents, and rule references. Cursor exposes each skill once in the `/` menu while keeping it available for contextual model invocation. Upgrading removes manifest-managed legacy `~/.cursor/commands/msd-*.md` copies that previously duplicated those menu entries; unknown user-authored command files are preserved.
**Override the install directory:**
```bash
CURSOR_CONFIG_DIR=~/.cursor-alt npx @golem15/msd-core@latest --cursor --global
```
---
### Antigravity
```bash
npx @golem15/msd-core@latest --antigravity --global
```
The installer auto-detects the Antigravity config directory (`~/.gemini/antigravity`, `~/.gemini/antigravity-ide`, or `~/.gemini/antigravity-cli`). Uses Gemini-compatible settings policy. Global skills and agents install under `~/.gemini/config/skills/` and `~/.gemini/config/agents/` — the directories Antigravity scans for machine-local discovery (#3738); the config directory above holds settings and MSD's runtime files.
**Override the install directory:**
```bash
ANTIGRAVITY_CONFIG_DIR=~/.gemini/antigravity-alt npx @golem15/msd-core@latest --antigravity --global
```
---
### ZCode
```bash
npx @golem15/msd-core@latest --zcode --global
```
[ZCode](https://zcode.z.ai/en) is Z.ai's desktop Agentic Development Environment for the GLM-5.2 model. MSD installs skills (nested `SKILL.md` bundles), slash commands, and subagents under `~/.zcode/`:
- **Skills** → `~/.zcode/skills/msd-<name>/SKILL.md` (invoke with `$msd-<name>` in chat)
- **Commands** → `~/.zcode/commands/msd-<name>.md` (invoke with `/msd-<name>`)
- **Subagents** → `~/.zcode/agents/msd-<name>.md`
ZCode's skill format is identical to Claude Code's, so no runtime-specific converter is required — MSD lands as a pure declarative descriptor with no hardcoded installer branches. ZCode also natively imports skills and MCP config from `~/.claude`; if you install MSD for **both** Claude and ZCode, you may see duplicate MSD skills inside ZCode, which is expected. To connect ZCode's MCP servers to MSD's companion server, see [how to connect the MSD MCP server](connect-msd-mcp-server.md).
MSD's hook-automation and native-MCP-registration integrations are not yet wired for ZCode — both are blocked on ZCode not yet publishing the on-disk config format for its plugin `Hook` component or the settings filename/schema for its MCP store. See the [`## zcode`](../reference/host-integration-capability-matrix.md#zcode) section of the host-integration capability matrix for the cited source URLs.
---
## Local vs global install
All examples above use `--global`, which installs MSD once for your user account. To scope an install to a single project, replace `--global` with `--local`:
```bash
npx @golem15/msd-core@latest --claude --local
```
A local install writes into the `.claude/` directory at your project root. Local install settings take precedence over global ones when both exist.
---
## Installing prerelease editions (Next / Nightly / Insiders / Preview)
Prerelease editions of runtimes (Cursor Nightly, VS Code Insiders, Codex preview channels, etc.) read from a sibling config directory. Set the matching `*_CONFIG_DIR` env var before running the installer:
```bash
CURSOR_CONFIG_DIR=~/.cursor-nightly npx @golem15/msd-core@latest --cursor --global
```
Select the corresponding stable runtime in the installer prompt. MSD does not enumerate prerelease editions as separate named runtimes — they are best-effort via this env-var mechanism and are not separately tested in release CI.
---
## Sharing one config root across environments
When one config root (`~/.claude`, `~/.config/opencode`, …) is mounted or synced into
machines with different Node.js layouts — a host plus Docker containers bind-mounting the
same directory, or WSL and Windows sharing a drive — install with `--portable-hooks`
(or `MSD_PORTABLE_HOOKS=1`):
```bash
npx @golem15/msd-core@latest --claude --global --portable-hooks
```
Hook script paths are emitted `$HOME`-relative, and every managed JavaScript hook command
resolves its node binary at hook-fire time instead of depending on whichever machine ran
the installer (#3662): portable installs route through a staged
`hooks/msd-node-runner.sh` resolver (the install-time node path first, then `command -v
node`, then the well-known layouts); non-portable installs carry an equivalent inline
fallback chain. The install-time path is always tried first, so GUI launches with a
minimal `PATH` keep working, and a bare `node` lookup is never depended on. Re-running
install or update from any of the environments converges stale runner paths — no mixed
state where some hooks work in one environment and the rest in another.
To pin down which node a given environment picks, run the resolver directly with
`MSD_NODE_RUNNER_NO_FALLBACKS=1` (first-argument-only resolution) — it prints a stderr
diagnostic and exits non-zero when nothing resolves.
---
## Local installs across several git worktrees
A local (`--local`) install writes the includes that point at MSD's own installed
files as absolute paths — the path the installer resolved at install time. For a
single checkout that is invisible and works fine.
It stops working once the same repository is checked out more than once. Each git
worktree gets its own `.claude/` copy, but every one of those copies points back at
the checkout that ran the installer. So a worktree runs its own `msd-tools.cjs`
(correctly resolved through `git rev-parse --show-toplevel`) while reading its
workflow prose out of a different checkout — and the moment you update that one
checkout, every other worktree is executing new instructions against an old engine,
with no way to stage the update.
Install with `--relative-includes` (or `MSD_RELATIVE_INCLUDES=1`) to write the
includes relative to the project instead:
```bash
npx @golem15/msd-core@latest --claude --local --relative-includes
```
Every emitted `@` include then reads `@.claude/msd-core/...` rather than
`@/absolute/path/to/checkout/.claude/msd-core/...`, so each worktree resolves its
own copy and the worktrees become independent.
Notes:
- **It is opt-in and stays opt-in.** Absolute includes work for a single checkout,
which is most people; the flag exists for those who need it.
- **Global installs are unaffected.** They keep their `$HOME`-relative form, which
is already checkout-independent.
- **The runtime launcher keeps its absolute fallbacks.** The shell snippet that
locates `msd-tools.cjs` probes `${CLAUDE_CONFIG_DIR:-$HOME/.claude}` and one such
default per runtime; those are shell word expansions, not includes, and a relative
value there would resolve against the current shell's directory rather than the
project. The launcher already probes `$(git rev-parse --show-toplevel)/.claude`
first, so it finds the current worktree before it ever reaches those defaults.
- **`--relative-includes` with `--global` does nothing.** The flag is only consulted
for local installs.
---
## Installing without Node.js
If you cannot run `npx` (for example, on a Windows machine without Node.js), you have two options.
**Option A — Use a machine that has Node.js.** Any machine with Node.js will do: WSL, a Linux VM, a CI runner, or a Docker container. Run the installer there, then copy the output directory to your target machine. For OpenCode:
```bash
npx @golem15/msd-core@latest --opencode --global
# Then copy ~/.config/opencode/agents/ to the Windows machine
```
**Option B — Manually transform the source files.** The agent source files live in `agents/` in the MSD Core repository and are in Claude Code's native frontmatter format. Each runtime expects a different shape. For the exact field transformations per runtime, see [Manual install / no-Node.js setup](../USER-GUIDE.md#manual-install--no-nodejs-setup) in the User Guide, which covers the OpenCode transformations in full detail and points to the installer's `convert*Frontmatter` functions for other runtimes.
---
## After install
Restart your runtime to pick up new commands and agents. Then start a new project or onboard an existing repo:
```bash
/msd-new-project # greenfield project
/msd-onboard # existing codebase
```
If the command is not found after restart, verify the install directory matches the runtime's expected config path. The prerelease-editions section above covers the most common mismatch.
### "… is not on your PATH" after install
If the installer's global bin directory is not on your `PATH`, it prints a one-time warning with a copy-paste command for your shell. The suggestion list covers `zsh`, `bash`, and `fish` (plus PowerShell, cmd.exe, and Git Bash on Windows). For fish, run the line it prints:
```fish
fish_add_path -- '/path/to/global/bin'
```
If the directory is already on your PATH but the installer still warns, open a new fish session (`exec fish`) to pick up the change.
---
## Related
- [Your first project](../tutorials/your-first-project.md)
- [Update MSD Core](update-msd.md)
- [Configuration](../CONFIGURATION.md)
- [Docs index](../README.md)