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.
52 KiB
Host Integration Capability Matrix
This document is the maintainer-facing source of truth for the hostIntegration block in every
capabilities/<cli>/capability.json runtime descriptor. Every per-CLI axis value is either:
- documented — backed by a cited authoritative source and evidence quote, or
undocumented— the explicit fail-closed sentinel used when the CLI's public documentation does not state a value for that axis.undocumentedvalidates in the registry but never propagates into effective axes: negotiation degrades closed to the safe default.
Values are generated from per-CLI documentation research (Context7 + official docs). They are
consumed verbatim by gen:capability-registry and validated by capability-validator.cjs.
Axes legend
| Axis | Meaning |
|---|---|
embeddingMode |
Whether the CLI exposes an in-process programmatic API (imperative) or integrates purely through configuration files (declarative). |
commandSurface |
How slash commands are registered: slash-file (markdown), slash-toml (TOML), slash-programmatic (code API), palette, prose-only. |
modelMode |
Whether extensions can programmatically request or supply a model (active) or select only by config (passive). |
hookBus |
Who owns the hook lifecycle: host (the CLI fires hooks), engine (VS Code/Electron extension host), none. |
stateIO |
Filesystem access model: filesystem (full local FS), sandboxed-storage, session-log-append. |
transport |
Integration transport: mcp (Model Context Protocol), native-extension. |
runtime |
Plugin/extension execution runtime: node, bun, python, go, rust, electron, sandboxed-web, other. |
effortSurface |
How reasoning effort reaches this host: argv (deliverable as an argument on the host's own invocation), none (the host exposes no reasoning-effort mechanism), or undocumented. Added by #2481; there is deliberately no config-file member — the only host that ever had one (Gemini CLI's thinkingConfig) was removed as a sunset runtime, and naming a member with no host would be a guess. |
dispatch sub-axes
| Sub-axis | Meaning |
|---|---|
namedDispatch |
Whether agents can be invoked by name (true/false/undocumented). |
nested |
Whether subagents can themselves spawn subagents (true/false/undocumented). |
maxDepth |
Maximum nesting depth (integer; -1 = unbounded; undocumented). |
background |
Whether subagents can run asynchronously in the background (true/false/undocumented). |
subagentToolkit |
Tool surface available to subagents: full, read-only, built-in-only, or undocumented. built-in-only means the host ships a fixed set of built-in subagent types whose tool surfaces differ from one another, so no single full/read-only value describes them; it degrades closed to read-only in the negotiated axes. |
backgroundDispatch |
Whether a BACKGROUND-dispatched sub-agent can itself spawn further named sub-agents — the #853 discriminator (true/false/undocumented). |
Interface points
| Point | Meaning |
|---|---|
command |
Slash-command routing and invocation capability. |
dispatch |
Subagent/multi-agent dispatch capability. |
model |
Programmatic model selection capability. |
hooks |
Lifecycle hook registration capability. |
state |
Filesystem/state I/O capability. |
artifact |
Artifact delivery (skills, commands) surface capability. |
Trigger precedence (#2871 Phase 2 — adjacent to, not part of, hostIntegration)
runtime.triggerPrecedence (an ordered list of trigger-bearing kind names, highest priority
first) is declared as a sibling of hostIntegration in capability.json's runtime body, not
inside it — it is not researched per-CLI documentation the way the axes above are, so it carries
no per-host Source/Evidence row. Only commands and skills are members of the vocabulary;
agents are excluded because they are not trigger-bearing (a /msd-<name> a user
types) — an agent is invoked through named/subagent_type dispatch, the separate dispatch
interface point above, never through the command interface point. Every shipped runtime
descriptor declares the same value, ["skills", "commands"] (skills wins a same-scope collision),
matching capability-validator.cjs's DEFAULT_TRIGGER_PRECEDENCE — the axis is
required-with-default (absence resolves to that default) so a third-party descriptor authored
before this phase keeps validating unchanged. runtime-artifact-layout.cts's
resolveTriggerSurface reads it to decide the winner among same-trigger candidates once scope
rank (Install Scope Module) has already been applied. See CONTEXT.md's Runtime Artifact Layout
Module entry and .msd/phase/feat-2871-trigger-resolution/40-design.md.
claude
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | imperative | https://code.claude.com/docs/en/agent-sdk/overview | "The Agent SDK offers hooks to execute custom code at critical points within the agent's lifecycle. These callback functions enable developer" |
| commandSurface | slash-file | https://code.claude.com/docs/en/agent-sdk/slash-commands | "Each custom command is a markdown file where the filename (without the .md extension) becomes the command name. The file content defines w" |
| modelMode | passive | https://code.claude.com/docs/en/agent-sdk/typescript | "setModel(model?: string): Changes the model (only available in streaming input mode) ... model overrides the default model for this subagent" |
| hookBus | host | https://code.claude.com/docs/en/agent-sdk/python | "HookEvent = Literal['PreToolUse', 'PostToolUse', 'PostToolUseFailure', 'UserPromptSubmit', 'Stop', 'SubagentStop', 'PreCompact', 'Notificati" |
| stateIO | filesystem | https://code.claude.com/docs/en/sandboxing | "The sandboxed Bash tool restricts file system access, granting read and write access to the current working directory and session temp direc" |
| transport | mcp | https://code.claude.com/docs/en/mcp | "Project-Scoped MCP Server Configuration in .mcp.json ... This JSON structure illustrates the format for a project-scoped MCP server configur" |
| runtime | node | https://code.claude.com/docs/en/agent-sdk/typescript | "import { query } from "@anthropic-ai/claude-agent-sdk"; ... pathToClaudeCodeExecutable (string) - Specifies the path to the Claude Code CLI" |
| effortSurface | argv | https://code.claude.com/docs/en/cli-reference ; claude --help |
--effort <level> is a documented flag on the host's own invocation, so MSD renders the resolved universal effort straight onto the argv it spawns (#2481). |
| dispatch.namedDispatch | true | https://code.claude.com/docs/en/agent-sdk/subagents | "agents: { 'code-reviewer': AgentDefinition({ description: 'Expert code reviewer.', ... }) } ... subagent_type: block.inp" |
| dispatch.nested | true | https://code.claude.com/docs/en/sub-agents | "As of Claude Code v2.1.172, a subagent can spawn its own subagents, allowing delegated tasks to split into parallel subt" |
| dispatch.maxDepth | 5 | https://code.claude.com/docs/en/sub-agents | "foreground subagents can spawn at any depth, blocking their parent until completion. Background subagents are limited to" |
| dispatch.background | true | https://code.claude.com/docs/en/sub-agents | "Subagents can run in the foreground, blocking the main conversation and passing permission prompts to you, or in the bac" |
| dispatch.subagentToolkit | full | https://code.claude.com/docs/en/sub-agents | "If all tools remain selected, the subagent inherits all tools available to the main conversation." |
| dispatch.backgroundDispatch | false | https://code.claude.com/docs/en/sub-agents | "Background subagents are limited to a depth of five and cannot spawn further, " |
| dispatch.isolation | harness-worktree | https://code.claude.com/docs/en/sub-agents ; Claude Code Agent tool (Agent(isolation="worktree")) |
The Claude Code Agent tool accepts an isolation="worktree" harness primitive — the host's own harness creates + binds a git worktree per executor; MSD passes the flag and calls no git itself (#2584) |
| dispatch.maxConcurrency | 20 | https://code.claude.com/docs/en/sub-agents | The subagent documentation states a default concurrent-subagent limit of 20, configurable via the CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS environment variable (#3673). |
Sources consulted:
- https://code.claude.com/docs/en/sub-agents
- https://code.claude.com/docs/en/agent-sdk/slash-commands
- https://code.claude.com/docs/en/agent-sdk/subagents
- https://code.claude.com/docs/en/agent-sdk/python
- https://code.claude.com/docs/en/agent-sdk/typescript
- https://code.claude.com/docs/en/agent-sdk/overview
- https://code.claude.com/docs/en/mcp
- https://code.claude.com/docs/en/sandboxing
- Context7 /websites/code_claude
- Context7 /llmstxt/code_claude_llms_txt
Cross-scope trigger shadowing and spec-root reachability (#2873, epic #2866 Phase 4, resolving #2218). MSD's claude artifactLayout installs global=[skills] and local=[commands, agents] (see "Trigger precedence" above). Claude Code's own documented precedence — personal overrides project, and a same-named skill overrides a same-named command — means both rules point the same direction when a user installs both scopes: the global skill always wins the /msd-<name> trigger, and the project-local .claude/msd-core/ spec tree the local command correctly points at becomes unreachable through that trigger, silently. MSD Core now (a) detects this at install time and from /msd-health (diagnostic W028) and prints which scope wins — an advisory only, exit code unchanged; and (b) for claude at global scope only, resolves the winning skill's own workflow-spec @-include at runtime rather than pre-expanding it: the skill body carries an explicit imperative instruction that resolves .claude/msd-core/workflows/<name>.md relative to the working directory first, falling back to ~/.claude/msd-core/workflows/<name>.md when no local tree exists. This is instruction-following, not the guaranteed inclusion a real @-include provides — it costs the agent one file read — and is deliberately confined to this one reference, in this one runtime, at this one scope: the skill's references//templates/ includes and the local scope's own emission are unchanged. See Interpret install-shadow warnings and Install on your runtime — Claude Code.
codex
Note: ADR-1239's host matrix lists Codex as
prose-only; current OpenAI Codex dev docs document slash-commands, socommandSurfaceisslash-filehere (docs are the source of truth).
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | declarative | https://developers.openai.com/codex/plugins/build | "No in-process programmatic API exists. Plugins integrate through: External command execution (hooks), MCP server processes, Configuration fi" |
| commandSurface | slash-file | https://github.com/openai/codex/blob/main/codex-rs/core-skills/src/loader.rs | "const SKILLS_FILENAME: &str = "SKILL.md"; ... Each skill is a folder with a SKILL.md file containing YAML frontmatter with name and descript" |
| modelMode | passive | https://github.com/openai/codex/blob/main/codex-rs/config/src/config_toml.rs | "pub model_provider: Option ... model is selected by config field; no programmatic model request API" |
| hookBus | host | https://github.com/openai/codex/blob/main/codex/codex-rs/hooks/src/lib.rs | "pub const HOOK_EVENT_NAMES: [&str; 10] = ["PreToolUse", "PermissionRequest", "PostToolUse", "PreCompact", "PostCompact", "SessionStart", "Us" |
| stateIO | filesystem | https://developers.openai.com/codex/concepts/sandboxing | "workspace-write: The default mode allowing Codex to read files, edit within the workspace, and run routine local commands inside that bounda" |
| transport | mcp | https://github.com/openai/codex/blob/main/codex-rs/config/src/config_toml.rs | "pub mcp_servers: HashMap<String, McpServerConfig> ... Definition for MCP servers that Codex can reach out to for tool calls." |
| runtime | node | https://github.com/openai/codex/blob/main/codex-cli/package.json | ""engines": {"node": ">=16"} ... The npm-distributed CLI wrapper is a Node.js script (#!/usr/bin/env node)" |
| effortSurface | argv | https://github.com/openai/codex/blob/main/codex-rs/exec/src/cli.rs ; https://developers.openai.com/codex/config-reference | model_reasoning_effort is a config.toml key and not a dedicated CLI flag, so the generic -c <key>=<value> override is the only argv route — which is still argv, hence argv rather than a config-file member (#2481). |
| dispatch.namedDispatch | true | https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/handlers/multi_agents_spec.rs | ""agent_type".to_string(), JsonSchema::string(Some(agent_type_description.to_string())) ... apply_role_to_config(&mut con" |
| dispatch.nested | true | https://developers.openai.com/codex/multi-agent | "agents.max_depth defaults to 1, which allows a direct child agent to spawn but prevents deeper nesting." |
| dispatch.maxDepth | 1 | https://developers.openai.com/codex/config-reference | "agents.max_depth: Maximum nesting depth allowed for spawned agent threads (root sessions start at depth 0; default: 1)" |
| dispatch.background | true | https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/handlers/multi_agents_spec.rs | "spawn_agent returns the spawned agent id immediately; a separate wait_agent tool polls for final status." |
| dispatch.subagentToolkit | full | https://developers.openai.com/codex/multi-agent | "Subagents inherit the sandbox policy and tool surface from the parent session." |
| dispatch.backgroundDispatch | true | https://github.com/openai/codex/blob/main/codex-rs/core/templates/collab/experimental_prompt.md | "Sub-agents have access to the same set of tools as you do so you must tell them if they are allowed to spawn sub-agents themselves or not." The config (codex-rs/config/src/config_toml.rs) exposes an |
| dispatch.isolation | orchestrator-worktree | https://learn.chatgpt.com/docs/environments/git-worktrees ; https://github.com/openai/codex/blob/main/codex-rs/utils/cli/src/shared_options.rs | "Worktrees are available only in Codex in the ChatGPT desktop app." (no native CLI worktree) + codex exec --cd <dir> sets an explicit working root, so MSD creates+manages the worktree and points the executor at it (#2584) |
| dispatch.maxConcurrency | undocumented | https://developers.openai.com/codex/config-reference | agents.max_concurrent_threads_per_session is a documented config key, but the reference states no numeric default — "Codex chooses the default" — so there is no single value to cite (#3673). |
MSD integration status — Phase D dogfood complete (#2088, ADR-1239). Codex installs through the declarative embedding adapter (createDeclarativeAdapter → installRuntimeArtifacts); the hardcoded runtime === 'codex'/isCodex projection is folded into descriptor-driven runtime.hostBehaviors, and install/uninstall output is byte-parity-gated at the time (tests/fixtures/golden-install-parity/codex.json; superseded by the differential attribution check, #2724). Three capability upgrades land, each with a test driving the user-reachable surface:
- Skill root — global skills install to the canonical
$HOME/.agents/skills(Codex core-skillsloader.rsuser-scope root), not the deprecated$CODEX_HOME/skillsfallback; local skills install to<project>/.codex/skills. The global path is declared via the global skills-kindhome: ".agents"override, while the local kind intentionally has no home override. Pre-move global installs are migrated (stale~/.codex/skills/msd-*cleaned on both install and uninstall); local installs do not remove$HOME/.agents/skillsbecause those skills may be intentionally global. - Hook events (corrected #2586) — MSD registers the
SessionStartevent only, wired tomsd-check-update.js. TheSubagentStart/Stop/PostToolUse(#772) + six #2088 extended events (PreToolUse,PermissionRequest,PreCompact,PostCompact,SubagentStop,UserPromptSubmit) described in earlier revisions of this doc were routed throughmsd-context-monitor.js, which reads a remaining-context-percentage bridge file (${TMPDIR}/claude-ctx-{session_id}.json) that onlymsd-statusline.jswrites — a Claude-only mechanism Codex never installs. Every one of those events was therefore a guaranteed silent no-op on Codex (confirmed:readSentinelthrowsENOENTon every invocation, unconditionally). #2586 stops copying/registeringmsd-context-monitor.json fresh installs and cleans up a pre-#2586 install's stale registrations + orphaned script on reinstall/uninstall. Agent-facing context warnings and MSD phase/lifecycle display are consequently unsupported on Codex (capabilities/codex/capability.json'shostBehaviors.unsupportedFeatures: ["context-warnings","phase-lifecycle-display"]) — no working warning path existed before this change either, so nothing regresses. Native Codex/statuslineconfiguration remains a separate, out-of-scope surface. (The descriptorextendedHookEventsfield'sSubagentStop/Stop/PreCompactvalue is a pre-existing, unrelated drift against the fuller event setbin/install.jsused to register — not corrected by #2586.) - Dispatch tuning —
[agents] max_depth = 1is written explicitly into the managedconfig.tomlblock, pinning thedispatch.maxDepth: 1axis instead of relying on codex-cli's implicit default. BecausemaxDepth === 1,degradationForflattens MSD-hosted wave dispatch to single-level even thoughdispatch.nested/background/backgroundDispatchare alltrue. The block is a bare[agents]AgentsToml scalar table; it does not carry per-role[agents.msd-*]sub-tables — those pointedconfig_fileback at the standaloneagents/msd-*.tomlfiles Codex already auto-discovers, so emitting them was a duplicate role registration (Codex logged "Ignoring malformed agent role definition: duplicate agent role name" once per agent) removed in #2406.validateCodexConfigSchemapermits a known-scalar-only[agents]while still rejecting[[agents]]and unknown-key forms.
Sources consulted:
- https://github.com/openai/codex (repo via gh CLI)
- /openai/codex (Context7 library ID)
- https://github.com/openai/codex/blob/main/codex-rs/config/src/config_toml.rs
- https://github.com/openai/codex/blob/main/codex-rs/core/src/tools/handlers/multi_agents_spec.rs
- https://github.com/openai/codex/blob/main/codex-rs/core-skills/src/loader.rs
- https://developers.openai.com/codex/config-reference
- https://developers.openai.com/codex/plugins/build
- https://developers.openai.com/codex/multi-agent
- https://developers.openai.com/codex/cli/slash-commands
Documentation gaps:
- dispatch.maxDepth is configurable (Option with no documented upper bound); the documented default is 1 but the actual enforced maximum is not stated.
- dispatch.subagentToolkit: docs say subagents 'inherit the tool surface' but do not enumerate whether any tools are excluded.
- runtime: the Node.js entry point is a thin launcher shim; the actual agent execution runtime is a compiled Rust binary — axis classification is ambiguous.
opencode
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | imperative | https://opencode.ai/docs/plugins | "Plugins are JavaScript/TypeScript modules that export plugin functions; they register hooks via `import type { Plugin } from '@opencode-ai/p'" |
| commandSurface | slash-file | https://opencode.ai/docs/commands | ""Create markdown files in the commands/ directory to define custom commands." and "The markdown file name becomes the command name." |
| modelMode | active | /anomalyco/opencode (Context7) — packages/plugin/src/v2/promise/README.md | "ctx.aisdk.sdk(async (event) => { ... event.sdk = mod.createXai(event.options) }) and `ctx.aisdk.language((event) => { ... event.language =" |
| hookBus | host | https://opencode.ai/docs/plugins | "Host fires events including: tool.execute.before, tool.execute.after, session.created, session.compacted, session.deleted" |
| stateIO | filesystem | https://opencode.ai/docs/plugins | "Plugin context includes directory (working directory path), worktree (git worktree path), and $ ("Bun's shell API")" |
| transport | mcp | https://opencode.ai/docs/mcp-servers | ""OpenCode supports both local and remote servers." and "Once added, MCP tools are automatically available to the LLM"" |
| runtime | bun | https://opencode.ai/docs/plugins | ""$": Bun's shell API for executing commands" (plugin context property); "OpenCode runs bun install at startup"" |
| effortSurface | argv | https://opencode.ai/docs/cli ; opencode run --help |
--variant is accepted on opencode run, so the resolved effort is deliverable as an invocation argument (#2481). |
| dispatch.namedDispatch | true | https://opencode.ai/docs/agents | ""Subagents can be invoked: Automatically by primary agents for specialized tasks based on their descriptions. Manually b" |
| dispatch.nested | undocumented | no authoritative doc — searched: https://opencode.ai/docs/agents | — |
| dispatch.maxDepth | undocumented | no authoritative doc — searched: https://opencode.ai/docs/agents | — |
| dispatch.background | false | https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/effect/runtime-flags.ts ; https://github.com/anomalyco/opencode/issues/29638 | "experimentalBackgroundSubagents: enabledByExperimental(\"OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS\") — enabledByExperimental falls back to the experimental flag, and bool() defaults to false, so the Task tool's background parameter is hidden from the model unless the operator opts in by env var. #29638 (OPEN) confirms the session loop still tasks.pop()s one subtask at a time. (#2598 — corrects #2087, whose "v1.17 default-on in all modes" reading does not hold against current dev)" |
| dispatch.subagentToolkit | full | https://opencode.ai/docs/agents | "The 'general' subagent "Has full tool access (except todo), so it can make file changes when needed."" |
| dispatch.backgroundDispatch | false | https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/effect/runtime-flags.ts ; https://github.com/anomalyco/opencode/issues/29638 ; https://github.com/anomalyco/opencode/issues/14195 | "Concurrent dispatch requires the opt-in OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS flag (default false), so it cannot be relied on. #14195: "the session loop does tasks.pop() to grab a single subtask, awaits it, then continues the loop — so even 3 simultaneous Task calls run sequentially." Declaring true would overstate the capability, against the fail-closed posture negotiation is built for. (#2598 — corrects #2087)" |
| dispatch.isolation | orchestrator-worktree | https://opencode.ai/docs/cli ; opencode.ai/docs/plugins ; opencode issues #14195/#29638/#5887 | "opencode run --dir <path> sets an explicit working root at the process level" — native subagent dispatch is synchronous-only, so MSD creates + manages the worktree and process-spawns the executor into it via --dir (#2584) |
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to 1 in negotiation (#3673) |
Sources consulted:
- https://opencode.ai/docs/plugins
- https://opencode.ai/docs/agents
- https://opencode.ai/docs/commands
- https://opencode.ai/docs/mcp-servers
- /websites/opencode_ai_plugins (Context7)
- /anomalyco/opencode (Context7)
- https://github.com/sst/opencode/issues/5887
Documentation gaps:
- dispatch.nested
- dispatch.maxDepth
cursor
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | imperative | https://cursor.com/docs/sdk/typescript | "local.customTools where you define tool functions that execute 'in your process, so it can reach anything your code can'; Agent.create()" |
| commandSurface | slash-file | https://cursor.com/docs/enterprise/llm-safety-and-controls | "Commands are reusable prompts invoked via slash commands (e.g., /test), while workflows enable multi-step processes" |
| modelMode | passive | https://cursor.com/docs/sdk/python | "The model used for a run can be overridden by passing a ModelSelection object in SendOptions to agent.send()." |
| hookBus | host | https://cursor.com/docs/hooks | "Agent hooks: sessionStart, sessionEnd, preToolUse, postToolUse, subagentStart, subagentStop, beforeShellExecution, afterShellExecution" |
| stateIO | filesystem | https://cursor.com/docs/reference/sandbox | "Local agents run with sandbox options disabled by default." |
| transport | mcp | https://cursor.com/docs/mcp | "The Model Context Protocol (MCP) allows Cursor to connect to external tools and data sources." |
| runtime | node | https://cursor.com/docs/sdk/typescript | "The SDK runs on Node.js. It requires Node.js 22.13 or later and is described as a Node-first package." |
| effortSurface | undocumented | no authoritative doc — per-host reasoning-effort survey, #2481 (09b535ac0) |
This host's documentation states no reasoning-effort setting, so the axis carries the fail-closed sentinel rather than inheriting a profile baseline. No host-specific URL is cited because the finding is an ABSENCE: #2481 surveyed all hosts for a reasoning-effort mechanism and found one only for claude/opencode/codex. |
| dispatch.namedDispatch | true | https://cursor.com/docs/subagents | "Invoke specific subagents using slash commands in your prompt. This allows for direct control over which agent performs" |
| dispatch.nested | true | https://cursor.com/docs/sdk/typescript | "The top-level agent and its direct subagents can launch subagents, but a subagent launched by another subagent can't lau" |
| dispatch.maxDepth | 2 | https://cursor.com/docs/sdk/typescript | "The top-level agent and its direct subagents can launch subagents, but a subagent launched by another subagent can't lau" |
| dispatch.background | true | https://cursor.com/docs/subagents | "Background, which returns immediately while the subagent works independently, best for long-running tasks or parallel wo" |
| dispatch.subagentToolkit | full | https://cursor.com/docs/subagents | "Subagents can utilize MCP tools, inheriting all tools available to their parent agent, including those from configured s" |
| dispatch.backgroundDispatch | true | https://cursor.com/docs/subagents (FAQ: Can subagents launch other subagents?) and https://cursor.com/docs/sdk/typescript (Subagents > Nested subagents) | FAQ: "As of Cursor 2.5, subagents have the capability to launch child subagents, enabling the creation of a hierarchical structure for coordinated tasks. This nested launching functionality requires T |
| dispatch.isolation | harness-worktree | https://cursor.com/docs/cli/reference/parameters ; cursor.com/docs/cli/using ; cursor.com/docs/cli/changelog | "-w, --worktree [name] — cursor-agent creates/binds a git worktree per agent (~/.cursor/worktrees/…); native parallel-agent dispatch" (#2584) |
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to 1 in negotiation (#3673) |
Sources consulted:
- https://cursor.com/docs/subagents
- https://cursor.com/docs/hooks
- https://cursor.com/docs/sdk/typescript
- https://cursor.com/docs/sdk/python
- https://cursor.com/docs/mcp
- https://cursor.com/docs/reference/sandbox
- https://cursor.com/docs/enterprise/llm-safety-and-controls
- /websites/cursor (Context7)
MSD integration status — Phase D dogfood complete (#2089, ADR-1239). Cursor installs through the imperative embedding adapter (createImperativeAdapter → installRuntimeArtifacts); the hardcoded runtime === 'cursor' / isCursor projection is folded into descriptor-driven runtime.hostBehaviors, and install/uninstall output is byte-parity-gated at the time (tests/fixtures/golden-install-parity/cursor.json; superseded by the differential attribution check, #2724). Two capability upgrades land, each with a test driving the user-reachable surface:
- Expanded hook-bus coverage — MSD registers all 6 managed lifecycle events in
hooks.jsonbeyond the originalsessionStart/postToolUse:preToolUse,stop,subagentStart,subagentStop(AC4a, cite https://cursor.com/docs/hooks). The hook-bus binding is descriptor-driven viasrc/host-integration-adapters/imperative-hook-bus.cts(readshostBehaviors.managedHookEvents), not a hardcoded event pair. - Named/background nested subagent dispatch —
dispatch.background/backgroundDispatch/nestedare alltruewithmaxDepth: 2;shouldFlattenDispatch(cursor)returnsfalseso MSD's wave-based execution drives Cursor's native background + depth-2 nested subagent dispatch instead of flattening to inline sequential calls (AC4b, cite https://cursor.com/docs/subagents + https://cursor.com/docs/sdk/typescript).
antigravity
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | declarative | https://github.com/alphaperseii3000/google-antigravity-docs/blob/master/google-antigravity-docs.md | "Skills require a SKILL.md file; Workflows are saved as markdown files; Rules are manually defined constraints — all configuration-file-based" |
| commandSurface | slash-file | https://github.com/alphaperseii3000/google-antigravity-docs/blob/master/google-antigravity-docs.md | "Workflows are saved as markdown files, providing a repeatable method for executing key processes. They can be invoked in the Agent using a s" |
| modelMode | passive | https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7 | "Selection occurs via -m flag or /model command inside the TUI. No programmatic model request API is documented for extensions/skills" |
| hookBus | host | https://www.aibuilderclub.com/blog/antigravity-cli-guide | "The CLI fires hooks, not the engine. These are JSON lifecycle interceptors (before tool call, after file edit, on session start)." |
| stateIO | filesystem | live agy 1.1.17 install probe — https://github.com/open-gsd/gsd-core/issues/3747 |
"Global skills discovery scans ~/.gemini/config/skills/: a probe skill placed there is visible to agy, while an identical probe skill under the configHome is not. An earlier third-party blog claim about configHome skills placement was disproved by that probe; MSD installs global skills/agents under ~/.gemini/config (#3738)" |
| transport | mcp | https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7 | "Both local (stdio) and remote (HTTP) Model Context Protocol servers are supported" |
| runtime | go | https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/ | "Built in Go, Antigravity CLI is snappier and more responsive." |
| effortSurface | undocumented | no authoritative doc — per-host reasoning-effort survey, #2481 (09b535ac0) |
This host's documentation states no reasoning-effort setting, so the axis carries the fail-closed sentinel rather than inheriting a profile baseline. No host-specific URL is cited because the finding is an ABSENCE: #2481 surveyed all hosts for a reasoning-effort mechanism and found one only for claude/opencode/codex. |
| dispatch.namedDispatch | undocumented | no authoritative doc — searched: https://www.aibuilderclub.com/blog/antigravity-cli-guide, https://antigravity.google/docs/agents | — |
| dispatch.nested | undocumented | no authoritative doc — searched: https://antigravity.google/docs/agents | — |
| dispatch.maxDepth | undocumented | no authoritative doc — searched: https://antigravity.google/docs/agents | — |
| dispatch.background | true | https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/ | "Antigravity CLI orchestrates multiple agents for complex tasks in the background" |
| dispatch.subagentToolkit | full | https://antigravity.google/docs/cli/features | "Capabilities: Subagents have full access to tools such as code search, file editing, terminal commands, and web searches to complete their assigned tasks." (#2096 EoS migration — the page is JS-rendered/blank on a static fetch; confirmed via headless-browser render) |
| dispatch.backgroundDispatch | undocumented | no authoritative doc — Multiple sources consulted: antigravity.google/docs/cli-subagents (returned blank/JS-rendered), antigravity.google/docs/agent (blank), github.com/google-antigravity/antigravity-cli README, Context7 /google-antigravity/antigravity-cli | All documentation consulted describes a two-level orchestrator→subagent architecture. Background subagents run asynchronously while the main agent continues accepting prompts. The DataCamp tutorial st |
| dispatch.isolation | undocumented | not researched / no concurrent fan-out documented for this axis | no authoritative source consulted for concurrent-executor isolation on this host — fails closed to none (sequential) in negotiation (#2584) |
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to 1 in negotiation (#3673) |
Sources consulted:
- https://github.com/alphaperseii3000/google-antigravity-docs/blob/master/google-antigravity-docs.md
- https://developers.googleblog.com/an-important-update-transitioning-gemini-cli-to-antigravity-cli/
- https://dev.to/arindam_1729/antigravity-cli-a-hands-on-guide-to-googles-terminal-coding-agent-5bc7
- https://www.aibuilderclub.com/blog/antigravity-cli-guide
- https://antigravity.google/docs/agents
- https://antigravity.google/docs/hooks
- https://antigravity.google/docs/cli/features (#2096 — subagentToolkit)
Documentation gaps:
- dispatch.namedDispatch — docs describe dynamic plain-English goal dispatch where agent names subagents at runtime; no pre-registered named sub-agent API documented.
- dispatch.nested — no documentation found on whether subagents can themselves spawn further subagents.
- dispatch.maxDepth — no documented depth limit or explicit unbounded statement found.
EoS migration status (#2096): Migrated onto the declarative adapter. All runtime === 'antigravity' / isAntigravity / canonical === 'antigravity' branches folded into descriptor-driven runtime.hostBehaviors + runtime.hostIntegration: getConfigDirFromHome (bin/install.js) now branches on configHome.kind === 'dot-home-nested' instead of a hardcoded runtime literal; projectLocalHookPrefix (src/shell-command-projection.cts) reads hostBehaviors.hookPathStyle ('raw' → bare dirName, no $CLAUDE_PROJECT_DIR anchor); applyAgentPathRewrites (src/runtime-artifact-conversion.cts) reads hostBehaviors.noPathRewrite to skip the ~/.claude/ → pathPrefix rewrites; and getProjectInstructionFile (src/runtime-name-policy.cts) reads hostBehaviors.projectInstructionFile ("GEMINI.md" — Antigravity CLI's contextFileName, successor to the sunset Gemini CLI per #1928) instead of a hardcoded canonical === 'antigravity' check. The dead isAntigravity branches these functions previously carried are removed. dispatch.subagentToolkit flipped undocumented → full per the citation above (antigravity.google/docs/cli/features); dispatch.namedDispatch/nested/maxDepth/backgroundDispatch stay undocumented — no authoritative source states named/nested/depth-bounded dispatch or a run_in_background-style call-time param, so negotiateHostCapabilities degrades all four closed to their most-restrictive value (false/0), and shouldFlattenDispatch still forces antigravity's dispatch to flatten (inline) despite dispatch.background: true, because backgroundDispatch itself never reaches true. Two upgrades land: UPGRADE 1 — permission-writer (configureAntigravityPermissions, runtime.permissionWriter: "antigravity") writes Antigravity's native {"permissions":{"allow":[...]}} schema (antigravity.google/docs/cli/permissions) into the same settings.json MSD's own hook registration writes, granting MSD's own read_file/command rules non-destructively. UPGRADE 2 — MCP companion config (configureAntigravityMcpConfig) writes a standalone mcp_config.json (antigravity.google/docs/cli/gcli-migration) registering the msd MCP server, non-destructively preserving any other mcpServers entries. Both upgrades are covered by tests/antigravity-upgrades.test.cjs; the axis/negotiation/source-grep coverage above is in tests/declarative-reference-antigravity.test.cjs.
zcode
ZCode (Z.ai) is a desktop Agentic Development Environment for the GLM-5.2 model, distributed as an Electron app. It exposes a Claude-Code-shaped extensibility surface (per-user
~/.zcode/skills/<name>/SKILL.md, slash commands, named subagents, native MCP, and a plugin system). All values below are sourced verbatim from the official ZCode docs.
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | declarative | https://zcode.z.ai/en/docs/plugin | "A single plugin can bundle several capabilities. ZCode detects which components a plugin includes from its directory layout" — plugins/skills/commands/agents are config/markdown files; no in-process programmatic extension API is documented. |
| commandSurface | slash-file | https://zcode.z.ai/en/docs/commands | "Custom commands are stored as .md files under ~/.zcode/commands ... invoke the command with /command-name" |
| modelMode | passive | https://zcode.z.ai/en/docs/configuration | Models are connected by provider config (Z.ai/BigModel/OpenAI-compat/Anthropic-compat base URLs + API keys in Model Settings); no programmatic model request API is documented. |
| hookBus | host | https://zcode.z.ai/en/docs/plugin | A plugin's bundled components include a "Hook — Automation hooks triggered on specific events" — the host fires the events a plugin subscribes to. |
| stateIO | filesystem | https://zcode.z.ai/en/docs/skill | "User-level skills for ZCode Agent: ~/.zcode/skills/<skill-name>/SKILL.md" — full local filesystem (desktop app). |
| transport | mcp | https://zcode.z.ai/en/docs/mcp-services | "MCP (Model Context Protocol) connects external capabilities ... type as stdio (SSE and HTTP remote servers are also supported)" — native MCP. |
| runtime | electron | https://zcode.z.ai/en/docs/install (download path cdn-zcode.z.ai/zcode/electron/releases/3.2.5/ZCode-3.2.5-mac-arm64.dmg) |
ZCode is shipped as an Electron desktop application; the release artifact lives under the electron/releases path. |
| effortSurface | undocumented | no authoritative doc — per-host reasoning-effort survey, #2481 (09b535ac0) |
This host's documentation states no reasoning-effort setting, so the axis carries the fail-closed sentinel rather than inheriting a profile baseline. No host-specific URL is cited because the finding is an ABSENCE: #2481 surveyed all hosts for a reasoning-effort mechanism and found one only for claude/opencode/codex. |
| dispatch.namedDispatch | true | https://zcode.z.ai/en/docs/subagents | "you can let the Agent pick the subagent automatically, or reference it with @ in the chat box" — subagents are invoked by name via the Agent tool. |
| dispatch.nested | undocumented | searched: https://zcode.z.ai/en/docs/subagents | The docs do not state whether a subagent can itself spawn further subagents. |
| dispatch.maxDepth | undocumented | searched: https://zcode.z.ai/en/docs/subagents | No maximum nesting depth is documented. |
| dispatch.background | false | https://zcode.z.ai/en/docs/subagents | "Foreground execution. Subagents run in the foreground ... Background execution is not enabled yet." |
| dispatch.subagentToolkit | full | https://zcode.z.ai/en/docs/subagents | "general-purpose is the default built-in subagent ... It has access to all tools"; custom subagents default to "All permissions by default" (inherits every tool). |
| dispatch.backgroundDispatch | false | https://zcode.z.ai/en/docs/subagents | "Background execution is not enabled yet" — background dispatch is therefore impossible. |
| dispatch.isolation | none | https://zcode.z.ai/en/docs/subagents (shipped descriptor: dispatch.backgroundDispatch: false) |
"Background execution is not enabled yet" — no concurrent fan-out primitive, so same-wave plans run inline/sequentially (#2584) |
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to 1 in negotiation (#3673) |
Sources consulted:
- https://zcode.z.ai/en/docs/skill
- https://zcode.z.ai/en/docs/commands
- https://zcode.z.ai/en/docs/subagents
- https://zcode.z.ai/en/docs/mcp-services
- https://zcode.z.ai/en/docs/plugin
- https://zcode.z.ai/en/docs/configuration
- https://zcode.z.ai/en/docs/install
Documentation gaps:
- dispatch.nested / dispatch.maxDepth — ZCode's subagent docs do not state whether subagents can spawn further subagents or any depth bound.
- configHome — skills/commands/agents homes are documented (
~/.zcode/skills,~/.zcode/commands,~/.zcode/agents); the exact settings filename under~/.zcode(where MCP server config is stored) is not fully documented at time of writing. - Maintenance note — ZCode is a young, fast-moving app (observed at v3.2.x); these axes may need revision as its on-disk config layout stabilizes. Because ZCode also natively imports skills/MCP from
~/.claude, installing MSD to BOTHclaudeandzcodecan surface duplicated skills inside ZCode; this overlap is expected and documented.
EoS migration status (#2101, ADR-1239): ZCode's install is fully dogfooded through the declarative adapter — its shared-hooks exclusion (previously a hardcoded !isZcode branch in bin/install.js) is now folded onto hostBehaviors.skipSharedHooksInstall, byte-parity with the prior install (ZCode's golden install tree has zero hook files). The two capability upgrades anticipated for ZCode both remain blocked on undocumented on-disk formats — hookBus and transport above stay documented-but-unimplemented pending ZCode publishing those formats, and implementing a guessed format risks a false-green descriptor, so neither upgrade is wired:
- Hook automation (the plugin
Hookcomponent,hookBus: hostabove) — https://zcode.z.ai/en/docs/plugin documents the capability only at a high level ("Automation hooks triggered on specific events"; components are "detected from directory layout, shown as badges"). No config file format, on-disk location, event-name vocabulary, or payload schema is published, so MSD cannot faithfully wire hook events into a plugin bundle. BLOCKED (undocumented on-disk hook-config format). - MCP registration (
transport: mcpabove) — https://zcode.z.ai/en/docs/mcp-services confirms servers are "stored in the .zcode configuration file of the chosen scope" and accepts both a bare{"server-name":{...}}map and an{"mcpServers":{...}}wrapper shape, but does not document the exact settings filename/path or full schema (the docs describe the UI flow, not the on-disk contract) — this is the same gap already noted underconfigHomeabove. BLOCKED (undocumented settings-filename/schema gap).
vscode
VS Code is the IDE-profile reference host: a Marketplace/VSIX-distributed extension, NOT file-projected onto a config directory — it has no
runtime.localConfigDirin the usual sense (configHome.kind: "none",localConfigDir: null) and no CLI install surface at all (installSurface: "none"; it is never installed bybin/install.js— no--vscodeflag, noallRuntimesmembership; seecapabilities/vscode/capability.json). The extension IS the host. Sourcing note: the citations below are the VS Code extension API documentation pages named in ADR-1239 (#2103) as the source for each axis; this environment did not have live Context7/ web-fetch access at authoring time, so the Evidence column is a paraphrase of VS Code's documented extension model rather than a verbatim excerpt — a maintainer with Context7/web access should verify the exact wording before treating this section as fully cited.
| Axis | Value | Source | Evidence |
|---|---|---|---|
| embeddingMode | imperative | https://code.visualstudio.com/api/references/vscode-api | The extension is loaded in-process by the extension host and calls the vscode namespace API directly (vscode.commands.registerCommand, vscode.chat.createChatParticipant, vscode.lm.registerTool) — an in-process programmatic API, not a config-file-only integration. |
| commandSurface | palette | https://code.visualstudio.com/api/extension-guides/command | Commands are contributed via contributes.commands in package.json and registered with vscode.commands.registerCommand, surfaced through the Command Palette (and the Chat view via the chat participant) — not a markdown/TOML slash-command file format. |
| modelMode | active | https://code.visualstudio.com/api/extension-guides/ai/language-model | The vscode.lm namespace lets an extension actively select a model (vscode.lm.selectChatModels) and send requests to it programmatically, rather than only reading a static config value. |
| hookBus | engine | https://code.visualstudio.com/api/references/activation-events | VS Code has no cross-extension lifecycle-hook bus that MSD subscribes to; the extension host (the "engine" here, per this axis's own host/engine/none vocabulary) owns activation events, and MSD's own hook lifecycle runs fully in-process/engine-owned inside the extension. |
| stateIO | sandboxed-storage | https://code.visualstudio.com/api/references/vscode-api#Memento | context.globalState/context.workspaceState (both Memento) are the extension's persistent storage surface — sandboxed key/value storage scoped to the extension, not unrestricted local filesystem access. |
| transport | mcp | https://code.visualstudio.com/api/extension-guides/ai/mcp | VS Code 1.99 added native MCP client support; on the Web (webworker) entry, full MSD command dispatch is available through VS Code's native MCP client connecting to the MSD companion MCP server (msd-mcp-server), not an in-process Node dispatch (which the web entry cannot run at all). |
| runtime | sandboxed-web | https://code.visualstudio.com/api/extension-guides/web-extensions | The browser entry point (vscode/browser.js) runs in a webworker context with no Node core modules — the Web Extension execution model VS Code documents for extensions that must run in vscode.dev/github.dev. |
| effortSurface | undocumented | no authoritative doc — per-host reasoning-effort survey, #2481 (09b535ac0) |
This host's documentation states no reasoning-effort setting, so the axis carries the fail-closed sentinel rather than inheriting a profile baseline. No host-specific URL is cited because the finding is an ABSENCE: #2481 surveyed all hosts for a reasoning-effort mechanism and found one only for claude/opencode/codex. |
| dispatch.namedDispatch | true | https://code.visualstudio.com/docs/copilot/chat/chat-agent-mode#_agent-mode-tools | Registered languageModelTools (and the chat participant) are addressable by name — the primary agent references a tool/participant by its declared name/toolReferenceName, not only positionally. |
| dispatch.nested | true | https://code.visualstudio.com/docs/copilot/copilot-chat-agents (subagents) | VS Code's chat subagent model (#runSubagent) explicitly supports a subagent invoking further subagents, gated by chat.subagents.allowInvocationsFromSubagents. |
| dispatch.maxDepth | 5 | https://code.visualstudio.com/docs/copilot/copilot-chat-agents (subagents) | Documented as VS Code's maximum nesting depth for #runSubagent chains — also matches this repo's existing PROFILE_BASELINES.ide.dispatch.maxDepth baseline. |
| dispatch.background | true | https://code.visualstudio.com/api/extension-guides/ai/tools | Language Model Tools can be invoked as part of an asynchronous agent turn (the primary agent does not block synchronously on a single extension call). |
| dispatch.subagentToolkit | undocumented | no authoritative doc found at authoring time | VS Code's subagent documentation does not state whether a subagent's tool surface is restricted to read-only tools or the full set an extension registers; recorded undocumented (fails closed to read-only in negotiation) rather than guessed. |
| dispatch.backgroundDispatch | undocumented | no authoritative doc found at authoring time | Whether a background-dispatched subagent can itself spawn further NAMED subagents (the #853 discriminator) is not stated in the sources reviewed; recorded undocumented (fails closed to false) rather than guessed. |
| dispatch.isolation | undocumented | not researched / no concurrent fan-out documented for this axis | no authoritative source consulted for concurrent-executor isolation on this host — fails closed to none (sequential) in negotiation (#2584) |
| dispatch.maxConcurrency | undocumented | not researched / no documented concurrent-subagent capacity for this axis | no authoritative source consulted for concurrent-executor capacity on this host — fails closed to 1 in negotiation (#3673) |
Sources consulted:
- https://code.visualstudio.com/api/references/vscode-api
- https://code.visualstudio.com/api/extension-guides/command
- https://code.visualstudio.com/api/extension-guides/ai/language-model
- https://code.visualstudio.com/api/extension-guides/ai/tools
- https://code.visualstudio.com/api/extension-guides/ai/mcp
- https://code.visualstudio.com/api/extension-guides/web-extensions
- https://code.visualstudio.com/api/references/activation-events
- https://code.visualstudio.com/docs/copilot/copilot-chat-agents
Documentation gaps:
- dispatch.subagentToolkit / dispatch.backgroundDispatch — the reviewed sources document that
#runSubagentexists (v1.105+,chat.subagents.allowInvocationsFromSubagents, max nesting depth 5) but do not state the subagent tool-restriction model or whether a background-dispatched subagent can itself spawn further named subagents; both stayundocumentedand negotiation fails closed. - This section's Evidence-column wording was authored without live Context7/web-fetch access (see the sourcing note above the table) — verify against the cited pages before relying on it for a future capability upgrade.
EoS migration status (#2103): vscode lands as a registry runtime (role:runtime) for
validator/host-integration coverage ONLY — it is deliberately NOT a CLI-installable runtime
(installSurface: "none", never in bin/install.js's allRuntimes; see the
NON_INSTALLABLE_RUNTIMES carve-out in tests/runtime-flags.test.cjs). The extension surface
(vscode/extension.js, vscode/browser.js, vscode/host-binding.js, vscode/package.json) is
distributed via the Marketplace/VSIX, not npx --vscode — there is no docs/how-to/install-on- your-runtime.md entry for it. Dispatch is SUBPROCESS REUSE on desktop (the same shared
dispatchMsdCommand in msd-core/bin/lib/shell-command-projection.cjs the companion MCP
server uses) via vscode/extension.js's main entry (Node). The browser entry
(vscode/browser.js) is a SEPARATE, independently zero-Node-API file: it does NOT require
host-binding.js because that module's engine-lib dependencies (state-io.cjs,
adapter-imperative.cjs → install-engine.cjs/capability-loader.cjs,
model-adapter.cjs → model-resolver.cjs → config-loader.cjs/configuration.cjs) all pull in
Node's fs/os/path at module-load time — requiring any of them from a webworker context would
throw immediately. browser.js instead composes its own minimal surface directly against
vscode.lm, and its command/tool/chat handlers surface an honest "full dispatch is unavailable on
web; configure the MSD MCP server" message rather than a silent failure. The chat participant
(@msd) and Language Model Tools (a representative 3-tool set — msd_progress, msd_workstreams,
msd_plan_phase — matching real shipped skills that map onto a single, safe, read-only
msd-tools.cjs command) are registered on BOTH entries identically; only the dispatch behavior
differs. #runSubagent wiring (registerSubagentDispatch/dispatchAsSubagent, gated on
chat.subagents.allowInvocationsFromSubagents availability, fail-soft on older/Insiders-gated
hosts) adds a belt-and-suspenders maxDepth: 5 ceiling independent of whatever VS Code's own chat
engine enforces natively — there is no separate extension-side "subagent contribution"
registration API beyond the chat participant + Language Model Tools already registered; VS Code's
chat engine surfaces them to #runSubagent on its own.