What hooks do
Guard adds its own entries to each harness's hook configuration. The harness then asks Guard about prompts, tool calls and tool output. We monitor agents, not developers.
- Tool calls. Reads of credential files and directories, credential commands (such as
security find-generic-password) and MCP tool arguments that name credential paths are denied. - Risky actions. Persistence writes, guardrail lowering, destructive commands, droppers, risky package installs, encoded secrets and credential writes are blocked, confirmed with the user or reported. See risky actions.
- Tool output. Critical and high secrets in output are replaced or reported, where the harness allows it.
- Prompts. Checked only when your organization turns on human-to-AI sharing detection (
privacy.human_ai_sharing) in its signed catalog. Without it, a prompt goes through unchanged and Guard records only that a prompt was submitted. See the privacy statement. - MCP tool access. When the signed catalog has tool access rules, MCP calls are checked against them. See MCP tools.
- Sessions. Calls are linked into agent sessions, so chains such as untrusted input, then a credential read, then an upload can be caught. Output from one MCP server followed by a sending, writing or deleting call on another is recorded too (
cross_server_mcp_flow, indetectmode by default). A call without a session ID gets no session rules.
Messages name secret types and rules, never secret values. Hooks also deny any tool call that reads or writes the Guard home, so an agent can't grant itself an exception.
Warning: Hooks are voluntary checks, not endpoint-wide enforcement. A user can edit or remove them, and in several harnesses a hook that fails or times out lets the action proceed. Guard's endpoint sensor reports the file opens and process launches that hooks miss, including agent CLIs started with a bypass flag or a variable that moves their configuration directory, only after the fact, and the native macOS sensor can't yet run on customer Macs (see Install).
Install
guard hooks install all
guard hooks status
allselects known harness configuration locations and supported official extension manifests. Incomplete discovery can skip automatic setup. Name a supported harness to choose explicitly:guard hooks install claude_code cursor.- Entries run the
guardbinary you raninstallwith, by absolute path. Use--binary PATHfor another one. - Catalog flags given before
hooksare added to every entry:guard --catalog PATH --catalog-key KEYS hooks install all. - Your other hooks are kept. The first time Guard changes a file, it saves the original with a
.before-runeward-guardsuffix. - Codex asks you to trust new hooks: run
/hooksin Codex after installing. guard hooks uninstall allremoves Guard's entries only.
status reports each harness as one of:
| State | Meaning |
|---|---|
installed |
All of Guard's entries are present. |
partial |
Some events have no Guard entry. |
broken |
An entry starts a binary that is missing or not executable. |
not_installed |
No Guard entries. |
invalid |
The file or vendor hook schema is invalid, or a native runtime home disagrees with the configured path. |
guard doctor and the Guard Cloud health report show the same states, without paths.
Repair
Harness updates and settings editors sometimes drop Guard's entries. Repair puts them back:
guard hooks repair all
Repair only touches harnesses in the partial or broken state. A harness with no Guard entries is left alone, because removing them all is how you turn Guard off for it. The last 20 repairs show in guard doctor as hook_repairs.
Scheduled repair is opt-in:
- macOS:
guard setup-launch-agent --binary /path/to/guard --repair-hookswrites thecom.runeward.guard.hooks-repairlaunch agent. It runs at login and hourly;--repair-interval SECONDSsets 300 to 86400. Load it withlaunchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.runeward.guard.hooks-repair.plist. - Linux: the packages ship a user timer, off by default. Each user enables it with
systemctl --user enable --now runeward-guard-hooks-repair.timer. - Windows:
install.ps1 -RepairHooksor the MSI'sREPAIRHOOKS=1registers a scheduled task that runsguard.exe hooks repair allas each user, two minutes after logon and then hourly. Administrators can also runguard hooks repair-task register,removeorstatus. It restores entries a user removed on purpose (to opt a harness out, remove the task) and can overwrite an edit saved while it runs. Windows hook install and repair aren't yet qualified.
A signed catalog can also repair JSON hooks automatically with a hooks_repair remediation playbook. Kimi TOML needs explicit repair; it is excluded from JSON-snapshot remediation.
Exceptions
Exceptions let named paths, MCP servers or commands through specific checks, such as test fixtures with fake keys. They come from:
hook_exceptionsin the signed catalog, which Guard Cloud can send to every enrolled device;policy.jsonin the Guard home (~/.runeward-guardby default), for one user. A catalog can turn these off with"local_hook_exceptions": false.
{
"version": 1,
"exceptions": [
{
"paths": ["~/src/payments/tests/fixtures/"],
"secrets": ["stripe_key", "jwt"],
"reason": "Fake keys used by the payments test suite"
},
{
"mcp_servers": ["sentry"],
"commands": [["npm", "test"], ["cargo", "test"]],
"secrets": ["github_token"],
"reason": "Test suites and error reports print fake tokens",
"expires": "2026-12-31T00:00:00Z"
}
]
}
| Field | Rules |
|---|---|
paths |
Catalog path patterns. Each must name at least two literal directories or files before any **, so ~/src/** is refused. |
mcp_servers |
Exact server names as configured. No wildcards. |
commands |
Argument-list prefixes. ["npm", "test"] covers npm test -- --watch=false but not npm run test. Pipes, lists and redirections never match. Broad prefixes such as ["bash"] are refused. |
secrets |
Catalog secret rules, or "*". |
actions |
Risky action rules, such as rules_file or git_reset_hard. Guardrail lowering, droppers and blocklisted packages can't be exempted. |
credentials |
Credential file kinds, such as dot_env, that may be read at paths. Reading whole credential directories and running credential commands can't be exempted. |
reason |
Required. |
expires |
Optional. Expired exceptions stop applying. |
Each exception needs at least one of paths, mcp_servers and commands. Exceptions never apply to prompts.
Validate the file with guard policy check. If it's invalid, hooks ignore it and every check still applies. It must be owned by you or root and not writable by others.
Risky actions
Each rule in the catalog has a decision:
blockdenies the call.askasks the user to confirm, where the harness can. Elsewhere Guard warns instead.warnlets the call run and tells the user, and in some harnesses the agent.
A rule in detect mode is recorded but not applied, so a new rule can be measured before it enforces.
| Action | Examples | Built-in decision |
|---|---|---|
| Persistence | Writes to CLAUDE.md, AGENTS.md, .cursor/rules/, skills, hook files, .git/hooks, scheduled tasks; crontab, launchctl load |
ask |
| Persistence | Writes to shell startup files and authorized_keys |
warn |
| Guardrail lowering | Turning on bypassPermissions, Codex danger-full-access, removing Guard's hook entries, --dangerously-skip-permissions or --yolo |
block |
| Destructive | Recursive deletes outside the workspace, git push --force, git reset --hard, terraform destroy, kubectl delete |
ask |
| Dropper | Downloaded content piped into an interpreter, such as curl … | base64 -d | node |
block |
| Package install | A package on the catalog blocklist | block |
| Package install | A name resembling a popular npm, PyPI, crates.io, NuGet or RubyGems package, such as expresss; the built-in look-alike rule records it in detect mode |
warn; not applied in the default detect mode |
| Package install | An npm, PyPI or crates.io name the registry doesn't have, going by a signed name snapshot or, where policy turns them on, registry lookups; names it can't settle are unknown and change nothing |
warn; not applied in the default detect mode |
| Package install | Installs from a URL or Git repository; npx, uvx or npm install -g without an exact version |
warn |
| Encoded secret | A base64 or hex string that decodes to a critical or high secret, in a command, a tool argument or, with the human-to-AI sharing opt-in, a prompt | warn |
| Credential write | Writing a critical or high secret into a file that didn't already hold it | warn |
| Untrusted model load | Handing Python or torchrun a pickle file (.pkl, .pt, .joblib and similar) that an agent session downloaded or wrote after taking in untrusted content. Only files named in the command or -c code are seen, and the file is never read |
Reported only |
Look-alike and not-on-registry findings send package names to Guard Cloud only when they match public data: a look-alike of a name on the built-in public reference list, or a name a public registry snapshot or lookup showed missing. A name your policy added to the reference list, or one another registry or a private registry may serve, stays on the device.
Destructive and persistence command rules can be limited to agents in a given state: agents with a named MCP server, skill or plugin, agents using a component nobody has reviewed, or agents whose owner is unknown or inactive. When Guard can't establish that state, the rule's on_unknown decision applies, and the finding says why.
Hooks don't see commands that programs run on their own, such as a package's install script.
What each harness supports
Prompt checks in this table apply with the human-to-AI sharing opt-in on.
| Harness | Prompts | Tool calls | Tool output | ask rules |
Limits |
|---|---|---|---|---|---|
| Claude Code | Blocked | Denied | Replaced for MCP tools; reported for others, after Claude has seen it | Asks | If Claude cannot launch a hook or it times out, the action may proceed. Tool hooks ran live in 2.1.302 on Windows and in WSL2. |
| Codex | Blocked | Denied | Replaced; the command has already run | Warns | Untrusted or disabled hooks don't run. A hook launch failure may let the action proceed. |
| Cursor | Blocked (editor) | Editor: denied reads, writes, shell, MCP. CLI: only shell is claimed | Editor: replaced for MCP tools; reported for others. CLI: not claimed | Asks for shell and MCP; write tools are allowed silently | Cursor CLI never fired beforeSubmitPrompt, so CLI prompts aren't checked. The editor and the MCP, write and ask paths have not been tested live. |
| Cline | Blocked (VS Code); the CLI can't block prompts | Cancelled: the task stops | In VS Code 4.1.23, output arrives as [object Object], so secrets in it reach the model |
Warns | Attachments aren't checked in 4.1.23. Hooks that fail or time out are ignored and the action proceeds. |
| Continue | Not available | Observe only | Not available | None | No hook Guard can use is dispatched, so nothing is installed. guard harness status continue reports its configuration. Not tested in a live session. |
| Copilot CLI / VS Code Copilot Session Target | Rewritten, not rejected; the original may stay in Copilot's local timeline | Denied | Replaced | Implemented and unit-tested, not run live; denied in autopilot mode; warn rules show nothing |
Retained live runs cover the CLI only. The editor's shared runtime has fixture tests; Legacy Local is unsupported. A timeout or invalid reply can run the action. Attachments aren't inspected. Copilot names MCP tools SERVER-TOOL and server names can contain hyphens, so MCP tool access rules and Console MCP blocks don't apply; Guard Cloud reports those blocks as harness_without_hooks. Use the MCP gateway for them. |
| Kimi Code | Opted-in submitted text checked; attachments aren't read | Denied by the reviewed protocol | Reported from an asynchronous preview of at most 2,000 characters; cannot withhold | Required approval is denied | Current Node runtime and its VS Code SDK path have source and fixture tests only. Older Python clients are outside this adapter. A payload Guard can't inspect is denied or blocked for its event. Timeouts and errors can let the action proceed. |
| Qwen Code | Only explicit submitted text is inspected with the opt-in; generated continuation text is not a substitute | Denied by the reviewed protocol | Withheld on the reviewed classic and ACP paths using continue: false; a Qwen build that follows Qwen's documentation may end the turn there |
Required approval is denied | CLI and companion runtime have source and fixture tests only. Code-mode inner tools and paths that bypass hooks aren't qualified. A payload Guard can't inspect is denied, blocked or withheld for its event. Timeouts and errors can let the action proceed. |
| Gemini CLI | Blocked | Denied | Replaced | Warns | A hook timeout or invalid reply runs the action. Guard can't edit a settings.json that has comments. |
| Windsurf | Blocked | Blocked: reads, writes, commands, MCP | Not checked: post-hooks can't change it | Warns | Not validated in a live Windsurf session. The JetBrains plugin reads ~/.codeium/hooks.json, which guard hooks doesn't manage. |
Where entries go
| Harness | Name for install |
User-level location |
|---|---|---|
| Claude Code | claude_code |
~/.claude/settings.json |
| Codex | codex |
~/.codex/hooks.json |
| Cursor | cursor |
~/.cursor/hooks.json |
| Cline | cline |
~/Documents/Cline/Hooks/, one script per event |
| Copilot CLI | copilot_cli |
~/.copilot/hooks/runeward-guard.json |
| VS Code Copilot Session Target | vscode_copilot (alias of copilot_cli) |
The same Copilot user file; reports remain copilot_cli |
| Kimi Code | kimi_code |
~/.kimi-code/config.toml |
| Qwen Code | qwen_code |
~/.qwen/settings.json |
| Gemini CLI | gemini_cli |
~/.gemini/settings.json |
| Windsurf | windsurf |
~/.codeium/windsurf/hooks.json |
- Claude Code: to cover one project only, add the same entries to its
.claude/settings.jsonby hand. - Cline: Guard won't replace a script it didn't write. On Linux, if
xdg-user-dir DOCUMENTSisn't~/Documents, copy the scripts there. For one project, use.clinerules/hooks/. - Windsurf: organizations can put the same entries in the system-level file (
/Library/Application Support/Windsurf/hooks.jsonon macOS,/etc/windsurf/hooks.jsonon Linux), which users can't edit.guard hooksmanages only the user-level file. - VS Code: check the session target and the host that executes the agent. An extension manifest or a default-path status is not proof that hooks ran. Remote SSH, WSL, containers, custom profiles and extension directories need their own setup and qualification. Continue remains observe-only; other extensions do not inherit Copilot's adapter.
- Kimi and Qwen: a custom
KIMI_CODE_HOMEorQWEN_HOMEthat disagrees with the catalog's paths is refused rather than silently installing into the default home. These native adapters do not supply Guard's exact-call Cloud approval, quarantine or Linux managed-endpoint routing. Status checks configuration, not delivery; neither vendor provides a fail-closed guarantee.
Hook checks inspect delivered tool actions outside model inference. Selecting DeepSeek, Kimi, Qwen, a local runtime or another hosted backend does not by itself qualify a client, model or extension. The new native-client tests use synthetic payloads and contact no model provider.
Test with synthetic secrets only, never real credentials.
Written from docs/hooks.md, docs/claude-code.md, docs/codex.md, docs/cursor.md, docs/cline.md, docs/continue.md, docs/copilot-cli.md, docs/gemini-cli.md, docs/windsurf.md, docs/vscode-copilot.md, docs/native-model-clients.md, docs/detection-catalog.md at commit fb79778d02f0. Rune Guard is in early access.