Skip to content

Latest commit

 

History

History
847 lines (622 loc) · 40.2 KB

File metadata and controls

847 lines (622 loc) · 40.2 KB

Platform Support Matrix

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:

Paradigm Platforms
JSON stdin/stdout Claude Code, Gemini CLI, VS Code Copilot, JetBrains Copilot, Cursor, Codex CLI, Qwen Code, Kimi Code
TS Plugin OpenCode, KiloCode, OpenClaw
MCP-only Antigravity, 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

Feature Claude Code Gemini CLI VS Code Copilot JetBrains Copilot Cursor OpenCode Codex CLI Kimi Code Antigravity Kiro OMP
Paradigm json-stdio json-stdio json-stdio json-stdio json-stdio ts-plugin json-stdio json-stdio mcp-only mcp-only mcp-only
PreToolUse equivalent PreToolUse BeforeTool PreToolUse PreToolUse preToolUse tool.execute.before PreToolUse PreToolUse -- -- --
PostToolUse equivalent PostToolUse AfterTool PostToolUse PostToolUse postToolUse tool.execute.after PostToolUse PostToolUse -- -- --
PreCompact equivalent PreCompact PreCompress PreCompact PreCompact -- experimental.session.compacting -- PreCompact -- -- --
SessionStart SessionStart SessionStart SessionStart SessionStart -- (buggy in Cursor) -- SessionStart SessionStart -- -- --
Stop equivalent -- -- Stop Stop stop -- Stop Stop -- -- --
Can modify args Yes Yes Yes Yes Yes Yes No Yes -- -- --
Can modify output Yes Yes Yes Yes No Yes (caveat) No Yes -- -- --
Can inject session context Yes Yes Yes Yes Yes -- Yes Yes -- -- --
Can block tools Yes Yes Yes Yes Yes Yes (throw) Yes Yes -- -- --
Config location ~/.claude/settings.json ~/.gemini/settings.json .github/hooks/*.json .github/hooks/*.json .cursor/hooks.json or ~/.cursor/hooks.json opencode.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 field session_id session_id sessionId (camelCase) sessionId (camelCase) conversation_id sessionID (camelCase) N/A session_id N/A N/A N/A
Project dir env CLAUDE_PROJECT_DIR GEMINI_PROJECT_DIR CLAUDE_PROJECT_DIR CLAUDE_PROJECT_DIR stdin workspace_roots ctx.directory (plugin init) N/A stdin cwd N/A N/A OMP_PROCESSING_AGENT_DIR
MCP/tool naming mcp__server__tool mcp__server__tool f1e_ prefix f1e_ prefix MCP:<tool> in hook payloads native ctx_* plugin tools mcp__server__tool mcp__context-mode__tool mcp__server__tool mcp__server__tool mcp__server__tool
Hook command format context-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/A N/A
Hook registration settings.json hooks object settings.json hooks object .github/hooks/*.json .github/hooks/*.json hooks.json native hook arrays opencode.json plugin array ~/.codex/hooks.json config.toml hooks array N/A N/A
MCP server command context-mode (or plugin auto) context-mode context-mode context-mode context-mode N/A (native plugin tools) context-mode context-mode context-mode context-mode
Plugin distribution Claude plugin registry npm global npm global npm global npm global npm global npm global npm global npm global npm 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)

Capability Claude Code Gemini CLI VS Code Copilot JetBrains Copilot Cursor OpenCode Codex CLI Kimi Code Antigravity Kiro OMP
PreToolUse Yes Yes Yes Yes Yes Yes Yes*** Yes -- -- --
PostToolUse Yes Yes Yes Yes Yes Yes Yes Yes -- -- --
PreCompact Yes Yes Yes Yes -- Yes* Yes**** Yes -- -- --
SessionStart Yes Yes Yes Yes Yes -- Yes Yes -- -- --
Stop -- -- Yes Yes Yes -- Yes Yes -- -- --
Modify Args Yes Yes Yes Yes Yes Yes -- Yes -- -- --
Modify Output Yes Yes Yes Yes No Yes** -- Yes -- -- --
Inject Context Yes Yes Yes Yes Yes -- Yes Yes -- -- --
Block Tools Yes Yes Yes Yes Yes Yes Yes Yes -- -- --
MCP/native tool support Yes Yes Yes Yes Yes Native plugin Yes Yes Yes Yes Yes

* 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

Platform Response 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": "..." }
OpenCode throw new Error("...")
Codex CLI { "hookSpecificOutput": { "permissionDecision": "deny" } } or exit code 2
Kimi Code { "hookSpecificOutput": { "permissionDecision": "deny" } } or exit code 2

Modifying Tool Input

Platform Response 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 CLI N/A (updatedInput in schema but not implemented)
Kimi Code { "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "allow", "updatedInput": { ... } } }

Injecting Additional Context (PostToolUse)

Platform Response 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:

Platform Events
claude-code pretooluse, posttooluse, precompact, sessionstart, userpromptsubmit
gemini-cli beforetool, aftertool, precompress, sessionstart
vscode-copilot pretooluse, posttooluse, precompact, sessionstart
jetbrains-copilot pretooluse, posttooluse, precompact, sessionstart
cursor pretooluse, posttooluse, stop
codex pretooluse, posttooluse, precompact, sessionstart, userpromptsubmit, stop
kimi pretooluse, 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:

Priority Condition Backend Why
1 Bun runtime bun:sqlite Built-in, no native addon
2 Linux + Node.js >= 22.5 node:sqlite Built-in, avoids SIGSEGV from V8 madvise bug
3 All other environments better-sqlite3 Mature 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:

Command What it does
ctx stats Show context savings, call counts, and session statistics
ctx doctor Diagnose installation: runtimes, hooks, FTS5, versions
ctx upgrade Update from GitHub, rebuild, reconfigure hooks
ctx purge Permanently 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.