Platform Support Matrix

June 1, 2026 · View on GitHub

This document provides a comprehensive comparison of all platforms supported by context-mode, including their hook paradigms, capabilities, configuration, and known limitations.

Overview

context-mode supports sixteen platforms across three hook paradigms:

ParadigmPlatforms
JSON stdin/stdoutClaude Code, Gemini CLI, VS Code Copilot, JetBrains Copilot, Cursor, Codex CLI, Qwen Code, Kimi Code
TS PluginOpenCode, KiloCode, OpenClaw
MCP-onlyAntigravity, Kiro, Zed, Pi, OMP (Oh My Pi)

The MCP server layer is 100% portable and needs no adapter. Only the hook layer requires platform-specific adapters.

Prerequisites

All platforms (except Claude Code plugin install) require a global install:

npm install -g context-mode

This puts the context-mode binary in PATH, which is required for:

  • MCP server: "command": "context-mode" (replaces ephemeral npx -y context-mode)
  • Hook dispatcher: context-mode hook <platform> <event> (replaces node ./node_modules/... paths)
  • Utility commands: context-mode doctor, context-mode upgrade
  • Persistent upgrades: ctx-upgrade updates the global binary in-place

Main Comparison Table

FeatureClaude CodeGemini CLIVS Code CopilotJetBrains CopilotCursorOpenCodeCodex CLIKimi CodeAntigravityKiroOMP
Paradigmjson-stdiojson-stdiojson-stdiojson-stdiojson-stdiots-pluginjson-stdiojson-stdiomcp-onlymcp-onlymcp-only
PreToolUse equivalentPreToolUseBeforeToolPreToolUsePreToolUsepreToolUsetool.execute.beforePreToolUsePreToolUse------
PostToolUse equivalentPostToolUseAfterToolPostToolUsePostToolUsepostToolUsetool.execute.afterPostToolUsePostToolUse------
PreCompact equivalentPreCompactPreCompressPreCompactPreCompact--experimental.session.compacting--PreCompact------
SessionStartSessionStartSessionStartSessionStartSessionStart-- (buggy in Cursor)--SessionStartSessionStart------
Stop equivalent----StopStopstop--StopStop------
Can modify argsYesYesYesYesYesYesNoYes------
Can modify outputYesYesYesYesNoYes (caveat)NoYes------
Can inject session contextYesYesYesYesYes--YesYes------
Can block toolsYesYesYesYesYesYes (throw)YesYes------
Config location~/.claude/settings.json~/.gemini/settings.json.github/hooks/*.json.github/hooks/*.json.cursor/hooks.json or ~/.cursor/hooks.jsonopencode.json~/.codex/hooks.json + ~/.codex/config.toml~/.kimi-code/config.toml~/.gemini/antigravity/mcp_config.json~/.kiro/settings/mcp.json~/.omp/agent/mcp_config.json
Session ID fieldsession_idsession_idsessionId (camelCase)sessionId (camelCase)conversation_idsessionID (camelCase)N/Asession_idN/AN/AN/A
Project dir envCLAUDE_PROJECT_DIRGEMINI_PROJECT_DIRCLAUDE_PROJECT_DIRCLAUDE_PROJECT_DIRstdin workspace_rootsctx.directory (plugin init)N/Astdin cwdN/AN/AOMP_PROCESSING_AGENT_DIR
MCP/tool namingmcp__server__toolmcp__server__toolf1e_ prefixf1e_ prefixMCP:<tool> in hook payloadsnative ctx_* plugin toolsmcp__server__toolmcp__context-mode__toolmcp__server__toolmcp__server__toolmcp__server__tool
Hook command formatcontext-mode hook claude-code <event>context-mode hook gemini-cli <event>context-mode hook vscode-copilot <event>context-mode hook jetbrains-copilot <event>context-mode hook cursor <event>TS plugin (no command)context-mode hook codex <event>context-mode hook kimi <event>N/AN/A
Hook registrationsettings.json hooks objectsettings.json hooks object.github/hooks/*.json.github/hooks/*.jsonhooks.json native hook arraysopencode.json plugin array~/.codex/hooks.jsonconfig.toml hooks arrayN/AN/A
MCP server commandcontext-mode (or plugin auto)context-modecontext-modecontext-modecontext-modeN/A (native plugin tools)context-modecontext-modecontext-modecontext-mode
Plugin distributionClaude plugin registrynpm globalnpm globalnpm globalnpm globalnpm globalnpm globalnpm globalnpm globalnpm global
Session dir~/.claude/context-mode/sessions/~/.gemini/context-mode/sessions/.github/context-mode/sessions/ or ~/.vscode/context-mode/sessions/.github/context-mode/sessions/~/.cursor/context-mode/sessions/~/.config/opencode/context-mode/sessions/~/.codex/context-mode/sessions/~/.kimi-code/context-mode/sessions/~/.gemini/context-mode/sessions/~/.kiro/context-mode/sessions/

Legend

  • Yes = Fully supported
  • -- = Not supported
  • (caveat) = Supported with known issues

Platform Details

Claude Code

Status: Fully supported (primary platform)

Hook Paradigm: JSON stdin/stdout

Claude Code is the primary platform for context-mode. All hooks communicate via JSON on stdin/stdout. The adapter reads raw JSON input, normalizes it into platform-agnostic events, and formats responses back into Claude Code's expected output format.

Hook Names:

  • PreToolUse -- fires before a tool is executed
  • PostToolUse -- fires after a tool completes
  • PreCompact -- fires before context compaction
  • SessionStart -- fires when a session starts, resumes, or compacts
  • UserPromptSubmit -- fires when user submits a prompt

Blocking: permissionDecision: "deny" in response JSON

Arg Modification: updatedInput field at top level of response

Output Modification: updatedMCPToolOutput for MCP tools, additionalContext for appending

Session ID Extraction Priority:

  1. UUID from transcript_path field
  2. session_id field
  3. CLAUDE_SESSION_ID environment variable
  4. Parent process ID fallback

Hook Commands:

context-mode hook claude-code pretooluse
context-mode hook claude-code posttooluse
context-mode hook claude-code precompact
context-mode hook claude-code sessionstart
context-mode hook claude-code userpromptsubmit

Known Issues: None significant.


Gemini CLI

Status: Fully supported

Hook Paradigm: JSON stdin/stdout

Gemini CLI uses the same JSON stdin/stdout paradigm as Claude Code but with different hook names and response format.

Hook Names:

  • BeforeTool -- equivalent to PreToolUse
  • AfterTool -- equivalent to PostToolUse
  • PreCompress -- equivalent to PreCompact (advisory only, async, cannot block)
  • SessionStart -- fires when a session starts

Blocking: decision: "deny" in response (NOT permissionDecision)

Arg Modification: hookSpecificOutput.tool_input (merged with original, not updatedInput)

Output Modification: decision: "deny" + reason replaces output; hookSpecificOutput.additionalContext appends

Environment Variables:

  • GEMINI_PROJECT_DIR -- primary project directory
  • CLAUDE_PROJECT_DIR -- alias (also works)

Hook Commands:

context-mode hook gemini-cli beforetool
context-mode hook gemini-cli aftertool
context-mode hook gemini-cli precompress
context-mode hook gemini-cli sessionstart

Known Issues / Caveats:

  • PreCompress is advisory only (async, cannot block)
  • No decision: "ask" support
  • Hooks don't fire for subagents yet

OpenCode

Status: Fully supported

Hook Paradigm: TS Plugin

OpenCode uses a TypeScript plugin paradigm instead of JSON stdin/stdout. Hooks and the 11 ctx_* tools are registered via the plugin array in opencode.json; no separate mcp block or stdio MCP child is required.

Hook Names:

  • tool.execute.before -- equivalent to PreToolUse
  • tool.execute.after -- equivalent to PostToolUse
  • experimental.session.compacting -- equivalent to PreCompact (experimental)
  • experimental.chat.system.transform -- SessionStart-equivalent (cross-session resume injection)

Blocking: throw Error in tool.execute.before handler

Arg Modification: output.args mutation

Output Modification: output.output mutation (TUI bug for bash, see issue #13575)

Session ID: input.sessionID (camelCase, note the uppercase ID)

Project Directory: Available via ctx.directory in plugin init, not via environment variable

Desktop markers: OpenCode desktop shells also export OPENCODE_CLIENT=desktop and OPENCODE_TERMINAL=1; context-mode treats those as OpenCode identity signals when the CLI markers are absent.

Configuration:

  • opencode.json or .opencode/opencode.json
  • Plugin registered in the plugin array with npm package names
  • ctx_* tools are native plugin tools, not mcp__server__tool calls
  • KiloCode uses the same plugin path via kilo.json; context-mode upgrade removes stale mcp.context-mode entries for both hosts while preserving other MCP servers

Cross-session resume: When OpenCode triggers experimental.session.compacting (auto on context overflow OR manual /compact), context-mode saves a snapshot to its per-project SQLite store. The NEXT new session in the same project — typically after Ctrl+D then re-running opencode, or starting a fresh chat — claims that snapshot via experimental.chat.system.transform and prepends it to system[1] (preserves OpenCode's [header, body] cache fold). The current session never claims its OWN snapshot back (self-injection guard, v1.0.106). To verify the injection landed, run with OPENCODE_DEBUG=1 and grep for <!-- context-mode v in the system prompt — that's the visible marker.

Known Issues / Caveats:

  • SessionStart is broken (issue #14808, no hook issue #5409) — we use experimental.chat.system.transform as a surrogate
  • Output modification has TUI rendering bug for bash tool (issue #13575)
  • experimental.session.compacting is marked experimental and may change
  • No canInjectSessionContext capability
  • Resume snapshots are scoped per-project (DB sharded by SHA-256 of ctx.directory); no cross-project bleed

Codex CLI

Status: Supported (MCP active, hooks require [features].hooks = true)

Hook Paradigm: JSON stdin/stdout

Codex CLI's Rust backend (codex-rs) includes a hook system using the same JSON stdin/stdout wire protocol as Claude Code. Hooks are configured via hooks.json.

Hook Names:

  • PreToolUse -- fires before a tool is executed
  • PostToolUse -- fires after a tool completes
  • PreCompact -- fires before context compaction on Codex builds that emit it
  • SessionStart -- fires when a session starts, resumes, or clears
  • UserPromptSubmit -- fires when user submits a prompt
  • Stop -- fires when agent turn ends (can continue with followup)

Blocking: permissionDecision: "deny" in hookSpecificOutput, or exit code 2 Arg Modification: NOT supported (updatedInput returns error) Output Modification: NOT supported (updatedMCPToolOutput returns error) Context Injection: additionalContext in hookSpecificOutput (PostToolUse, SessionStart only). PreToolUse does NOT support additionalContext — the codex formatter handles this automatically (deny works, context/modify/ask responses are dropped).

Configuration:

  • Hook config: $CODEX_HOME/hooks.json or ~/.codex/hooks.json (JSON format, same structure as Claude Code)
  • MCP config: $CODEX_HOME/config.toml or ~/.codex/config.toml (TOML format, [mcp_servers] section)
  • Feature flags: use [features].hooks (or codex --enable hooks) if you need to force hooks on. Prefer [features].hooks; [features].codex_hooks remains accepted as a legacy alias in current Codex builds.

Hook Commands:

context-mode hook codex pretooluse
context-mode hook codex posttooluse
context-mode hook codex precompact
context-mode hook codex sessionstart
context-mode hook codex userpromptsubmit
context-mode hook codex stop

Known Issues / Caveats:

  • PreToolUse additionalContext is unsupported — context injection works via PostToolUse and SessionStart instead. The codex formatter handles this automatically (deny works, context is dropped). Source: codex-rs/hooks/src/engine/output_parser.rs:267.

  • PreToolUse input rewriting still needs upstream updatedInput support. Track: openai/codex#18491.

  • PreCompact support is runtime-gated: context-mode configures it and treats a missing registration as a warning, because older Codex builds may not emit the event. The hook stores the resume snapshot out-of-band and SessionStart restores it.

  • Codex emits structured tool names such as Bash and apply_patch; context-mode only normalizes legacy shell aliases.

  • updatedInput and updatedMCPToolOutput are in the schema but NOT implemented

  • Default hook timeout: 600 seconds

  • Older context-mode releases used a plugins/context-mode -> .. symlink shim because Codex rejects the repository root ("./") as an empty local plugin source path. On native Windows, Git can check that symlink out as a regular file containing only .., which makes codex plugin add context-mode@context-mode fail with missing plugin.json. Current releases avoid this by declaring the Codex marketplace plugin as a relative Git source (url: "./"), so Codex materializes the installed marketplace root and finds .codex-plugin/plugin.json without any symlink or junction.

    After installation succeeds, verify that Codex hooks are enabled in %USERPROFILE%\.codex\config.toml:

    [features]
    hooks = true
    

    Some Codex builds may also require plugin_hooks = true. Without hook support, the MCP tools can still work, but automatic session capture and persistent memory may not record events.


Kimi Code

Status: Supported (JSON stdin/stdout hooks + MCP)

Hook Paradigm: JSON stdin/stdout

Kimi Code CLI uses the same JSON stdin/stdout wire protocol as Claude Code and Codex, configured via ~/.kimi-code/config.toml with [[hooks]] array tables. The key difference from Codex is that Kimi accepts additionalContext, updatedInput, and permissionDecision: "ask" in PreToolUse responses — the codex formatter drops these, but the kimi formatter emits them fully.

Hook Names:

  • PreToolUse — fires before a tool is executed
  • PostToolUse — fires after a tool completes
  • PreCompact — fires before context compaction
  • SessionStart — fires when a session starts or resumes
  • UserPromptSubmit — fires when user submits a prompt (payload is ContentPart[])
  • Stop — fires when the agent turn ends

Blocking: permissionDecision: "deny" in hookSpecificOutput, or exit code 2

Arg Modification: updatedInput inside hookSpecificOutput wrapper

Output Modification: additionalContext inside hookSpecificOutput

Context Injection: additionalContext in hookSpecificOutput (works in all hook types)

Configuration:

  • Hooks: ~/.kimi-code/config.toml ([[hooks]] array tables)
  • MCP: ~/.kimi-code/mcp.json
  • Sessions: ~/.kimi-code/context-mode/sessions/

Hook Commands:

context-mode hook kimi pretooluse
context-mode hook kimi posttooluse
context-mode hook kimi precompact
context-mode hook kimi sessionstart
context-mode hook kimi userpromptsubmit
context-mode hook kimi stop

Known Issues / Caveats:

  • UserPromptSubmit sends prompt as a ContentPart[] array; the kimi hook normalizes this to a string for downstream extractors.
  • SessionStart additionalContext injection is emitted but acceptance by the host is not documented in Kimi Code CLI docs (fails-open if unsupported).

Qwen Code

Status: Supported (MCP + hooks — identical wire protocol to Claude Code)

Hook Paradigm: JSON stdin/stdout (same as Claude Code)

Qwen Code (by Alibaba/Qwen team) uses the exact same hook wire protocol as Claude Code, verified from source (hookRunner.ts, claude-converter.ts). Hooks are configured inside ~/.qwen/settings.json under the hooks key.

Hook Names: PreToolUse, PostToolUse, SessionStart, PreCompact, UserPromptSubmit (Qwen supports 12 events total, context-mode uses these 5)

Blocking: permissionDecision: "deny" or exit code 2 Arg Modification: updatedInput in response Output Modification: updatedMCPToolOutput in response Context Injection: additionalContext in response

Configuration:

  • Settings + hooks: ~/.qwen/settings.json
  • MCP: mcpServers in settings.json
  • Sessions: ~/.qwen/context-mode/sessions/

Detection: MCP clientInfo (qwen-cli-mcp-client-* pattern), QWEN_PROJECT_DIR env var, or ~/.qwen/ config dir.

Hook Commands:

context-mode hook qwen-code pretooluse
context-mode hook qwen-code posttooluse
context-mode hook qwen-code sessionstart
context-mode hook qwen-code precompact
context-mode hook qwen-code userpromptsubmit

Antigravity

Status: MCP-only (no hooks)

Hook Paradigm: MCP-only

Google Antigravity is an AI-powered IDE by Google/DeepMind. It shares the ~/.gemini/ directory structure with Gemini CLI but uses a separate config path for MCP servers. Antigravity does not expose a public hook API — only MCP integration is available.

Configuration:

  • ~/.gemini/antigravity/mcp_config.json (JSON format)
  • MCP servers configured in mcpServers object

Detection:

  • Auto-detected via MCP protocol handshake (clientInfo.name: "antigravity-client")
  • Fallback: CONTEXT_MODE_PLATFORM=antigravity environment variable override

Routing Instructions:

  • GEMINI.md auto-written at project root on first MCP server startup
  • Antigravity reads GEMINI.md natively (same filename as Gemini CLI, different content — no hook references)

Capabilities:

  • PreToolUse: --
  • PostToolUse: --
  • PreCompact: --
  • SessionStart: --
  • Can modify args: --
  • Can modify output: --
  • Can inject session context: --

Known Issues / Caveats:

  • No hook support — only routing instruction files for enforcement (~60% compliance)
  • Shares ~/.gemini/ directory with Gemini CLI — session DB uses project hash to prevent collision
  • No verified Antigravity-specific environment variables exist

Sources:


Kiro

Status: MCP-only (hooks planned for Phase 2)

Hook Paradigm: MCP-only

Kiro is an AWS agentic IDE and CLI. It supports MCP servers via ~/.kiro/settings/mcp.json using the standard mcpServers JSON format. Hook support for Kiro CLI (JSON stdin + exit code 2 blocking, preToolUse/postToolUse) is verified in the Kiro CLI docs but not yet implemented in context-mode — planned for Phase 2.

Detection:

  • Auto-detected via MCP protocol handshake (clientInfo.name: "Kiro CLI")

Configuration:

  • Global: ~/.kiro/settings/mcp.json (JSON format, standard mcpServers object)
  • Project: .kiro/settings/mcp.json

Routing Instructions:

  • KIRO.md written at project root on first MCP server startup

Hook System (Phase 2 — not yet implemented):

  • Kiro CLI supports preToolUse/postToolUse hooks via JSON stdin
  • Blocking: exit code 2 (similar to Gemini CLI pattern)
  • Hook format verified in Kiro CLI docs but context-mode adapter is not yet built

Built-in Tools:

  • fs_read / read, fs_write / write, execute_bash / shell, use_aws / aws

Capabilities:

  • PreToolUse: --
  • PostToolUse: --
  • PreCompact: --
  • SessionStart: --
  • Can modify args: --
  • Can modify output: --
  • Can inject session context: --

Known Issues / Caveats:

  • Hook adapter not yet implemented — Phase 2 work item
  • Kiro IDE hooks use a UI-based "Run Command" shell action; stdin format unverified

Sources:


VS Code Copilot

Status: Fully supported (preview)

Hook Paradigm: JSON stdin/stdout

VS Code Copilot uses the same JSON stdin/stdout paradigm as Claude Code with PascalCase hook names. It also provides unique hooks for subagent lifecycle.

Hook Names:

  • PreToolUse -- fires before a tool is executed
  • PostToolUse -- fires after a tool completes
  • PreCompact -- fires before context compaction
  • SessionStart -- fires when a session starts
  • Stop -- fires when agent stops (unique to VS Code)
  • SubagentStart -- fires when a subagent starts (unique to VS Code)
  • SubagentStop -- fires when a subagent stops (unique to VS Code)

Blocking: permissionDecision: "deny" (same as Claude Code)

Arg Modification: updatedInput inside hookSpecificOutput wrapper (NOT flat like Claude Code)

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "updatedInput": { ... }
  }
}

Output Modification: additionalContext inside hookSpecificOutput, or decision: "block" + reason

MCP Tool Naming: Uses f1e_ prefix (not mcp__server__tool)

Session ID: sessionId (camelCase, not session_id)

Configuration:

  • Primary: .github/hooks/*.json
  • Also reads: .claude/settings.json
  • MCP config: .vscode/mcp.json

Environment Detection:

  • VSCODE_PID environment variable
  • TERM_PROGRAM=vscode

Hook Commands:

context-mode hook vscode-copilot pretooluse
context-mode hook vscode-copilot posttooluse
context-mode hook vscode-copilot precompact
context-mode hook vscode-copilot sessionstart

Known Issues / Caveats:

  • Preview status -- API may change without notice
  • Matchers are parsed but IGNORED (all hooks fire on all tools)
  • Tool input property names use camelCase (filePath not file_path)
  • Response must be wrapped in hookSpecificOutput with hookEventName

JetBrains Copilot

Status: Fully supported (preview)

Hook Paradigm: JSON stdin/stdout

JetBrains Copilot (GitHub Copilot plugin for JetBrains IDEs) uses the same JSON stdin/stdout paradigm and hook wire protocol as VS Code Copilot. It shares hook names, response format, and MCP tool naming conventions.

Hook Names:

  • PreToolUse -- fires before a tool is executed
  • PostToolUse -- fires after a tool completes
  • PreCompact -- fires before context compaction
  • SessionStart -- fires when a session starts
  • Stop -- fires when agent stops
  • SubagentStart -- fires when a subagent starts
  • SubagentStop -- fires when a subagent stops

Blocking: permissionDecision: "deny" (same as VS Code Copilot)

Arg Modification: updatedInput inside hookSpecificOutput wrapper (same as VS Code Copilot)

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "updatedInput": { ... }
  }
}

Output Modification: additionalContext inside hookSpecificOutput, or decision: "block" + reason

MCP Tool Naming: Uses f1e_ prefix (same as VS Code Copilot)

Session ID: sessionId (camelCase)

Configuration:

  • Hook config: .github/hooks/*.json
  • MCP config: Settings UI (Settings > Tools > AI Assistant > MCP)

Hook Commands:

context-mode hook jetbrains-copilot pretooluse
context-mode hook jetbrains-copilot posttooluse
context-mode hook jetbrains-copilot precompact
context-mode hook jetbrains-copilot sessionstart

Known Issues / Caveats:

  • Preview status -- API may change without notice
  • Shares the same hook wire protocol as VS Code Copilot
  • MCP servers are configured via Settings UI, not a file
  • Requires GitHub Copilot plugin v1.5.57+

Cursor

Status: Supported (native hooks, v1 scope)

Hook Paradigm: JSON stdin/stdout

Cursor uses native lower-camel hook names and flat hook entries in .cursor/hooks.json or ~/.cursor/hooks.json. context-mode treats Cursor as a first-class adapter and does not rely on Claude-compat wrappers for official support.

Hook Names:

  • preToolUse -- fires before a tool is executed
  • postToolUse -- fires after a tool completes
  • stop -- fires when agent turn ends (can send followup_message to continue loop)
  • afterAgentResponse -- fires after assistant response (fire-and-forget, receives full response text)
  • sessionStart -- documented but currently rejected by Cursor's validator (forum report)

Blocking: { "permission": "deny", "user_message": "..." }

Arg Modification: not natively supported (Cursor does not have updated_input)

Output Modification: not supported in v1

Session Context Injection: { "additional_context": "..." }

Session ID Extraction Priority:

  1. conversation_id (stdin JSON)
  2. CURSOR_TRACE_ID environment variable
  3. Parent process ID fallback

Platform Detection Env Vars:

  • CURSOR_TRACE_ID (MCP server context)
  • CURSOR_CLI (integrated terminal context)
  • ~/.cursor/ directory fallback (medium confidence)

Configuration:

  • Project: .cursor/hooks.json
  • User: ~/.cursor/hooks.json
  • MCP config: .cursor/mcp.json or ~/.cursor/mcp.json
  • Marketplace plugin (recommended): .cursor-plugin/plugin.json at the repo root auto-registers MCP, hooks, rules, and skills. Manifest explicitly points hooks at ./hooks/cursor/hooks.json to avoid colliding with the Claude-format ./hooks/hooks.json. Local install: ln -s <repo> ~/.cursor/plugins/local/context-mode. Plugin hook commands use npx -y context-mode hook cursor <event> so no global install is required.

Plugin/native duplication: context-mode doctor warns when both the plugin and .cursor/hooks.json register context-mode hooks (each event would otherwise fire twice). Remove one configuration to keep events single-fire.

Hook Commands:

context-mode hook cursor pretooluse
context-mode hook cursor posttooluse
context-mode hook cursor stop

Known Issues / Caveats:

  • preCompact is intentionally not shipped in v1
  • stop hook receives: conversation_id, status, loop_count, transcript_path; returns followup_message to continue
  • afterAgentResponse is fire-and-forget (receives text, no return value expected)
  • Hook payloads name MCP tools as MCP:<tool> and need adapter normalization
  • Claude-compatible Cursor behavior exists, but native Cursor config is the supported path
  • additional_context in postToolUse and sessionStart hooks is accepted but NOT surfaced to the model (Cursor upstream bug — forum #155689, forum #156157). Routing enforcement relies on .mdc rules file and MCP tool descriptions instead.

OpenClaw

Status: Fully supported

Hook Paradigm: TS Plugin (gateway plugin via api.registerHook() / api.on())

OpenClaw is an OpenAI-stack agent gateway. context-mode ships as a native gateway plugin that registers hooks through OpenClaw's plugin API rather than the JSON stdin/stdout wire protocol. The same plugin entry also registers context-mode as a context engine, owning compaction.

Hook Names:

  • tool_call:before -- equivalent to PreToolUse
  • tool_call:after -- equivalent to PostToolUse
  • command:new -- equivalent to SessionStart (fires on each new gateway command)
  • before_prompt_build -- lifecycle hook for routing instruction injection
  • registerContextEngine (with ownsCompaction) -- equivalent to PreCompact

Blocking: return { block: true, blockReason: "..." } from the tool_call:before handler

Arg Modification: mutate event.params in the tool_call:before handler (or return { params: ... })

Output Modification: not supported (the plugin paradigm exposes args/context, not the rendered tool output)

Context Injection: via before_prompt_build (session-level) and registerContextEngine (compaction-level)

Path Resolution:

  • Detection root: ~/.openclaw/
  • Plugin install: ~/.openclaw/extensions/context-mode/
  • Project config: openclaw.json or .openclaw/openclaw.json
  • Global config fallback: ~/.openclaw/openclaw.json
  • Project dir: process.cwd() (the gateway provides no dedicated env var)
  • Memory dir: project-relative ./memory
  • Session dir: ~/.openclaw/context-mode/sessions/
  • Routing instructions: AGENTS.md

Configuration:

  • openclaw.json registers context-mode under plugins.entries["context-mode"] ({ "enabled": true })
  • plugins.slots.contextEngine = "context-mode" enables ownership of compaction
  • No CLI hook command; OpenClaw imports the plugin module directly

Notes / Caveats:

  • TS plugin paradigm — hooks run in-process, so there is no shell command to chmod and no platform-specific stdin/stdout quirks
  • ask decisions are converted to block (with the original reason) since the gateway has no interactive confirmation path
  • context decisions inside tool_call:before are dropped — context injection must be routed through before_prompt_build or the registered context engine
  • Session ID falls back to pid-${process.ppid} when the gateway does not surface one

Zed

Status: MCP-only (no hooks)

Hook Paradigm: MCP-only

Zed is a code editor with first-class MCP support but no hook pipeline. context-mode runs purely through Zed's context_servers configuration; routing enforcement falls back to the AGENTS.md instruction file (~60% compliance).

Hook Support:

  • PreToolUse: --
  • PostToolUse: --
  • PreCompact: --
  • SessionStart: --
  • Stop: --
  • Can modify args: --
  • Can modify output: --
  • Can inject session context: --

The hook adapter exists only to satisfy the interface contract — every parser throws Error("Zed does not support hooks") and every formatter returns undefined.

Path Resolution:

  • Detection root: ~/.config/zed/
  • Settings file: ~/.config/zed/settings.json
  • MCP registration: context_servers object inside settings.json
  • Session dir: ~/.config/zed/context-mode/sessions/
  • Routing instructions: AGENTS.md (sourced from configs/zed/AGENTS.md in the package, with an inline fallback if missing)

Detection:

  • Auto-detected via the presence of ~/.config/zed/
  • Override via CONTEXT_MODE_PLATFORM=zed

Notes / Caveats:

  • No hook adapter implies no automatic routing — the model must follow AGENTS.md voluntarily
  • No marketplace or plugin registry for Zed; getInstalledVersion() always reports not installed
  • validateHooks always returns a single warn row reminding the user that Zed exposes only MCP integration
  • configureAllHooks, setHookPermissions, and updatePluginRegistry are intentional no-ops

OMP (Oh My Pi)

Status: MCP-only (no hooks)

Hook Paradigm: MCP-only

Oh My Pi (OMP) is a Pi-compatible harness that stores its agent state under ~/.omp/agent/ (overridable via OMP_PROCESSING_AGENT_DIR). Before the dedicated adapter, OMP detection fell through to pi and storage rooted under another harness's directory (typically ~/.claude/), per issue #473. The OMP adapter exists primarily to keep ~/.omp/context-mode/ isolated, not to provide hook integration — OMP, like Antigravity/Kiro/Zed, runs context-mode purely as an MCP server.

Hook Support:

  • PreToolUse: --
  • PostToolUse: --
  • PreCompact: --
  • SessionStart: --
  • Stop: --
  • Can modify args: --
  • Can modify output: --
  • Can inject session context: --

The hook adapter exists only to satisfy the interface contract — every parser throws Error("OMP does not support hooks") and every formatter returns undefined.

Path Resolution:

  • Agent root: $OMP_PROCESSING_AGENT_DIR if set, else ~/.omp/agent/
  • Settings file: <agent root>/mcp_config.json
  • MCP registration: mcpServers object inside mcp_config.json
  • Session dir: ~/.omp/context-mode/sessions/ (intentionally rooted at ~/.omp/, not the agent dir, so multiple OMP instances on one host share an index without colliding session DBs)
  • Routing instructions: PI.md (Pi-compatible filename — OMP shares the Pi instruction surface)

Detection (priority order, listed BEFORE pi so OMP is never misclassified):

  • OMP_PROCESSING_AGENT_DIR env var (high confidence)
  • ~/.omp/ directory presence (medium confidence)
  • CONTEXT_MODE_PLATFORM=omp override

Notes / Caveats:

  • No hook adapter implies no automatic routing — the model must follow PI.md voluntarily (~60% compliance)
  • No marketplace or plugin registry for OMP; getInstalledVersion() reports not installed unless an extensions/context-mode/package.json exists under the agent dir
  • validateHooks always returns a single warn row reminding the user that OMP exposes only MCP integration
  • configureAllHooks, setHookPermissions, and updatePluginRegistry are intentional no-ops

Capability Matrix (Quick Reference)

CapabilityClaude CodeGemini CLIVS Code CopilotJetBrains CopilotCursorOpenCodeCodex CLIKimi CodeAntigravityKiroOMP
PreToolUseYesYesYesYesYesYesYes***Yes------
PostToolUseYesYesYesYesYesYesYesYes------
PreCompactYesYesYesYes--Yes*Yes****Yes------
SessionStartYesYesYesYesYes--YesYes------
Stop----YesYesYes--YesYes------
Modify ArgsYesYesYesYesYesYes--Yes------
Modify OutputYesYesYesYesNoYes**--Yes------
Inject ContextYesYesYesYesYes--YesYes------
Block ToolsYesYesYesYesYesYesYesYes------
MCP/native tool supportYesYesYesYesYesNative pluginYesYesYesYesYes

* OpenCode experimental.session.compacting is experimental ** OpenCode has a TUI rendering bug for bash tool output (#13575) *** Codex CLI PreToolUse supports deny only (no additionalContext); context injection works via PostToolUse and SessionStart **** Codex CLI PreCompact is runtime-gated on builds that emit the event


Hook Response Format Comparison

Blocking a Tool

PlatformResponse Format
Claude Code{ "permissionDecision": "deny", "reason": "..." }
Gemini CLI{ "decision": "deny", "reason": "..." }
VS Code Copilot{ "permissionDecision": "deny", "reason": "..." }
JetBrains Copilot{ "permissionDecision": "deny", "reason": "..." }
Cursor{ "permission": "deny", "user_message": "..." }
OpenCodethrow new Error("...")
Codex CLI{ "hookSpecificOutput": { "permissionDecision": "deny" } } or exit code 2
Kimi Code{ "hookSpecificOutput": { "permissionDecision": "deny" } } or exit code 2

Modifying Tool Input

PlatformResponse Format
Claude Code{ "updatedInput": { ... } }
Gemini CLI{ "hookSpecificOutput": { "tool_input": { ... } } }
VS Code Copilot{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "updatedInput": { ... } } }
JetBrains Copilot{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "updatedInput": { ... } } }
Cursor{ "updated_input": { ... } }
OpenCode{ "args": { ... } } (mutation)
Codex CLIN/A (updatedInput in schema but not implemented)
Kimi Code{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "allow", "updatedInput": { ... } } }

Injecting Additional Context (PostToolUse)

PlatformResponse Format
Claude Code{ "additionalContext": "..." }
Gemini CLI{ "hookSpecificOutput": { "additionalContext": "..." } }
VS Code Copilot{ "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "..." } }
JetBrains Copilot{ "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "..." } }
Cursor{ "additional_context": "..." }
OpenCode{ "additionalContext": "..." }
Codex CLI{ "hookSpecificOutput": { "additionalContext": "..." } }
Kimi Code{ "hookSpecificOutput": { "hookEventName": "PostToolUse", "additionalContext": "..." } }

CLI Hook Dispatcher

All hook-based platforms use the CLI dispatcher pattern instead of direct node paths:

context-mode hook <platform> <event>

The dispatcher resolves the hook script relative to the installed package and dynamically imports it. Stdin/stdout flow through naturally since it runs in the same process.

Advantages over node ./node_modules/... paths:

  • Works from any directory (no per-project npm install needed)
  • Single global install serves all projects
  • context-mode upgrade updates hooks in-place
  • Short, portable command strings in settings files

Supported dispatches:

PlatformEvents
claude-codepretooluse, posttooluse, precompact, sessionstart, userpromptsubmit
gemini-clibeforetool, aftertool, precompress, sessionstart
vscode-copilotpretooluse, posttooluse, precompact, sessionstart
jetbrains-copilotpretooluse, posttooluse, precompact, sessionstart
cursorpretooluse, posttooluse, stop
codexpretooluse, posttooluse, precompact, sessionstart, userpromptsubmit, stop
kimipretooluse, posttooluse, precompact, sessionstart, userpromptsubmit, stop

OpenCode uses a TS plugin paradigm (no command dispatcher). Antigravity and Kiro have no hook support.


SQLite Backend Selection

context-mode automatically selects the best SQLite backend at runtime based on the environment:

PriorityConditionBackendWhy
1Bun runtimebun:sqliteBuilt-in, no native addon
2Linux + Node.js >= 22.5node:sqliteBuilt-in, avoids SIGSEGV from V8 madvise bug
3All other environmentsbetter-sqlite3Mature native addon, prebuilt binaries

Why node:sqlite on Linux? Node.js's V8 garbage collector can call madvise(MADV_DONTNEED) on memory ranges that overlap better-sqlite3's native addon .got.plt section, corrupting resolved symbol addresses and causing sporadic SIGSEGV crashes (1-4/hour on Node v22-v24). node:sqlite is compiled into the Node.js binary itself — no separate .node file, no dlopen(), no .got.plt to corrupt.

Fallback: If node:sqlite is unavailable (Node < 22.5), context-mode silently falls back to better-sqlite3. No user configuration needed.

Override: Not currently supported — backend selection is automatic. If you need to force a specific backend, open an issue.


Utility Commands

All platforms support utility commands via MCP meta-tools:

CommandWhat it does
ctx statsShow context savings, call counts, and session statistics
ctx doctorDiagnose installation: runtimes, hooks, FTS5, versions
ctx upgradeUpdate from GitHub, rebuild, reconfigure hooks
ctx purgePermanently deletes all indexed content from the knowledge base

How they work: The MCP server exposes stats, doctor, upgrade, and purge tools. The <ctx_commands> section in routing instructions (CLAUDE.md, GEMINI.md, AGENTS.md, copilot-instructions.md) maps natural language triggers to MCP tool calls. The doctor and upgrade tools return shell commands that the LLM executes and formats as a checklist. The purge tool permanently deletes all indexed content from the knowledge base and is the sole reset mechanism.