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, no longer an AGENTS.md in the KB — removed by 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), 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 always talks to the server over HTTP (no stdio transport on the client side, D37).

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;
  • tests under internal/configurator and internal/provisioning — executable compatibility contract.

Known divergences from the documented path (D192)

Two destinations differ from the path the provider's own documentation currently presents as canonical. Both were proven working against the real client, so neither is a fault today — but both 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) client 0.153.4
agent × opencode ~/.opencode/agent/<name>.md .opencode/agents (source) client 1.18.20

Neither is moved here: a destination change is a migration (prune the old files, re-key the lockfile), and what was missing was the alarm, not the move. The Codex case is now half-resolved: the workspace scope (D193) does use the repository path the vendor documents, .agents/skills/<name>/, because that scope is new and has no installed base to migrate. The global cell stays at ~/.codex/skills/ for the reason above.

Current limitations are documented once in the relevant table/section rather than repeated here. In particular, Kiro's flat MCP tool namespace may require the server's per-KB tool prefix, and 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/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
Hermes none its configuration is rendered by its own Ansible role and skills go to one inbox (D141)
Antigravity none only a global configuration root is documented (D194)

Two consequences are worth stating plainly. Kiro receives subagents in both scopes since D195 but keeps an unsupported hook cell, because the shipped client has no hook mechanism at all. 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.

Kiro hooks: documented, not shipped (D195)

Kiro's documentation describes standalone hooks — .kiro/hooks/*.json with a "version": "v1" schema, and ~/.kiro/hooks/ firing in every workspace. The shipped client does not implement them. Verified on Kiro CLI 2.21.3, 2026-09-11:

  • a hook in ~/.kiro/hooks/ and in the workspace's .kiro/hooks/, with each of AgentSpawn, SessionStart, PromptSubmit, UserPromptSubmit and PreToolUse, never fires — in a session that completes normally, with --v3;
  • the agent log never mentions hooks, the config kiro-cli agent create writes has no hooks key, and the shipped agent binary contains no .kiro/hooks path (it does contain .kiro/agents, .kiro/skills, .kiro/steering).

The reason is in the vendor's own text: the v1 hook format was "introduced in IDE 1.0 and CLI 3.0", and the CLI changelog puts 3.0 in early access with 2.21.x on the release channel. kiro-cli --v3 launches the next-generation agent, which is not the same thing as CLI 3.0.

The documentation also contradicts itself on the trigger names: the migration page lists SessionStart among the CLI triggers, while the feature page marks SessionStart as IDE-only and AgentSpawn as CLI-only. D140 recorded the same pattern against 2.20.0.

So Kiro's hook cell stays unsupported and its re-sync trigger stays the scheduled timer. Re-check when CLI 3.0 reaches the release channel.

Instruction slots Cartographer deliberately does not write

Leveraging a provider to the fullest also means declining to write where the write would not survive, or would destroy what another owner maintains. Two Hermes slots are unsupported for that reason (D141), not for lack of a mapping:

  • SOUL.md, its always-on instruction slot — operator-owned and rendered from a template by an Ansible role, so a managed block written there is gone on the next playbook run. The imprinting that reaches every other provider as a kind: instructions block simply does not reach Hermes;
  • config.yaml, its MCP endpoint list — rendered by the same role, for the same reason. connect hermes therefore configures no MCP entry and says so.

  • $HERMES_HOME/skills/ is a third: not an instruction slot but the agent's own curated skill store, rewritten by its curator from its learning loop. Cartographer delivers proposals to skill-inbox/<name>/cartographer/ and the agent adopts what it chooses — see sync.md §Hermes.