SCHEMAS
Pinned known-good config shapes the 8 writers target, with the official source + retrieval date. The MEDIUM/LOW (volatile) surfaces carry a **live-verification gate**: their checkbox stays ☐ until a maintainer installs the entry against a real running agent and confirms it
$ npx -y skills add OpenLatch/saferskills --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Pinned known-good config shapes the 8 writers target, with the official source + retrieval date. The MEDIUM/LOW (volatile) surfaces carry a **live-verification gate**: their checkbox stays ☐ until a maintainer installs the entry against a real running agent and confirms it
Agent definition
SCHEMAS.mdAgent config schemas + live-verification checklist
Pinned known-good config shapes the 8 writers target, with the official source + retrieval date. The MEDIUM/LOW (volatile) surfaces carry a **live-verification gate**: their checkbox stays ☐ until a maintainer installs the entry against a real running agent and confirms it loads, then ticks it here. A surface that cannot be verified ships **detect-only with a copy-paste fallback** for that one surface — never a per-agent descope (the full-8 wedge is non-negotiable).
> This CLI installs **every capability kind** the platform catalogs across every > compatible agent (the original two-shape scope was widened): the five > install shapes are `mcp_server` (format-preserving map-merge), `skill` (folder > copy), `rules` (single-file copy), `hook` (per-event `settings.json` merge), and > `plugin` (native bundle install). The per-capability config the CLI needs comes > from the backend `install_spec` field (`app/scan/discovery.py::build_install_spec`) > on the report — not CLI-side zip re-parsing. The backend `agent_compatibility` is > the outer filter, so a writer never sees a kind its agent can't take; the on-disk > surface check is `writer::kind_supported`.
MCP map-merge — per-agent key + URL landmines
| Agent | Conf. | Config file (global / project) | MCP key | URL field | Source (2026-06-04) | |---|---|---|---|---|---| | claude-code | HIGH | `~/.claude.json` / `.mcp.json` | `mcpServers` | `url` | code.claude.com/docs/en/mcp | | cursor | HIGH | `~/.cursor/mcp.json` / `.cursor/mcp.json` | `mcpServers` | `url` | cursor.com/docs/mcp | | windsurf | HIGH (MCP) | `~/.codeium/windsurf/mcp_config.json` (global only) | `mcpServers` | **`serverUrl`** | docs.windsurf.com/windsurf/cascade/mcp | | copilot (CLI) | HIGH | `~/.copilot/mcp-config.json` | `mcpServers` | `url` | docs.github.com copilot-cli | | copilot (VS Code) | HIGH | `.vscode/mcp.json` (project) | **`servers`** | `url` | code.visualstudio.com/docs/agent-customization/mcp-servers | | codex | HIGH | `~/.codex/config.toml` / `.codex/config.toml` | TOML `[mcp_servers.<n>]` | `url`+`bearer_token_env_var` | developers.openai.com/codex/mcp | | gemini | HIGH (MCP) | `~/.gemini/settings.json` / `.gemini/settings.json` | `mcpServers` | `url` / `httpUrl` | github.com/google-gemini/gemini-cli docs/tools/mcp-server.md | | cline | HIGH (MCP) | VS Code globalStorage `…/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` (variant-resolved) / `~/.cline/mcp.json` | `mcpServers` | `url` | docs.cline.bot/mcp/configuring-mcp-servers | | openclaw | **MED** | `~/.openclaw/openclaw.json` / `.mcp.json` | **`mcpServers` ∨ `mcp.servers` (probed)** | `url` | docs.openclaw.ai/cli/mcp (key-shape unverified) |
Notes:
- **claude-code local-scope nesting** (`projects."<abs>".mcpServers`) is NOT used —
both our scopes write the top-level `mcpServers` (global → `~/.claude.json`, project → `.mcp.json`). This avoids a dotted-key that contains the abs path.
- **Idempotency hazards** (re-verify after write — `doctor`/`verify()` re-reads):
Codex Desktop has rewritten/dropped MCP entries on a Windows restart; OpenClaw + Windsurf need a gateway/editor restart to apply ("write succeeded" ≠ "active").
Skill folder copy
| Agent | Skills dir | Notes | |---|---|---| | claude-code | `~/.claude/skills/<name>/` · `.claude/skills/<name>/` | HIGH | | openclaw | `~/.openclaw/skills/<name>/` | MED (dir path unverified) | | codex / copilot / gemini | `~/.codex/skills/` · `~/.copilot/skills/` · `~/.gemini/skills/` | dirs known, but the backend `agent_compatibility` keeps skills off these agents, so the CLI never offers a skill install there |
Frontmatter `name` must equal the folder name (Copilot/VS Code enforces it); the writer copies the SaferSkills snapshot `.zip` into `<skills>/<name>/`.
Rules file copy
| Agent | Rules dir (global / project) | File extension | Backend compat | |---|---|---|---| | cursor | `~/.cursor/rules` / `.cursor/rules` | `.mdc` | ✓ | | windsurf | `.windsurf/rules` (workspace) | `.md` | ✓ | | cline | `~/Documents/Cline/Rules` / `.clinerules` | `.md` | ✓ | | copilot | `.github/instructions` (repo-level) | `.instructions.md` | ✓ |
`install_rules_file` copies the source rules body (read from the snapshot `.zip` at `install_spec.rules_files[0].path`) to `<rules_dir>/<name><ext>` → an [`InstallChange::File`]. Verify = the file exists; uninstall = remove it.
Hook settings.json merge
| Agent | Settings file (global / project) | Block | Backend compat | |---|---|---|---| | claude-code | `~/.claude/settings.json` / `.claude/settings.json` | top-level `hooks` | ✓ | | openclaw | `~/.openclaw/openclaw.json` (probe-and-adapt) | top-level `hooks` | ✓ (hook only) |
`merge_json_hook` merges the source `hooks` block (the `hooks` value of the capability's anchor file in the snapshot, or the file itself when its top-level keys ARE the events) into the settings `hooks` block, recording one `ConfigKey` `hooks.<event>` per event so uninstall byte-restores via `restore_json_key` (a new event is removed exactly; an existing event is restored to its prior array). Claude hooks live in `settings.json`, **not** the MCP config path — hence the distinct `hooks_path` on `DetectedAgent`.
Plugin native bundle install
| Agent | Plugins root | Layout | Backend compat | |---|---|---|---| | claude-code | `~/.claude/plugins` | `cache/<mp>/<plugin>/<ver>/` + `installed_plugins.json` | ✓ | | openclaw | — | layout not yet live-verified → gated OFF | ✓ (deferred) |
`install_plugin` extracts the bundle `.zip` (prefix-stripped to `component_path`) into `<plugins>/cache/<mp>/<plugin>/<ver>/` — the exact layout the local-audit enumerator (`enumerate.rs::discover_plugins`) reads — and merges a `plugins["<plugin>@<mp>"].installs[] = {scope:"user", version}` ledger entry into `installed_plugins.json`. `<plugin>`/`<ver>` come from `install_spec.plugin_ref` (`<ver>` falls back to `ref_sha[..7]`); `<mp>` is a stable id derived
Read more
Agent config schemas + live-verification checklist
Pinned known-good config shapes the 8 writers target, with the official source + retrieval date. The MEDIUM/LOW (volatile) surfaces carry a **live-verification gate**: their checkbox stays ☐ until a maintainer installs the entry against a real running agent and confirms it loads, then ticks it here. A surface that cannot be verified ships **detect-only with a copy-paste fallback** for that one surface — never a per-agent descope (the full-8 wedge is non-negotiable).
> This CLI installs **every capability kind** the platform catalogs across every > compatible agent (the original two-shape scope was widened): the five > install shapes are `mcp_server` (format-preserving map-merge), `skill` (folder > copy), `rules` (single-file copy), `hook` (per-event `settings.json` merge), and > `plugin` (native bundle install). The per-capability config the CLI needs comes > from the backend `install_spec` field (`app/scan/discovery.py::build_install_spec`) > on the report — not CLI-side zip re-parsing. The backend `agent_compatibility` is > the outer filter, so a writer never sees a kind its agent can't take; the on-disk > surface check is `writer::kind_supported`.
MCP map-merge — per-agent key + URL landmines
| Agent | Conf. | Config file (global / project) | MCP key | URL field | Source (2026-06-04) | |---|---|---|---|---|---| | claude-code | HIGH | `~/.claude.json` / `.mcp.json` | `mcpServers` | `url` | code.claude.com/docs/en/mcp | | cursor | HIGH | `~/.cursor/mcp.json` / `.cursor/mcp.json` | `mcpServers` | `url` | cursor.com/docs/mcp | | windsurf | HIGH (MCP) | `~/.codeium/windsurf/mcp_config.json` (global only) | `mcpServers` | **`serverUrl`** | docs.windsurf.com/windsurf/cascade/mcp | | copilot (CLI) | HIGH | `~/.copilot/mcp-config.json` | `mcpServers` | `url` | docs.github.com copilot-cli | | copilot (VS Code) | HIGH | `.vscode/mcp.json` (project) | **`servers`** | `url` | code.visualstudio.com/docs/agent-customization/mcp-servers | | codex | HIGH | `~/.codex/config.toml` / `.codex/config.toml` | TOML `[mcp_servers.<n>]` | `url`+`bearer_token_env_var` | developers.openai.com/codex/mcp | | gemini | HIGH (MCP) | `~/.gemini/settings.json` / `.gemini/settings.json` | `mcpServers` | `url` / `httpUrl` | github.com/google-gemini/gemini-cli docs/tools/mcp-server.md | | cline | HIGH (MCP) | VS Code globalStorage `…/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` (variant-resolved) / `~/.cline/mcp.json` | `mcpServers` | `url` | docs.cline.bot/mcp/configuring-mcp-servers | | openclaw | **MED** | `~/.openclaw/openclaw.json` / `.mcp.json` | **`mcpServers` ∨ `mcp.servers` (probed)** | `url` | docs.openclaw.ai/cli/mcp (key-shape unverified) |
Notes:
- **claude-code local-scope nesting** (`projects."<abs>".mcpServers`) is NOT used —
both our scopes write the top-level `mcpServers` (global → `~/.claude.json`, project → `.mcp.json`). This avoids a dotted-key that contains the abs path.
- **Idempotency hazards** (re-verify after write — `doctor`/`verify()` re-reads):
Codex Desktop has rewritten/dropped MCP entries on a Windows restart; OpenClaw + Windsurf need a gateway/editor restart to apply ("write succeeded" ≠ "active").
Skill folder copy
| Agent | Skills dir | Notes | |---|---|---| | claude-code | `~/.claude/skills/<name>/` · `.claude/skills/<name>/` | HIGH | | openclaw | `~/.openclaw/skills/<name>/` | MED (dir path unverified) | | codex / copilot / gemini | `~/.codex/skills/` · `~/.copilot/skills/` · `~/.gemini/skills/` | dirs known, but the backend `agent_compatibility` keeps skills off these agents, so the CLI never offers a skill install there |
Frontmatter `name` must equal the folder name (Copilot/VS Code enforces it); the writer copies the SaferSkills snapshot `.zip` into `<skills>/<name>/`.
Rules file copy
| Agent | Rules dir (global / project) | File extension | Backend compat | |---|---|---|---| | cursor | `~/.cursor/rules` / `.cursor/rules` | `.mdc` | ✓ | | windsurf | `.windsurf/rules` (workspace) | `.md` | ✓ | | cline | `~/Documents/Cline/Rules` / `.clinerules` | `.md` | ✓ | | copilot | `.github/instructions` (repo-level) | `.instructions.md` | ✓ |
`install_rules_file` copies the source rules body (read from the snapshot `.zip` at `install_spec.rules_files[0].path`) to `<rules_dir>/<name><ext>` → an [`InstallChange::File`]. Verify = the file exists; uninstall = remove it.
Hook settings.json merge
| Agent | Settings file (global / project) | Block | Backend compat | |---|---|---|---| | claude-code | `~/.claude/settings.json` / `.claude/settings.json` | top-level `hooks` | ✓ | | openclaw | `~/.openclaw/openclaw.json` (probe-and-adapt) | top-level `hooks` | ✓ (hook only) |
`merge_json_hook` merges the source `hooks` block (the `hooks` value of the capability's anchor file in the snapshot, or the file itself when its top-level keys ARE the events) into the settings `hooks` block, recording one `ConfigKey` `hooks.<event>` per event so uninstall byte-restores via `restore_json_key` (a new event is removed exactly; an existing event is restored to its prior array). Claude hooks live in `settings.json`, **not** the MCP config path — hence the distinct `hooks_path` on `DetectedAgent`.
Plugin native bundle install
| Agent | Plugins root | Layout | Backend compat | |---|---|---|---| | claude-code | `~/.claude/plugins` | `cache/<mp>/<plugin>/<ver>/` + `installed_plugins.json` | ✓ | | openclaw | — | layout not yet live-verified → gated OFF | ✓ (deferred) |
`install_plugin` extracts the bundle `.zip` (prefix-stripped to `component_path`) into `<plugins>/cache/<mp>/<plugin>/<ver>/` — the exact layout the local-audit enumerator (`enumerate.rs::discover_plugins`) reads — and merges a `plugins["<plugin>@<mp>"].installs[] = {scope:"user", version}` ledger entry into `installed_plugins.json`. `<plugin>`/`<ver>` come from `install_spec.plugin_ref` (`<ver>` falls back to `ref_sha[..7]`); `<mp>` is a stable id derived
Every AI skill, independently scanned. Public, open-source trust scoring for skills, MCP servers, hooks, and plugins across every agent platform. Apache-2.0. saferskills.ai
Repo: OpenLatch/saferskills

