Skarn guard: agent plugins
Hook configuration, agent skills, and a local MCP server declaration for Skarn, packaged for four hosts, with a fifth host served from its own repository. This repository is generated at every Skarn release. It contains no binary, no detection rules, and no engine code.
Five units live here, four of them guard units. claude/ and codex/ are plugins in the marketplace this repository's root manifest serves, for Claude Code and Codex CLI. antigravity/ is a plugin directory for the Antigravity CLI (agy). The repository root is itself a Gemini CLI extension, because Google's installer and gallery crawler read the manifest from the root. A file at the root is either a repository-level file (this README, LICENSE, SECURITY.md, the marketplace manifest) or a Gemini file (gemini-extension.json, GEMINI.md, hooks/, skills/); every other host gets a subdirectory. The fifth unit, recall/, is a skill-only plugin in the same marketplace: one skill, no hooks, no MCP server. The Cursor unit is not in this repository at all; it lives at https://github.com/skarn-security/cursor-plugin.
The guard is a pre-execution hook. Before your agent runs a shell command, applies a patch, writes a file, fetches a URL, calls an MCP tool, or sends a prompt to the model provider, the pending action is scanned by the Skarn detection engine on your machine and gets a verdict: deny (block), ask (escalate to you), or allow (silent). It scans locally, makes no network call, and never prints a raw secret - a verdict names the rule and a redacted preview.
Install
Install the skarn binary first (the plugin does not carry it; the hooks call skarn guard on your PATH):
brew install skarn-security/tap/skarn
Claude Code:
claude plugin marketplace add skarn-security/agent-guard
claude plugin install skarn-guard@skarn
Codex CLI:
codex plugin marketplace add skarn-security/agent-guard
codex plugin add skarn-guard-codex@skarn
The two guard plugins carry different names because one marketplace cannot hold two plugins under the same name, and each ships its host's hook shape (event names, tool matchers, and the --agent the guard routes on). Install the one for the host you are wiring. Both carry the skarn-audit skill, which runs skarn assess and skarn vet over this machine and reports redacted findings. Redaction masks the credential values Skarn detects; the surrounding transcript context in a finding is still session-derived, so the skill treats a whole result as session data rather than as safe text.
Codex asks you to trust the hooks the first time you start it after installing: choose "Trust all and continue" at the "Hooks need review" prompt. Until you do, the hooks do not run and the guard is not protecting you. Trust is a content hash per hook, so any later change to a hook (a version bump, or the audit-to-enforce flip) asks again. Claude Code needs no trust step; the hooks are live in your next session.
skarn-recall is a third plugin in the same marketplace, and the marketplace add above already reaches it. It carries one skill, no hooks, and nothing host-specific, so the same plugin serves both hosts:
claude plugin install skarn-recall@skarn
codex plugin add skarn-recall@skarn
That skill reconstructs what you worked on from your session transcripts, which is why it ships apart from the guard rather than inside it. Transcript content it reads leaves your machine for the model provider serving the agent; redaction masks the credentials Skarn detects, not everything you would call sensitive. Install it when you want that, and scope what it reads by project and by time window.
Gemini CLI installs this repository as an extension, which carries the same guard hooks in audit mode, the skarn-audit skill, a GEMINI.md context file, and the MCP server below:
gemini extensions install https://github.com/skarn-security/agent-guard
gemini extensions list
gemini extensions uninstall skarn
Install asks for consent, because the extension declares both hooks and an MCP server, and it asks you to trust the folder. Answer both.
Antigravity CLI installs the antigravity/ directory of a clone:
git clone https://github.com/skarn-security/agent-guard
agy plugin install agent-guard/antigravity
agy plugin list
agy plugin uninstall skarn-guard
agy plugin list reports the plugin with its hook, skill, and MCP server counts. Copying antigravity/ to ~/.gemini/config/plugins/skarn-guard/ by hand does the same thing.
Cursor has its own repository, https://github.com/skarn-security/cursor-plugin, generated by the same release. Cursor's marketplace and its review are per repository, which is why that unit does not live here.
skarn setup is the alternative install path for Claude Code, Codex CLI, Cursor, Copilot CLI, Gemini CLI and Grok Build: it merges the same hooks into each of those hosts' native config without the plugin system. It does not know the Antigravity CLI, so that host installs the plugin directory above or merges its hook file by hand.
Local MCP server
Each of the four guard units (claude/, codex/, antigravity/, and the Gemini extension at the root) declares the same stdio MCP server, which the host starts by running skarn mcp from your PATH. Cursor and VS Code take it in one click:
Both buttons register the server as skarn and run skarn mcp from your PATH, so install the binary first. If you would rather not install it, the pinned launcher form works with only Node present: Cursor or VS Code - it downloads @skarn-security/[email protected] on first run and reuses the npx cache afterwards; a newer Skarn needs a newer link.
Manual configuration for any client:
{
"mcpServers": {
"skarn": {
"command": "skarn",
"args": ["mcp"]
}
}
}
It runs on your machine, makes no network call, and exposes four read-only tools: scan_sessions (findings from past sessions, every previewed value redacted), vet_configs (a masked report on your assistant configuration surface), list_sessions and session_stats (metadata and aggregates, never message content). There is no write tool and no tool that returns message content.
Two content tools, search_sessions and get_session, appear only if you start the server as skarn mcp --enable-recall. Both mask what they return, and the content still leaves your machine for the model provider serving the session, so the declarations above do not set the flag. search_sessions refuses a call that names neither hours nor project; get_session takes one exact session_id, which is already its scope.
If you would rather not install the binary yourself, a version-pinned npx form works:
{
"mcpServers": {
"skarn": {
"command": "npx",
"args": ["-y", "@skarn-security/[email protected]", "mcp"]
}
}
}
npx downloads the package the first time the server starts and caches it afterward, so the first start is slower and needs network access. Pin the version. The unpinned form resolves to whatever the registry serves at start time, and skarn vet reports it as vet-mcp-unpinned. Do not use it.
llms-install.md at this repository's root is the same install in agent-readable steps, for a client that wires the server up for you.
Each host reports a missing binary its own way. claude mcp list says Failed to connect with Executable not found in $PATH: "skarn". gemini mcp list shows the skarn server as Disconnected. codex mcp list runs no health check, so the row stays listed and enabled and the server fails when a session starts it. Cursor shows the plugin's row as Error - Show Output, and the output panel ends with spawn skarn ENOENT. In every case, run skarn --version in a terminal: command not found means the binary is not installed or is not on the PATH that host inherits, which is the usual answer for an application launched from a desktop rather than a shell.
Audit first, then enforce
Both guard plugins ship in audit mode (skarn-recall has no hooks, so it has no mode): the guard reports the verdict it would have returned and never changes what your agent does. Run it that way first and measure your real would-block rate. Set SKARN_GUARD_LOG=<path> in the environment your agent inherits and the guard appends one redacted JSONL record per flagged call (ts, verdict, tool, rule, severity, redacted reason, session, cwd, latency_ms); clean calls are not logged.
When the log looks clean, flip the --guard-mode audit in the hook command to --guard-mode enforce, or run skarn setup --update --mode enforce. Enforcement requires a Skarn license; without one the guard stays in audit and reports rather than blocks, so a lapsed license never breaks your editor.
Keeping a hook current as Skarn releases widen a host's event set is the plugin update below, not a Skarn command: these plugins carry their own hook files, and skarn setup --update refreshes only the Skarn-owned entries that skarn setup itself wrote, at whichever scope it wrote them (per-user by default, or the repo config under --scope project). For a config wired that other way, --update rewrites those entries to whatever the installed binary writes, replacing each one whole except for a hook-call timeout you tuned yourself (timeout, or timeoutSec on Copilot), which is carried across when it pairs unambiguously with its replacement and the value is sane, so a per-machine budget survives the refresh; any other field you added to such an entry is dropped. Run at a terminal, skarn guard report and skarn assess name a setup-wired per-user hook that has fallen behind, once per release, with the exact update command for that host.
Updating
Claude Code:
claude plugin marketplace update skarn
claude plugin update skarn-guard@skarn
Codex CLI (it has no update verb; re-adding installs the new version):
codex plugin marketplace upgrade
codex plugin add skarn-guard-codex@skarn
Plugin updates and binary updates are independent: the hook commands invoke skarn guard on PATH, so brew upgrade skarn alone gives you the newer detection engine. A plugin update matters when anything the plugin itself carries changes: the hook shape (a new event, a new flag, a new matcher), a skill's text, or the manifest metadata.
Safety
The guard only ever tightens a decision, never loosens one. What happens when the guard itself fails depends on the host, because each host decides what a hook crash, timeout, or malformed output means.
Claude Code, Codex CLI, and Gemini CLI fail open: a malformed event, an out-of-scope tool, or any guard error yields allow, and the guard never bricks your agent. The only fail-closed path on those hosts is --strict with a licensed enforce, which each host README documents.
The Antigravity CLI fails closed on every hook outcome except an explicit allow: a crash, a timeout, invalid JSON, and an empty {} all block the matched call, in audit mode as well as enforce, and a wired hook with no skarn binary on PATH blocks every matched call. The guard answers every event it receives with an explicit decision, and the shipped matcher names only the tools it scopes so that a step outside the matcher can never be blocked by a guard failure. Install skarn before wiring that hook, and remove the entry before uninstalling skarn. Documentation: https://getskarn.com/?utm_source=agent-guard-readme&utm_medium=referral&utm_campaign=home&utm_content=documentation
License, privacy, and support
This repository is MIT licensed; see LICENSE. It carries configuration only, so that covers the plugin manifests, the hooks, the skills, and the MCP server declarations in it.
The skarn binary those files invoke is a separate download and is not open source. It is licensed under the Skarn End User License Agreement at https://getskarn.com/terms/, and running it accepts that agreement. What it reads, what it keeps, and what it never sends anywhere: https://getskarn.com/privacy/.
Support: [email protected]. Vulnerability reports go to [email protected]; see SECURITY.md in this repository.