Harness coverage
A harness is an AI client that loads and runs Agent Skills — Claude Code, Codex, Cursor, and many more. skillsvault draws two capabilities and is careful never to conflate them:
- Distribution governance — install the org's approved skills, and remove banned ones and any a Block policy covers. Works for every agent that discovers
SKILL.mdfolders on disk — 17 today, plus the shared.agents/skillslocation. - Runtime veto — a hook that blocks a banned skill at the moment of invocation. Requires the harness to expose a hook that can refuse a tool call. Claude Code today.
Honest by design
We lead with the harnesses that can enforce and never claim universality. A harness without a vetoing hook still gets full distribution governance — approved skills installed, banned skills removed — it just can't block at the instant of invocation.
Coverage matrix
| Harness | pull installs skills into | Subagents / commands | Distribution | Runtime veto |
|---|---|---|---|---|
| Claude Code | ~/.claude/skills | ~/.claude/agents, ~/.claude/commands | ✓ | ✓ |
| Codex | ~/.agents/skills | — | ✓ | — |
| Pi | ~/.pi/agent/skills | — | ✓ | — |
| Amp | ~/.config/amp/skills | — | ✓ | — |
| Gemini CLI | ~/.gemini/skills | ~/.gemini/agents | ✓ | — |
| Antigravity | ~/.gemini/config/skills | ~/.gemini/config/agents | ✓ | — |
| OpenClaw | ~/.openclaw/skills | — | ✓ | — |
| Hermes | ~/.hermes/skills | — | ✓ | — |
| OpenCode | ~/.config/opencode/skills | ~/.config/opencode/agents, …/commands | ✓ | — |
| Cursor | ~/.cursor/skills | ~/.cursor/agents, ~/.cursor/commands | ✓ | — |
| Windsurf (Devin Desktop) | ~/.codeium/windsurf/skills | — | ✓ | — |
| Cline | ~/.cline/skills | — | ✓ | — |
| Roo Code | ~/.roo/skills | ~/.roo/commands | ✓ | — |
| Continue | ~/.continue/skills | — | ✓ | — |
| GitHub Copilot | ~/.copilot/skills | ~/.copilot/agents | ✓ | — |
| Zed | ~/.agents/skills | — | ✓ | — |
| Augment | ~/.augment/skills | ~/.augment/agents, ~/.augment/commands | ✓ | — |
Shared .agents/skills | ~/.agents/skills | — | ✓ | — |
| Aider | — (no Agent Skills support) | — | — | — |
Only where the agent actually looks
Every row is the directory the vendor's own docs say the agent discovers SKILL.md folders in. A subagent or command is installed only where the agent reads that kind as markdown — elsewhere pull skips it and says so. Rule and instruction files (.cursor/rules, .clinerules, .github/instructions, …) are always-on context, not on-demand skills, so pull never writes them; skillsvault scan still inventories them.
Aider
Aider has no skill discovery: it only loads files you pass with --read or list under read: in .aider.conf.yml, and always in context. skillsvault detect shows it, and pull --all skips it rather than writing files it would never open.
Upgrading from an older CLI
Earlier CLI versions wrote some harnesses' skills to directories they don't read (for example ~/.github/skills for Copilot or ~/.windsurf/skills for Windsurf). pull now removes those copies, but only folders and files it can prove it wrote: a folder carrying its marker, or one whose SKILL.md matches the org's skill. Anything else in those directories is left alone.
Detecting and installing
skillsvault detect lists the harnesses found on a machine. Claude Code is labelled from the gate hook actually installed — enforced (hook), partially enforced (hook misses …) or not enforced (no gate hook), the same coverage sync reports under Hook coverage — and every other harness is distribution only. With Claude Code installed and no gate hook, detect also prints the fix.
skillsvault detect
# skillsvault detect — AI agents found on this machine
#
# • claude_code /Users/me/.claude/skills enforced (hook)
# • cursor /Users/me/.cursor/skills distribution only
skillsvault pull --all then installs the approved skills into every detected harness and removes any that are banned or covered by a Block policy — in harnesses without a runtime gate, that removal is the enforcement. Target a single harness with --harness, or a directory with --dir. See the command reference.
Claude Code hook
Runtime veto on Claude Code uses its PreToolUse and UserPromptExpansion hooks. skillsvault install-hook prints the snippet to add to your Claude Code settings — ~/.claude/settings.json to gate every project, or a project's .claude/settings.json (the printed command is the absolute path of your skillsvault binary):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Skill|Agent|Task",
"hooks": [
{ "type": "command", "command": "skillsvault gate" }
]
}
],
"UserPromptExpansion": [
{
"hooks": [
{ "type": "command", "command": "skillsvault gate" }
]
}
]
}
}
PreToolUse covers what the agent invokes: skills through the Skill tool, and subagents through the Agent tool (named Task before Claude Code 2.1.63). UserPromptExpansion covers a person typing /name, which never reaches PreToolUse. Claude Code pipes each payload to skillsvault gate, which evaluates it locally and, on a block, vetoes the invocation and surfaces your policy's reason. The machine needs a synced bundle — login syncs one for you. The full protocol is on The runtime gate.
What each path can do:
| Invocation | Hook | On a ban / Block policy |
|---|---|---|
| A skill the agent invokes | PreToolUse, tool Skill | denied, reason shown to the agent |
| A subagent the agent launches | PreToolUse, tool Agent / Task | denied |
A /command a person types | UserPromptExpansion | a skill of that name is blocked; a command is only warned — commands are capped at warn |
Claude Code invokes installed skills by their bare name (deploy, not acme/deploy); the gate maps every form back to your registry — see How an invoked name is resolved.
Hook coverage
On every sync, pull, try and login, the CLI (0.5.2 and later) reports which of these paths a hook running skillsvault gate covers. It reads .claude/settings.json and .claude/settings.local.json in the directory you run it from, and ~/.claude/settings.json — so put the hook in ~/.claude/settings.json, or run sync from the project that holds it. The Gating column on the console's Harnesses page shows the result:
| State | Meaning |
|---|---|
| Gating: full | skills, subagents (Agent and Task) and typed commands are all gated |
| Gating: partial | the hook runs the gate but misses a path — typically a hook from before CLI 0.5.1 (matcher "Skill", no UserPromptExpansion), so subagents and typed commands go through unchecked |
| Not gating | the machine reports in, but no hook runs the gate |
| registered | a hook runs the gate; the CLI is older than 0.5.2 and doesn't say which paths |
| unknown | the CLI is too old to report its hooks at all |
To fix a partial machine, run skillsvault install-hook, paste the block over the old skillsvault entry in the settings file that holds it, and run skillsvault sync. Until then sync and detect print a one-line hint on the machine. A machine on a CLI below the minimum supported version (0.5.1) also shows CLI outdated — upgrade; see Upgrading an existing machine. The report is self-attested, so it catches a stale config, not a determined user.
Other harnesses
Codex, Pi, and the rest have no vetoing hook, so they cannot block at invocation time. They still receive full distribution governance. Don't represent them as runtime-enforced — that would be untruthful.