Client support

August 12, 2026 · View on GitHub

Sixteen clients are supported at the strongest level their current protocol allows. The old two-tier table was stale: it incorrectly said Gemini and Qwen had no pre-tool veto and omitted newer Cursor, Cline, Windsurf, and Kilo hook surfaces.

Capability matrix

The tier is a protocol guarantee, not a product preference. A rules/MCP-only client cannot observe arbitrary built-in shell or file operations, so it is never presented as having native automatic capture.

Client groupTierAutomatic guarantee
Claude Code, Codex, Copilot CLI, Gemini CLI, Qwen Code, Cursorlifecycle continuationnative routing/capture/delivery and one active-model completion reflection
Cline, OpenCode, Kilo, Windsurfnative observationnative routing/capture/delivery; semantic write through the active-model rule
Roo Code, Zed, Amp, Continue, Crush, DroidMCP + rulesMCP-visible activity and explicit graph tools; no claim over hidden built-in calls

The executable registry in hooks-core/capabilities.mjs contains the exact per-client surfaces and prevents the adapter, generator, verifier, dashboard, and certification report from inventing different matrices.

“Active-model semantic harvest” always means the model doing the work decides whether a durable, non-obvious conclusion exists and calls wiki_write itself. No supported path delegates that judgment to a detached harvesting model.

One decision engine

Every native command-hook client runs the decision and graph engine in hooks-core/; generated entry files only name the client and event. OpenCode and Kilo bridge their in-process plugin APIs into those same generated entries. Clients without command hooks receive rules generated from one source in scripts/generate-client-configs.mjs.

This is deliberate. Before it, Claude Code, Codex and Gemini each carried their own copy of the threshold constant and the guidance string, and they had already drifted. Client integrations now differ only where the protocol differs.

npm run sync:hooks          # regenerate vendored copies, entries, and configs
npm run sync:hooks:check    # CI gate: fails if any copy has drifted
npm run verify:certification # structured protocol certification for all 16
node scripts/certify-clients.mjs --json # also detects installed exact versions

The core is vendored into each native client directory rather than imported, because each client executes hooks from a directory it controls (~/.codex/hooks, the Gemini extension path, the Claude Code plugin root) and no shared location resolves across all of them. sync:hooks:check is what keeps vendoring honest.

All native lifecycle paths also import the same privacy-safe observability core. Each invocation produces one correlated completion event whether it succeeds, skips unusable input, times out, or fails open after an exception. The version stamped into vendored hooks comes from package.json during sync:hooks, so a mixed installation is visible in diagnostics instead of looking like a product logic failure. Claude Code's custom SessionStart, PreToolUse, and PreCompact paths are explicitly instrumented rather than being mistaken for generated adapter entries.

How these were verified

Every config shape was checked against the client's own published documentation, and the URL is recorded in each integration's README. That check found four real errors, each of which would have failed silently -- the file installs, the client reports nothing, and the server never loads:

ClientWasShould be
Kilomcp_settings.json / mcpServerswrong at the schema level. Kilo rebranded; it reads kilo.jsonc under an mcp key, with type: "local", command as an array, and environment rather than env
Zeda source keynot in the current schema; removed
Windsurf.windsurfrulesthe legacy single-file form; now .windsurf/rules/
CrushCRUSH.mdthe per-user file; the project one is AGENTS.md
Clinecline_mcp_settings.jsonthe VS Code filename; the CLI reads ~/.cline/mcp.json
Roomcp_settings.jsonthe global path; project-level .roo/mcp.json takes precedence

Kilo is the one worth dwelling on: six of ten clients share the mcpServers convention, and assuming the seventh did too would have shipped a config that could never load. Conventions are not schemas.

npm run verify:clients asserts these shapes on every run, including that superseded paths stay deleted and that rule-only clients do not claim a native veto they do not have.

All ten generated configuration shapes are confirmed against published documentation, with the source URL recorded in each integration's README.

Configuration, all clients

The MCP server advertises its 18 essential tools by default. Set TOKEN_OPTIMIZER_TOOL_PROFILE=full in the server environment only when a client needs the complete 102-tool specialist catalog. Use the four-operation cognitive profile for UCR/live-graph sessions; its measured static schema is 1,162 cl100k_base tokens versus 30,593 for the full catalog.

VariableDefaultEffect
TOKEN_OPTIMIZER_MODEenforceadvise = never refuse; off = disable
TOKEN_OPTIMIZER_LARGE_READ_BYTES25600Size at which a read stops being cheap
TOKEN_OPTIMIZER_PRECOMPACT_TIMEOUT_MS8000Cap on pre-compaction work
TOKEN_OPTIMIZER_LOG_DIRstate logsStructured lifecycle JSONL directory
TOKEN_OPTIMIZER_LOG_MAX_BYTES5242880Rotate an active lifecycle log at size
TOKEN_OPTIMIZER_LOG_RETENTION_DAYS14Maximum lifecycle log age
TOKEN_OPTIMIZER_LOG_MAX_FILES40Maximum retained lifecycle log files

An unrecognised TOKEN_OPTIMIZER_MODE falls back to enforce, so a typo cannot quietly turn the product off.