Skip to content

Interoperability: OKF, providers and the configurator

OKF conformance

Every KB is a conformant OKF v0.1 bundle and a git repository in its own right. Any external OKF tool can consume it without modification. Everything is git + files: history, diff, backup, sharing, zero lock-in. The skills (SKILL.md agentskills.io) and secrets (SOPS) are likewise open, portable standards.

Obsidian is the human viewer (graph view, Dataview), conceptually read-only.

Hard rules vs soft guidance

  • Hard rules → server: path/layout validation, strict-map type palettes, optimistic writes and git serialization. Agents use MCP tools instead of editing KB files directly.
  • Soft guidance → instructions provisioning (D56/D61; the KB carries no AGENTS.md, D62): a generated block injected into each provider's global instructions file (.claude/CLAUDE.md, .config/opencode/AGENTS.md, .codex/AGENTS.md, Kiro steering, .gemini/GEMINI.md, .config/crush/CRUSH.md, .copilot/copilot-instructions.md), plus the optional curated instructions.md in the KB root (D61) and the auto-generated agent section — see sync.md §Instructions.

The MCP + skill + hook triad

Level What it does Token cost
MCP Data and capabilities (bounded reads, structured frontmatter queries, search, validated writes) Proportional to the content read
Skill Competence/procedure (how to do ingest/query/lint), loaded on-demand ~100 tokens catalog; body on-demand
Hook Deterministic client-side automation distributed by the KB No model cost unless the hook invokes an agent

Multi-provider configurator

A dedicated tool (the cartographer client subcommands — agents/connect/status/sync, see docs/configurator.md) configures skills, MCP, hooks (and references to services/secrets) on each provider leveraging its capabilities to the fullest — no least-common-denominator. The client talks to the server over HTTP (D37); the MCP entry it writes for a provider with a workspace binding is the local stdio bridge cartographer mcp --provider <name>, which proxies the session to the server (D737).

Single source-of-truth → per-provider adapter: the source is the provisioning manifest generated by the server (compiled bundle + artifacts of the mounted KBs — skills, agents, hooks, instructions); a per-provider adapter (internal/configurator for the MCP config, internal/provisioning.Apply for materialization) translates each artifact into the native constructs, discarding what cannot be reliably mapped instead of guessing it. The full kind×provider matrix is in sync.md §Kind × provider matrix.

TUI: interactive dashboard (cartographer with no arguments): autodetects installed providers, per-provider status with per-kind counts, connect/resync/disconnect — see configurator.md §TUI mode.

Idempotent and non-destructive sync: deep-merge for JSON; marker-delimited blocks for TOML and instruction files; never overwrite the user's contracts or secrets; dry-run.

Automatic realignment when skills/agents/hooks change (bundle or KB): manifest+revision server-side, lockfile client-side, drift detection and layered triggers (SessionStart hook, MCP tool, push). See → sync.md.

Secrets and local commands: MCP descriptors may name environment variables in provider-native syntax, but Cartographer does not distribute or resolve their values. A trusted stdio descriptor configures a provider to run a locally preflighted executable; Cartographer never launches it during provisioning. Runtime secret injection remains an operator responsibility.

Provider behavior

Provider formats change independently of Cartographer, so this page does not duplicate a dated market-wide capability matrix. The maintained sources are:

  • configurator — exact files Cartographer reads and writes;
  • synchronization — the kind × provider materialization matrix, translation losses, trust and pruning;
  • harness ledger — per client, the version last aligned with, where its changes are announced and which cells depend on it;
  • tests under internal/configurator and internal/provisioning — executable compatibility contract.

Known divergences from the documented path (D192)

One destination differs from the path the provider's own documentation currently presents as canonical. It was proven working against the real client, so it is not a fault today — but it can break on a client release, which is why internal/provisioning/clientcompat_test.go asserts the declared destination against the client's own discovery output on a machine that has the client installed (and skips where it does not).

Kind × provider Cartographer writes Provider documents Last verified
skill × codex ~/.codex/skills/<name>/ $HOME/.agents/skills (source) the version in the harness ledger

The global cell is not moved: a destination change is a migration (the lockfile-driven relocation of D360 does it), and what the cell needs is the alarm. The workspace scope (D193) uses the repository path the vendor documents, .agents/skills/<name>/, because that scope has no installed base to migrate. The OpenCode global cells (~/.config/opencode/{skills,agents}/) are asserted against opencode debug paths (D360).

Current limitations are documented once in the relevant table/section rather than repeated here. In particular, provider translations intentionally drop fields that cannot be represented safely.

Project-local scopes as an external contract (D193)

The workspace scope writes into each provider's project-local configuration, which is a second set of external contracts, verified during the D193 audit and changing outside this project's release cycle. Re-verify before changing a cell; the citation lives next to it in internal/provisioning/workspacescope.go.

Provider Project-local scope Source
Claude Code .claude/skills/, .claude/agents/, .claude/hooks/, .mcp.json, ./CLAUDE.md skills, memory, sub-agents, hooks, mcp
Codex .agents/skills, .codex/agents, .codex/hooks, .codex/hooks.json, .codex/config.toml, AGENTS.md skills, subagents, hooks, mcp
Kiro .kiro/skills/, .kiro/agents/, .kiro/steering/, .kiro/settings/mcp.json skills, custom agents
OpenCode .opencode/skills, .opencode/agent, .opencode/hooks, opencode.json, AGENTS.md skills, rules, agents, plugins
Antigravity .agents/skills, .agents/agents, .agents/hooks, .agents/hooks.json, .agents/mcp_config.json, AGENTS.md probed on the real client (D364)
Crush .crush/skills, .crush/hooks, .crush.json (mcp, hooks) agents and instructions unsupported (D363)
Copilot CLI AGENTS.md, .agents/skills the project mcp, agent and hook locations are gated on folder trust (D676)

A subagent's tools allow-list is enforced by Claude Code only. The other clients receive the agent without it, and therefore with every tool that client has; each sync warns per agent, and strict_tools: true in the agent's frontmatter skips it on those clients instead (D283). An agent can instead carry each client's own restriction in a providers: frontmatter block (opencode, codex, kiro, antigravity, copilot), copied verbatim into that client's native agent file; a client with an entry is not widened, so it is neither warned about nor skipped (D291). Cartographer does not infer the syntax, and which native keys each client honours has not been verified against the real clients: the author writes them and owns their correctness.

Two consequences are worth stating plainly. Kiro receives subagents in both scopes since D195, and hooks only in the global scope, where they fire in one session mode (D300, below). And Codex ignores a project's .codex/ layer unless the project is trusted, which is the one case where writing the files correctly is not the same as the projection being active: status and doctor report it as inactive rather than installed, and workspace bind codex <path> --kb … --trust records the trust on request (D1074).

Kiro hooks: one session mode (D300)

Kiro has hooks on every engine, but a hook Cartographer can own fires in only one of its session modes. Probed on Kiro CLI 2.26.1 and 2.27.0 (macOS, the real binary, an unrelated temp dir, a sentinel file per hook):

Session Standalone ~/.kiro/hooks/*.json hooks inside an agent config
kiro-cli chat interactive (the default; since 2.27.0 a new TUI over the v2 engine) does not fire fires (agentSpawn)
kiro-cli chat --no-interactive does not fire fires
kiro-cli chat --v3 --tui fires (SessionStart, UserPromptSubmit, Stop) fires
--v3 / --agent-engine v3, non-interactive does not fire: the engine builds its hook cache only when the ACP client asks for hooks —

What this means for Cartographer:

  • The registration is a standalone file Cartographer owns whole, ~/.kiro/hooks/cartographer.json ({"version": "v1", "hooks": [...]}), with the hooks' files one level below it. The loader reads only the *.json files directly in ~/.kiro/hooks/: it does not recurse, and a hook file in a subdirectory was not loaded. The scripts are therefore never read as hook files themselves. The workspace .kiro/hooks/ fires in the same mode as the global one, so it adds nothing and stays unsupported.
  • No agent config is written for a hook. An agent's own hooks fire in every mode, but only for that agent. The user's agent is theirs. Shadowing the built-in kiro_default (it can be shadowed in v2 since 2.26.1) would replace its prompt and tools, which is the intrusion D140 refused. A Cartographer-owned agent made the default with chat.defaultAgent would not behave like the default either: an agent with no tools key gets no tools (/tools: "No tools available", against 14 for kiro_default), and the default's prompt is compiled into the binary, so it would have to be copied from a moving target.
  • The scheduled timer stays Kiro's trigger for every session but --v3 --tui. connect, status and doctor say so, and status qualifies the hook count (hook 1/1 (fires in kiro-cli chat --v3 --tui only)).

Kiro IDE (workspace .kiro/hooks/<id>.json is documented, a global directory is not) and Kiro Crew (~/.kiro/crew/hooks/ is documented) were not installed on the probing machine, so no cell claims them.