Harness ledger¶
Per agent client ("harness"), the client version Cartographer was last aligned
with, where that client announces changes, and which parts of the provider matrix
depend on it. The matrix itself stays the source of truth for what is written
where (destinationMatrix in internal/provisioning/provisioning.go,
projectDestinationMatrix in internal/provisioning/workspacescope.go, the
descriptors in internal/configurator/registry.go); this page records how
recently it was checked and what to watch. The cartographer-audit-clients skill
(.claude/skills/cartographer-audit-clients/SKILL.md) reads it as its baseline and updates it
as its output (D292).
TestHarnessLedgerCoversEveryProvider requires one ## <provider-id> section per
provider in configurator.Providers() and no section for an unknown one.
Conventions: unknown means no version or date was ever recorded in this
repository; unverified means a source was named but not confirmed to exist. A
value is never filled in from memory. Documentation is not evidence: a change that
would flip a matrix cell is confirmed with a probe
(.claude/skills/cartographer-audit-clients/references/probes.md), not from a changelog line.
Project skills and instructions below a bound folder (probe 2026-10-21, D1019). A project
skill and project instructions in a bound non-git folder W, asked back from W, from a git
repository W/repo and from a plain subfolder W/plain. A client that looks for project
skills only up to the repository root gets, from a folder binding, the repositories below it as
tools (through the bridge, D737) but not their skills or agents: a repository a KB declares in its
paths.yaml is therefore bound itself and projected into (sync.md §Workspace scope).
| Client (version) | skill in W/repo |
instructions in W/repo |
|---|---|---|
| Claude Code 2.1.304 | no | yes (CLAUDE.md is read up every ancestor) |
| Codex 0.163.0 | no | no |
| Copilot CLI 1.0.98 | no | no |
| Kiro CLI 2.32.0 | no | no |
| OpenCode 2.0.32 | yes | no |
Claude Code 2.1.304 also reads an untracked CLAUDE.local.md beside a tracked CLAUDE.md
(probed 2026-10-22: a unique token in it was repeated by claude -p), which is where a derived
binding puts its instructions block when the repository tracks CLAUDE.md.
claude¶
- Aligned with:
2.1.286— 2026-10-01. Documentary review of the changelog from 2.1.246 (about 40 releases) and of the vendor docs; one cell probed (the projectCLAUDE.mdvsAGENTS.mdprecedence, below), the others not re-probed. - Sources (reachable on 2026-10-01): changelog
https://raw.githubusercontent.com/anthropics/claude-code/main/CHANGELOG.md;
version:
claude --version, latestnpm view @anthropic-ai/claude-code version(dist-tagslatest,next,stable); docs https://code.claude.com/docs/en/memory,/sub-agents,/skills,/hooks,/mcp,/settingsunder the same prefix. - Depends on:
- Stdio bridge (D737):
cartographer mcp --provider claudeis spawned in the session's folder (probe 2026-10-17, Claude Code 2.1.302: working directory yes,rootsdeclared with[cwd]). The token variable reaches the child (the process environment is inherited). Replaces the D717 project-entry shadowing, which is no longer used. - Writer header (D904): an HTTP entry carries
Cartographer-Authorinheaders, next toAuthorization. skill/agent/hookin~/.claude/{skills,agents,hooks}/, project-local in.claude/…(D137, D193);mcpin~/.claude.json(project:.mcp.json);instructionsin~/.claude/CLAUDE.md(project:CLAUDE.md). UnderCLAUDE_CONFIG_DIRonly thecartographerMCP entries followclients.claude.config_dirs(D755); everything else here stays$HOME-relative (symlink it per account).- Agent translation is a passthrough: Cartographer subagents are Claude
subagents; Claude takes its own restriction fields (
tools, alsodisallowedTools,permissionMode) at the top level (D291). - Sync layer 1:
SessionStartentry in~/.claude/settings.json(docs/sync.md§Layer 1); hooks run through Git Bash on Windows, PowerShell as the documented fallback (D267). - Write-findings feedback (D353): a
PostToolUseentry (matcher on the MCP tool name) whose command exits 2 with a message on stderr returns that message to the agent. Payload:tool_nameandtool_response. The other clients were probed on 2026-10-09 (#637–#640): codex and opencode carry the findings through a different channel (their sections), antigravity and kiro cannot carry them at all. CLAUDE.md→@AGENTS.mdimport and per-directory loading (D213). Since 2.1.277 the built-inagents-md@builtinplugin (on by default) reads a projectAGENTS.mditself, but only when noCLAUDE.md/CLAUDE.local.mdis on the project path; the import stays necessary wherever aCLAUDE.mdexists.- session transcripts, read by the usage scan (D326):
~/.claude/projects/**/*.jsonl, one JSON record per line;assistantrecords carrymessage.contentblocks, and the scan reads onlytool_useblocks (theSkilltool'sinput.skill, theAgent/Tasktool'sinput.subagent_type, and any other tool whose arguments carry a materialised skill path). The format is undocumented: an unknown shape is skipped, never fatal. - Watch items:
- the
PostToolUsepayload shape of an MCP result (tool_response) is not documented to the byte: the write-findings hook accepts the result object, a content-block array and JSON in a text block, and is silent on any other shape, so a change shows up as the hook going quiet. - the project
instructionsblock prepends@AGENTS.mdwhen the project root has one, because a projectCLAUDE.mdhides the repository'sAGENTS.mdfrom the built-in plugin otherwise (D293). - claude.ai account-synced skills share
~/.claude/skills/(2.1.275, 2.1.280); not a cell. - Probe notes: the AGENTS.md probe needs the plugin on: a machine can disable
it (
"agents-md@builtin": falsein~/.claude/settings.json), so pass--settings '{"enabledPlugins":{"agents-md@builtin":true}}'toclaude -pto test the default. Ask for a token planted in the file under test.
codex¶
- Aligned with:
0.162.0— 2026-10-09 for the write-findings probe (#637, below);0.159.3— 2026-10-01 (documentary review). Probed on0.158.0— 2026-10-01:codex debug prompt-inputcatalogues skills from both~/.codex/skillsand~/.agents/skills(D192 still holds); a user-layerSessionStarthook fires incodex exec, but only for a trusted hook definition; a project's.codex/hooks.jsonruns only once the project is trusted (D193 still holds). Not probed:sandbox_modeon an agent. - Sources: changelog https://learn.chatgpt.com/docs/changelog; releases
https://github.com/openai/codex/releases (tags
rust-v<version>); version:npm view @openai/codex version,codex --version. Documentation (thedevelopers.openai.com/codex/...URLs redirect here): https://learn.chatgpt.com/docs/build-skills, https://learn.chatgpt.com/docs/agent-configuration/agents-md, https://learn.chatgpt.com/docs/agent-configuration/subagents, https://learn.chatgpt.com/docs/hooks, https://learn.chatgpt.com/docs/extend/mcp?surface=cli. - Depends on:
- Stdio bridge (D737): spawned in the session's folder with
$PWDunset (probe 2026-10-17, Codex 0.163.0);rootsnot declared. Codex filters the environment of an MCP server, so the entry lists the token variable inenv_vars; every other client inherits it. - Writer header (D904): an HTTP entry carries it in
http_headers, which Codex sends as written (config reference; not probed). Auth staysbearer_token_env_var. skillglobal~/.codex/skills/(deliberate divergence from the documented$HOME/.agents/skills, still the only documented user path, D192, guarded byclientcompat_test.go); project.agents/skills/(D193).agentas TOML (name/description/developer_instructions) in~/.codex/agents/(project:.codex/agents/);sandbox_modeis a documented optional agent field (D291: documented, not probed).hookfiles in~/.codex/hooks/, registered in~/.codex/hooks.json(D230;config.tomland project.codex/hooks.jsonare also documented); sync layer 1SessionStart.mcpandinstructionsin~/.codex/config.tomland~/.codex/AGENTS.md(AGENTS.override.mdin the same directory wins, first non-empty file only); hook trust is keyed by the exact hook definition, and a project's.codex/layer is inactive unless the project is trusted (D193);workspace bind codex … --trustwrites the[projects."<path>"]table on request (D1074).PostToolUsewrite-findings hook (D361), registered in the samehooks.json.- write-findings feedback (D353, probed on 0.162.0, #637): a user-layer
PostToolUseentry with Claude's matcher (mcp__.*__(concept_write|…)$) fires for an MCP tool namedmcp__<server>__<tool>; the payload carriestool_nameandtool_responseas the MCP result object (contentblocks), whichcartographer hook write-findingsalready parses. Exit 2 is the wrong channel here: Codex reportsPostToolUse Blocked, replaces the tool result with the stderr text, and the agent, seeing a failed call, repeats the write.{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"…"}}on stdout with exit 0 reaches the model and keeps the result; exit 0 with stderr only does not reach it (negative control). Supported (D361): the hook is installed with--channel context; the user approves it once. - session transcripts, read by the usage scan (D326):
~/.codex/sessions/**/rollout-*.jsonl. Codex records no per-activation skill event: aworld_stateevent whosepayload.state.host_skillsis non-empty proves the catalogue was loaded (a catalogue sighting, not a use), and aresponse_itemtool call (function_call,local_shell_call,custom_tool_call,mcp_tool_call) whose arguments carry a materialised skill path is a use. Message and reasoning items are never read. - Watch items: none open.
- Probe notes:
codex debug prompt-inputlists the catalogued skills (no model call). Isolate a run with a tempHOMEandCODEX_HOME, copying onlyauth.json; close stdin (</dev/null) orcodex execwaits for input. Hook trust is per definition (atrusted_hashunder[hooks.state]inconfig.toml, granted interactively): an untrusted sentinel never fires, so probe withcodex exec --dangerously-bypass-hook-trustinside the isolated home only. Project trust:[projects."<path>"] trust_level = "trusted".
kiro¶
- Aligned with:
2.28.0— 2026-10-09 for the write-findings probe (#640, below;chatwithout flags still runs the v2 engine and announces V3 as an early release);2.27.0— 2026-10-02 for thehookcell (D300: the default interactive TUI,--no-interactive,--v3 --tui, the default-agent probe);2.26.1— 2026-10-01 for the first hook re-probe (KAS0.66.15);2.21.3— 2026-09-11 for the agent and hook cells (D195);2.21.4for skill symlinks (D207,CONTRIBUTING.md);2.20.0— 2026-08-27 for D140. - Sources: changelog https://kiro.dev/changelog/cli/; hook docs
https://kiro.dev/docs/hooks/ and https://kiro.dev/docs/cli/v3/hooks-migration/
(all cited in D195/D140); version:
brew info --cask kiro-cli. - Depends on:
- Stdio bridge (D737): spawned in the session's folder (probe 2026-10-17, Kiro CLI 2.32.0);
rootsnot declared. Kiro IDE not probed: an IDE that spawns the server outside the workspace and declares no roots gets the provider's default set. - Writer header (D904): none. Kiro documents
headersfor a remote server (https://kiro.dev/docs/mcp/configuration/), but the emitter writes no headers for Kiro,Authorizationincluded (an older gap), so a write over a Kiro HTTP entry is authored by the token; the bridge names the writer. agentas JSON (name/description/prompt) in~/.kiro/agents/, workspace.kiro/agents/wins over global (D195); native restriction keys believed to betools/allowedTools(D291, not verified). The ledger names no read-only tool set, so the repository's read-only agents list["*"]and keep the restriction in the prompt; an agent with notoolshas none (D300).hookin~/.kiro/hooks/cartographer/<name>/, registered in the owned~/.kiro/hooks/cartographer.json(D300). It fires only inkiro-cli chat --v3 --tui, so the scheduled timer stays advised. The loader must stay non-recursive, or the cell has to move out of~/.kiro/hooks/. The workspace cell stays unsupported.- write-findings feedback (D353): not supportable (probed on 2.28.0,
chat --v3 --tuiwith workspace.kiro/hooks/*.json, #640).PostToolUsefires, fortool_loadas well as for the MCP call, and an MCP tool is namedmcp_<server>_<tool>(single underscores; Claude's matcher never matches);tool_responseis the result text. No output reaches the model: exit 2 with stderr, plain stdout,additionalContextJSON and{"decision":"block"}all left the agent unaware. skillin~/.kiro/skills/(project.kiro/skills/),mcpin~/.kiro/settings/mcp.json,instructionsin~/.kiro/steering/cartographer.md.- session transcripts, read by the usage scan (D326):
~/.kiro/sessions/**/*.jsonl. When the model activates a skill it reads itsSKILL.mdwith the built-in file-read tool, recorded askind.BuiltIn.FileRead.operations[].path; a shell record carries the path in its command. The scan reads only thekindobject. The record shape is pinned byinternal/provisioning/testdata/usage/kiro-session.jsonl(home replaced by$HOME). It was observed on the operator's machine on 2026-10-05; the Kiro version was not recorded then, so none is declared here: re-probe on a machine with Kiro, read the shape off a real record, and write the version on this line. - Watch items:
- the default
kiro-cli chatstarts firing standalone hooks (its KAS log showsv2 hooks cache initialized). Then drop thesessionHookLimiton the Kiro hook mechanism, and the timer advice with it; - the usage scan's record shape (above) changes: a new Kiro release that renames
kind.BuiltIn.FileReadmakes every Kiro skill look unused, silently; - Kiro IDE: does it read a global
~/.kiro/hooks, and fire aSessionStartfrom it? - Kiro Crew: does
~/.kiro/crew/hooks/take the same v1 file?
Probe both on a machine that has them before any matrix cell claims them.
- Probe notes: run the real binary
("/Applications/Kiro CLI.app/Contents/MacOS/kiro-cli" on macOS; the Homebrew
symlink breaks its launcher). The V3 TUI asks before running an MCP tool, and a
scripted \r does not answer it; use -a and accept its warning (down arrow,
then Enter) before typing the prompt. A first run on a clean profile creates
~/.kiro/{logs,sessions,session-index,agents}: remove them afterwards. Three agent engines coexist (--agent-engine
v1|v2|v3, default v2): a feature present in a non-default engine is not
"supported". An interactive probe needs a pty. Details in the probe recipe.
opencode¶
- Aligned with:
2.0.30— 2026-10-17, probed: project agents in.opencode/agents/(opencode debug agentslists them; it does not load.claude/agents/) and.agents/skills/found,.opencode/skills/winning.2.0.25— 2026-10-09, probed (#478, #638): global skill and agent discovery, agentpermission, the write-findings channel.1.18.34— 2026-10-01 (documentary review). Earlier probe:1.18.20, dateunknown(D192). - Sources: repository https://github.com/anomalyco/opencode (
sst/opencoderedirects there), releases https://github.com/anomalyco/opencode/releases, changelog https://opencode.ai/changelog; version: npmopencode-ai; docs https://opencode.ai/docs/agents,/skills,/plugins,/mcp-servers,/rules,/config. - Depends on:
- Stdio bridge (D737): spawned in the session's folder but with
$PWDset to$HOME(probe 2026-10-17, OpenCode 2.0.30), which is why the bridge readsos.Getwd, never$PWD;rootsdeclared with[cwd]. - Writer header (D904): an HTTP entry carries it in
headers; the token's${VAR}becomes{env:VAR}, the author is a literal. agentglobal~/.config/opencode/agents/(theconfigdirectory ofopencode debug paths, probed on 2.0.25 and the documented 1.x path, D360, guarded byclientcompat_test.go;~/.opencode/agent/is not loaded on 2.x): Markdown withdescription+mode: subagent. Native restriction keypermission(edit,bash, … allow/ask/deny) is documented (D291);toolsis no longer shown in the agents doc: usepermissioninstead,toolsmay still work but is undocumented (D320).skillglobal~/.config/opencode/skills/(probed on 2.0.25, D360); project.opencode/skills/(documented, not probed on 2.x). Hooks fire through a generated JS plugin in~/.config/opencode/plugins/(documented, autoloaded; D59; shape per installed major, 1.x and 2.x, D359: 2.x rejects the 1.x shape; an unreadable version writes the newest shape with a warning, D719; sourcesopencode.ai/v2/docs/build/plugins/and/migrate-v1), files kept in~/.opencode/hooks/(never discovered by the client, run by path); sync layer 1 is the documentedsession.createdevent.mcpunder themcpkey of~/.config/opencode/opencode.json, the global config file of both majors (D1172:$HOME/opencode.jsonis only a project file found by walking up from the session folder, and 1.x stops at the git root);instructionsin~/.config/opencode/AGENTS.md(both documented).- Probed on 2.0.25 (2026-10-09):
- the former global
skillandagentcells were not loaded (moved by D360): a skill in~/.opencode/skills/is missing from the skill tool ("Unable to load skill"), an agent in~/.opencode/agent/is missing fromopencode debug agents; the same files in~/.config/opencode/{skills,agents}/load. KB skills reach OpenCode only through its~/.claude/skillsscan. - agent
permission: {edit: deny, bash: deny}resolves toedit/shelldeny rules inopencode debug agents; the behaviour was not verifiable (the free tier refused to run that agent). - write-findings (D353, #638):
ctx.tool.hook("execute.after")fires for the code-modeexecutetool and for the inner MCP call, named<server>_<tool>with the result text inresult.output. Appending toevent.result.outputreaches the model and keeps the result; throwing reaches it as a tool error and the agent retries the write. The generic plugin passes no payload on stdin. Implemented as a dedicated plugin for 2.x only (D362): it appends the message toresult.outputon exit 2 and never throws; 1.x was not probed and gets nothing. The inner call's output joins the write response and the server's sync-state block with a newline; the subcommand reads both values. opencode --versionprintsopencode v2.0.25(seen on both streams); the major parser reads it (D719). The no-PATHsync run andsession.createddelivery toctx.event.subscribeare not yet probed.- 2.x
opencode.jsonis translated on load (mcp→mcp.servers,permissionmap →permissionslist), so the 1.x shape still works. - Watch items: the project skill cell (
.opencode/skills) is documented. The project agent cell inprojectDestinationMatrixis.opencode/agent, while the 2.0.30 probe listed project agents from.opencode/agents/: the matrix cell and the probe disagree. - Probe notes: 2.x has no
opencode agent list: useopencode debug agents(JSON) andopencode debug paths. A background service caches the configuration: runopencode reloadafter changing a file.opencode run -m opencode/big-pickleworks without credentials, but the free tier refuses some custom primary agents ("can only be used from within OpenCode").
antigravity¶
- Aligned with: CLI
agy1.3.2— 2026-10-09, probed (#478, #639). App2.19.1— 2026-10-01 (documentary review; the app was not available for the probe). The CLI is versioned separately (agy --version). - Sources: changelog https://antigravity.google/docs/changelog/; CLI
changelog
https://github.com/google-antigravity/antigravity-cli/blob/main/CHANGELOG.md;
docs https://antigravity.google/docs/rules (
/docs/rules-workflows/redirects there),/docs/skills,/docs/subagents,/docs/hooks,/docs/mcp; installed version source:unverified. - Depends on (what the matrix encodes; D193/D207, not re-probed):
- Stdio bridge (D737): not probed (2026-10-17) for the IDE nor for
agy. If the host spawns the server outside the workspace and declares noroots, the session gets the provider's default set;cartographer workspace resolveshows what the bridge would pick for a folder. - Writer header (D904): an HTTP entry carries it in
headers. - Global, under
~/.gemini:skillconfig/skills,agentconfig/agents(Markdown:name,description,mainAgent: false,subagent: true),hookconfig/hooksregistered in~/.gemini/config/hooks.json,mcpconfig/mcp_config.json,instructionsGEMINI.md. - Project-local (D364):
skill.agents/skills,agent.agents/agents(same translation),hook.agents/hooks/<n>/registered in.agents/hooks.json(the file is picked from the hook's path),mcp.agents/mcp_config.json,instructionstheAGENTS.mdblock. Rules (.agents/rules/) are deliberately unused: they needtrigger: always_on. - Native hooks support
SessionStart(D1007),PreToolUse,PostToolUse,PreInvocation,PostInvocation, andStop. Sync layer 1 installs thecartographer-bootstraphook for Antigravity (D60, D1007). Agent frontmatter documentstools,modelandcommandExecutionPolicy(candidate D291 keys, not verified). - Probed on CLI 1.3.2 (2026-10-09):
- workspace scope confirmed (now the project cells above):
.agents/skills/,.agents/agents/,.agents/hooks.json,.agents/mcp_config.json(used in the session even thoughagy mcp listshows only global servers),AGENTS.md, and.agents/rules/*.mdonly with frontmattertrigger: always_on; nothing in a directory without.agents/. - globals: the CLI reads
~/.gemini/config/{skills,agents}(the current cells), not~/.gemini/antigravity-cli/{skills,agents}as its docs say. - agent
tools: [view_file]+commandExecutionPolicy: neverdid not restrict the agent (it ran a shell command): not D291 keys. - write-findings (D353, #639): not supportable.
PostToolUsefires for an MCP call as toolcall_mcp_tool(argsServerName,ToolName,Arguments), so Claude's matcher never matches, and the payload (toolCall,error,conversationId,stepIdx,transcriptPath,workspacePaths, …) has no tool result. A failed hook (exit 2, stderr) does reach the model; exit 0 with stderr does not. - Watch items: the app's workspace scope and
.gemini/config.json(2.17.0), not probed; aSessionStartevent would change the layer-1 trigger; a tool result in thePostToolUsepayload would reopen write-findings. - Probe notes:
agy -p "<prompt>" --print-timeout 240s --dangerously-skip-permissions </dev/null; the MCP test server must be global (~/.gemini/config/mcp_config.json) or in.agents/mcp_config.json. Back up and restore~/.gemini/config/*around a global probe.
crush¶
- Aligned with:
v0.98.0— 2026-10-09, probed (#478). - Sources: releases https://github.com/charmbracelet/crush/releases; README
https://github.com/charmbracelet/crush; config
https://github.com/charmbracelet/crush/tree/main/docs/config; hooks
https://github.com/charmbracelet/crush/tree/main/docs/hooks; JSON schema
https://charm.land/crush.json; package: Homebrew tap
charmbracelet/tap/crush, npm@charmland/crush(not in homebrew-core). - Depends on:
- Stdio bridge (D737): spawned in the session's folder (probe 2026-10-17, Crush 0.98.1);
rootsdeclared with an empty list, so the working directory decides. - Writer header (D904): an HTTP entry carries it in
headers; a value Crush would expand ($VAR,$(cmd)) is written in the encoded form, never as is. mcpin~/.config/crush/crush.json— JSON Crush documents as deprecated (no new options) in favour ofcrushrc, a Bash file Cartographer refuses to write;$VARform for values,$(refused (D225). JSON is still read and merged withcrushrc.instructionsin~/.config/crush/CRUSH.md(Crush also loads~/.config/AGENTS.md);skillin~/.config/crush/skills/(project.crush/skills/; Crush also scans~/.claude/skills,~/.agents/skillsand the.agents/.claude/.cursorproject skill directories).hookin~/.config/crush/hooks/<name>/, registered ashooks.PreToolUseentrycartographer-<name>incrush.json(D363); project:.crush.jsonand.crush/hooks/.mcpalso has a project cell,.crush.json.agentunsupported (no documented subagent mechanism); sync layer 1 is the timer.- Probed on v0.98.0 (2026-10-09):
- hooks:
hooks.PreToolUsein~/.config/crush/crush.jsonand in a project.crush.jsonfire (negative control: none); of six events tried onlyPreToolUsefires. Exit 2 blocks the tool and its stderr reaches the model. Payload:cwd,event,session_id,tool_input,tool_name(lowercase, e.g.bash). There is no session event (D363). - a project
.crush.jsonmcpentry is used by the session (D363: projectmcpandhookcells;agentandinstructionsnot probed). - the global
crush.jsonis still read when acrushrcexists. - Watch items:
crush.jsonbecoming unreadable, orcrushrcthe only format, would remove themcpcell; a session event would allow the bootstrap hook, aPostToolUsethat fires the write-findings hook. - Probe notes:
crush run -q -m openai/gpt-5.5 "<prompt>" </dev/null(the default model may be refused by a ChatGPT account);--yolois a root flag, not accepted byrun.~/.config/crush/may not exist: create it for a global probe and remove it afterwards.
copilot¶
- Aligned with:
1.0.98— 2026-10-17, probed: project agents in.github/agents/<name>.agent.mdload once the folder is trusted, themodelkey is honoured and an unavailable model falls back toautowith a warning.1.0.94— 2026-10-10, probed (#676). The GitHub Copilot CLI (copilot), not Copilot in VS Code. - Sources (
unverified): releases https://github.com/github/copilot-cli/releases; docs https://docs.github.com/copilot/how-tos/use-copilot-agents/use-copilot-cli. Every cell below comes from a probe withCOPILOT_HOMEpointed at a scratch directory, not from these pages. - Depends on:
- Stdio bridge (D737): spawned in the session's folder (probe 2026-10-17, Copilot CLI 1.0.98);
rootsnot declared. - Writer header (D904): an HTTP entry carries it in
headers, next toAuthorization. mcpin~/.copilot/mcp-config.json(mcpServers,type: "http",headers,"tools": ["*"]);${VAR}in a header value is expanded from the environment. Withouttoolsa non-interactive session is offered nothing from the server.instructionsin~/.copilot/copilot-instructions.md("Personal instructions" incopilot instruction list); projectAGENTS.md("Repository instructions").skillin~/.copilot/skills/<name>/("Personal skills"); project.agents/skills/<name>/("Project skills";.github/skills/is listed too).agentin~/.copilot/agents/<name>.agent.md(frontmattername,description); a session reported seeing it.hookin a dedicated~/.copilot/hooks/cartographer-<name>.json({"version":1,"hooks":{"<event>":[{"type":"command","bash":…,"powershell":…}]}});~/.copilot/settings.jsonalso takes inline hooks and is never patched (D676). The KB hook's own files go to~/.copilot/cartographer-hooks/<name>/, outsidehooks/: Copilot loads~/.copilot/hooks/recursively and parses every*.jsonbelow it (probed: a non-Copilot JSON in a subdirectory logged "Invalid hook configuration … hooks must be an object").- Project
mcp,agentandhookcells unsupported:.mcp.json/.github/mcp.jsonare documented but not listed bycopilot mcp listin an untrusted folder, and.github/agentsand.github/hooksare gated on folder trust (--help). COPILOT_HOMEis not honoured: paths are$HOME/.copilot, like every provider.- Probed on 1.0.94 (2026-10-10):
- hooks:
sessionStart,preToolUse,postToolUsefire (other events not probed, not claimed). Payload (camelCase):sessionId,timestamp,cwd,toolName,toolArgs;postToolUseaddstoolResult: {resultType, textResultForLlm}. No matcher field: a hook fires for every tool. preToolUsestdout{"permissionDecision":"deny","permissionDecisionReason":…}blocks the call;postToolUsestdout{"additionalContext":…}(top level) is appended to the tool result the model reads (the write-findings hook, D676).- MCP tools are
<server_name>-<tool>in hook payloads.textResultForLlmis the response JSON followed, with no separator, by a second object ({"last_error":"","sync_state":"pending"}). - session transcripts:
~/.copilot/session-state/<session>/events.jsonl; a skill activation istool.execution_startwithdata.toolName: "skill"anddata.arguments.skill. - non-interactive:
copilot -p "<prompt>" -s; tools need a grant (--allow-tool <server_name>,--allow-all-tools), passed with--client-flag. - Watch items: project cells under folder trust (they would flip the three
unsupported project cells); whether
sessionStartoutput reaches the model (the bootstrap hook only needs its side effect); a matcher field. - Probe notes:
COPILOT_HOME=<scratch> copilot instruction list | skill list | mcp listshow the cells without a model; hooks needcopilot -p … -s --allow-all-tools. Never point the probe at$HOME/.copilot.