Skip to main content

Platform capability matrix

This page states exactly what AgentBoot can and cannot do on each platform, because a governance claim that's true on one platform and assumed on the others isn't a governance claim.

Officially supported (enforcement-grade): the CLI surfaces of Claude Code, OpenAI Codex CLI, and GitHub Copilot CLI. On these three, AgentBoot emits blocking compliance hooks from one canonical set of portable hook scripts, kept in lock-step.

Officially supported output (advisory-enforcement): the universal AGENTS.md standard β€” the industry-standard cross-tool instruction file. AgentBoot generates and maintains it as a first-class, officially supported output. Support tier is not enforcement tier: AGENTS.md is advisory by nature (the standard has no hook mechanism), so it never carries blocking enforcement β€” that remains a Claude Code / Codex / Copilot capability.

Community tier (advisory): Cursor, Windsurf, Gemini, JetBrains, and agentskills.io SKILL.md output. AgentBoot emits native instruction files for these, and drift detection still covers the files β€” but AgentBoot does not emit enforcement hooks for them, so nothing enforces the content. (Several of these tools β€” Cursor, Windsurf, Gemini β€” do have hook surfaces of their own; AgentBoot just doesn't bind them today.) Guidance an agent can ignore is not a control.

The matrix​

CapabilityClaude CodeOpenAI Codex CLIGitHub Copilot CLICommunity tier
Compiled instructions (personas, traits, gotchas β†’ native config)βœ… CLAUDE.md, skills, settings.jsonβœ… AGENTS.md, .agents/skills/βœ… copilot-instructions.md, path-scoped .instructions.md, agentsβœ… Native files emitted (Cursor rules, Gemini, JetBrains, SKILL.md) β€” advisory only. The universal AGENTS.md file is an officially supported output (not community tier), but its enforcement class is the same: advisory
Blocking pre-tool-use / lifecycle hooksβœ… Full hook lifecycle (PreToolUse, PostToolUse, Stop, …), blocking on exit code 2, via .claude/settings.jsonβœ… Blocking on exit code 2, via .codex/hooks.json β€” hooks require a trust review unless deployed as managed; tool coverage is partial (shell/patch/MCP, not WebSearch); SessionEnd unsupported⚠️ Blocking on exit code 2, via .github/hooks/agentboot.json β€” lower ceiling: fewer hook types; command-hook timeouts fail open (a slow hook does not block); exit-2 blocking is documented but not yet empirically verified for GA❌ AgentBoot emits no enforcement here β€” instructions only. (Cursor/Windsurf/Gemini have hook surfaces of their own; AgentBoot does not bind them today.)
Drift detectionβœ… Content-hash manifest comparison flags any managed file that's been modifiedβœ… Same mechanismβœ… Same mechanismβœ… Same mechanism β€” the files are still drift-checked, but nothing enforces their content
Managed settings (non-overridable)βœ… managed-settings.json β€” MDM-deployable; overrides user and project settings❌ No native non-overridable settings layer. HARD guardrails are protected at build time (a lower scope cannot silently disable one) and ride in the emitted hooks/config❌ Same as Codex❌ Not available
MCPβœ… .mcp.json compiled and synced, with an approved-server allowlist filterβœ… .codex/config.toml emitted with the AgentBoot MCP server entry ([mcp_servers.agentboot]) automatically⚠️ No MCP config emitted for Copilot β€” point it at the AgentBoot MCP server manually⚠️ Varies by tool; manual setup

Enforcement classification​

Every security-relevant control above falls into exactly one of these classes per platform β€” when evaluating AgentBoot as a control, use the class, not the feature name:

ClassMeaningWhere it applies
Hard-enforcedThe platform mechanically blocks the action; a developer cannot override it locallyClaude Code managed settings via MDM; Claude Code blocking hooks
Enforced, known bypassesBlocks in the normal path, but a documented gap existsCodex hooks (partial tool coverage, trust-review requirement); Copilot exit-2 blocking (not yet empirically GA-verified)
Fail-openEnforces when healthy; a failure/timeout allows the actionCopilot command-hook timeouts; any hook if its runtime dependency (node) is missing
AdvisoryThe agent receives the policy as instructions; nothing enforces itEntire community tier; the officially supported AGENTS.md output; output-scan in default (warn) mode
UnsupportedThe control does not exist on the platformManaged settings outside Claude Code; MCP allowlisting outside compiled configs

Prompt instructions are not a security boundary. An instruction saying "never do X" is behavior shaping; prompt injection or simple non-compliance can bypass it. Hard controls live outside the prompt: hooks, managed settings, platform permissions, and your organization's own perimeter (network egress, DLP, branch protection). agentboot doctor prints an Enforcement section that applies this classification to your actual config: if you have hard org policy configured and an output platform can only receive it as advisory instructions, doctor says so.

Reading the matrix honestly​

  • Drift detection detects; it does not prevent. A content-hash mismatch tells you a synced repo has modified managed files β€” visibly, in /ab status and list_repos. It does not stop the modification from happening. What AgentBoot gives you is drift you can see, not drift that cannot occur.
  • Copilot's ceiling is real and stated on purpose. Its hooks block on exit code 2 like the other two, but it exposes fewer hook types, its command-hook timeouts fail open (a slow hook does not block), and exit-2 blocking is documented but not yet empirically verified for GA. If your control depends on a specific lifecycle event, verify it exists on your target platform before you rely on it.
  • Codex hooks aren't zero-config. They require a trust review unless deployed as managed, and cover shell/patch/MCP calls (not WebSearch) β€” confirm the tool call you want to gate is in scope.
  • Support is scoped to the CLI surface β€” for now. Official support covers each tool's command-line surface. The IDE and editor extensions of these same tools, and additional platforms, are on the roadmap β€” not shipped today. If your team lives primarily in an IDE extension, plan around the CLI surface for the enforcement levels above.
  • Enforcement lives on the agent surface, not around it. Blocking hooks bind the three official CLI surfaces. They do not constrain a developer who uninstalls the tooling or works outside it β€” pair them with your normal repo-level controls (branch protections, CI, review).
  • Sync PRs touch only agent-config files, so they're safe to auto-merge β€” under your own branch protections. AgentBoot never asks you to weaken them.

If a cell says advisory, treat it as advisory.

Tested, not just documented: agentboot conformance executes the compiled hook scripts per platform and writes dist/<platform>/enforcement-manifest.json recording declared level vs observed behavior. The classification in this matrix is the same single source of truth the harness tests and doctor reports.

Capability Γ— platform β€” which platforms EMIT a capability at all​

The table above is about enforcement strength. This one is about a prior and different question: does the platform receive a mechanism for the capability at all? A capability nobody emits is not weakly enforced β€” it is absent.

The source of truth is CAPABILITY_SUPPORT in scripts/lib/conformance.ts. Every row was verified by building a hub with the capability configured and inspecting dist/, and each carries a warrant (file:line of the emitter) so a reviewer can check the row against the code. The build fails when a configured capability's platform set does not intersect personas.outputFormats.

Capabilityclaudecodexcopilotplugincursorgeminiwindsurfjetbrainsagentsskill
claude.hooks (org-authored)βœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
claude.permissions (allow + deny)βœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
claude.mcpServersβœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
claude.settings pass-throughβœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
mcp.enforceApproved filteringβœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
ab.modelOverridesβœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
managed.guardrails.disableBypassPermissionsβœ…β€“β€“β€“β€“β€“β€“β€“β€“β€“
compliance.inputScan.scannerCommandβœ…βœ…βœ…βœ…β€“β€“β€“β€“β€“β€“
compliance.outputScan.blockingβœ…βœ…βœ…βœ…β€“β€“β€“β€“β€“β€“
managed.guardrails.denyToolsβœ…βœ…βœ…βœ…β€“β€“β€“β€“β€“β€“
managed.guardrails.requireAuditLogβœ…βœ…βœ…βœ…β€“β€“β€“β€“β€“β€“
managed.guardrails.forcePlugins––––––––––
instructions[].applyTo (narrowing)βš βš βœ…βš βœ…βš βœ…βœ…βš βš 
gotchas[].pathsβ€“β€“βœ…β€“βœ…β€“βœ…βœ…β€“β€“

managed.guardrails.forcePlugins has an empty row on purpose. It is typed, documented, accepted β€” and read by no code path on any platform. Setting it fails the build, because that is the only honest thing a governance product can do with a knob wired to nothing.

plugin carries the generated compliance hooks, not claude.hooks. Both were verified by building and grepping dist/; the distinction matters and is easy to assume wrongly.

Instruction path scoping (applyTo) β€” native, translated, or unsupported​

applyTo is a third axis: not "how strongly is it enforced" and not "is it emitted at all", but "did the target receive the scope the operator actually wrote".

PlatformSupportMechanism
copilotnativeapplyTo: is a first-class Copilot instruction key
cursortranslatedglobs: + alwaysApply: false in the .mdc frontmatter
windsurftranslatedtrigger: glob + globs: in .windsurf/rules/
jetbrainstranslatedglobs: in .aiassistant/rules/
claudeunsupportedrules/ files are @-imported unconditionally from CLAUDE.md
skillunsupportedSKILL.md instruction files have no scoping key
pluginunsupportedplugin rules/ load with the plugin, unscoped
agents Β· codexunsupportedtext is inlined into AGENTS.md, which is always-on
geminiunsupportedtext is inlined into GEMINI.md, which is always-on

On the unsupported tier a narrow rule is necessarily delivered always-on β€” which is the opposite of what the operator wrote, not merely a weaker version of it. That inversion fails the build unless the artifact carries scope-unsupported: acknowledged, and an acknowledged artifact ships with a Scope: preamble in its body so the agent is told which paths the rule is for. A universal applyTo: "**" is always-on by definition and never triggers anything.

The translated tier produces no diagnostic at all: nothing was lost, so there is nothing to say.