guard
Stdlib-only safety hooks for Claude Code.
Every decision is logged to JSONL — query and trace in place with guard status|noisy|silent|trace.
$ rm -rf /
guard: deny - rm -rf against /, /*, ~, $HOME, ., or ./ is catastrophic.
Guardrails not walls: guard catches the obvious foot-guns at the Claude Code hook layer so a stray tool call doesn't turn into a bad day. It is defense-in-depth, not a security boundary.
What it does
| Hook | What it catches |
|---|---|
| bash_command_validator | dangerous shell commands (rm -rf, eval/source, env-var hijack, shell-wrapper bypass) + admin-CLI default-deny for aws/gcloud/az/kubectl/launchctl (only read-only verbs pass) |
| git_c_validator | git -C path traversal, git -c key=value config injection, git commit -C silent message reuse |
| credential_check | hardcoded credentials in tool inputs |
| commit_message_validator | AI-attribution trailers (Co-Authored-By: Claude…) and missing/file-backed commit messages |
| agent_output_guard | reads of subagent transcript files (/tmp/claude-<pid>/.../tasks/*.output) |
| protected_files | edits to user-marked protected files |
| subagent_scope | file edits outside the declared .claude/subagent-scope.json allowlist |
| permission_request_logger | observation-only: logs every Claude Code permission prompt as a permission_request JSONL row (no enforcement) |
Install
Inside Claude Code:
/plugin marketplace add TracineHQ/plugins
/plugin install guard@tracine
This installs guard from the unified TracineHQ plugin catalog. The same marketplace also hosts convo; once the marketplace is registered you can install either with one command.
Standalone alternative (skip the catalog and install guard directly from this repo):
/plugin marketplace add TracineHQ/guard
/plugin install guard@tracinehq
TracineHQ/guard is the GitHub owner/repo shorthand for the marketplace source. guard@tracinehq is the <plugin>@<marketplace> reference Claude Code uses to install. To pin a specific tag:
/plugin marketplace add TracineHQ/guard#v1.3.0
Requirements
- Claude Code v2.0.0+ (plugins entered public beta on 2025-10-09)
- Python 3.11+ available on
python3PATH (no third-party dependencies) - POSIX shell environment (Linux, macOS, WSL). Windows is not supported in v1 — the matchers target POSIX shell shapes (
rm -rf,cat ~/.aws/credentials, process substitution) and offer no meaningful protection against PowerShell orcmd.exeequivalents. CI runs onubuntu-latestandmacos-latest.
Optional: power-user CLI
The marketplace install above wires up the safety hooks. To query the decision log without tail | jq, install the read-side CLI from PyPI:
pipx install tracine-guard
Then guard status shows the log location and last record, guard noisy --since 24h ranks rules by hit count, guard trace <session_id> dumps a chronological view, and guard silent lists rules that fired historically but not recently. Query subcommands are read-only against ~/.claude/guard-decisions.jsonl; guard allowlist * writes to your allowlist file (project or --global). The two install paths complement each other; they aren't alternatives.
Configuration
Guard reads a small set of environment variables. See SKILL.md for the canonical descriptions and defaults.
Strict default-deny activates from Claude Code's permission_mode field in
PreToolUse hook input (no env var). The strict modes are auto (Anthropic's
classifier-mediated unattended mode), dontAsk, and bypassPermissions --
all three imply "no human at the prompt." Other modes (default, plan,
acceptEdits) use advisory evaluation.
Requirements: Claude Code that emits permission_mode on PreToolUse
payloads (current Claude Code releases do; older builds default to advisory
since the field is absent). For one minor cycle, a deprecated
CLAUDE_AUTONOMOUS=1 env var fallback escalates to dontAsk with a stderr
warning -- remove the env var before the next minor release.
Healthcheck: guard healthcheck exits 0 on healthy, non-zero on
failure. Suitable for CI gates and cron-based monitors.
Mode (enforce / shadow / off): the effective mode lives in
.claude/guard/allowlist.json as a top-level "mode" field (project),
with ~/.claude/guard/allowlist.json (global) as fallback. Default is
"enforce". Flip with guard mode shadow --project to test a new rule
against real sessions without blocking -- denies are logged with
mode: "shadow" but the hook exits 0 so Claude Code's normal permission
flow takes over. Restore with guard mode enforce --project. "off"
short-circuits the hook entirely (no decisions, no audit row).
| Variable | Purpose |
|---|---|
GUARD_DECISIONS_PATH |
Override the JSONL decision-log path |
GUARD_STRICT_DENY_QUEUE_PATH |
Override the strict-deny queue path |
GUARD_DEBUG |
Emit per-hook debug to stderr |
GUARD_DATA_DIR |
Override guard's data directory |
GUARD_PROTECTED_EXTRA |
Comma-separated extra protected glob patterns (fallback when .claude/guard-protected.txt, rooted at cwd, is absent) |
GUARD_ADMIN_ALLOW_VERBS |
Per-verb allow for bash.admin_default_deny; format <cli>:<verb.path>,<cli>:<verb.path> (e.g. aws:ec2.run-instances,gcloud:functions.deploy) |
Catalog model (AWS): the admin matcher uses an explicit (service, verb) allowlist for aws. Verbs not in the catalog deny by default. To rescue a long-tail verb without a code change, set GUARD_ADMIN_ALLOW_VERBS="aws:<service>.<verb>" (see SECURITY.md for the decision tree and the list of deliberately-excluded verbs).
To disable an individual hook, remove its entry from ~/.claude/settings.json PreToolUse, or comment the line in hooks/hooks.json if you forked the plugin.
What it doesn't do
- Not a security boundary. A determined attacker who controls input to Claude Code can bypass any client-side hook.
- Defense-in-depth, not an exclusive safety mechanism.
- Logs decisions for observability; doesn't enforce server-side.
Output log
Every decision is appended to ~/.claude/guard-decisions.jsonl (NDJSON, one record per line). The schema is stable and documented in docs/JSONL_FORMAT.md.
Tail and pretty-print:
tail -f ~/.claude/guard-decisions.jsonl | jq
Or use the built-in guard CLI for read-side queries:
guard status # installation status + log location + line count
guard healthcheck # synthesise a known-deny payload and assert deny
guard noisy --since 7d # top hit rules in the last week
guard silent --since 30d # rules that haven't fired in 30 days
guard trace <session-id> # all records for a single session
guard test "<command>" # what would each hook decide?
guard diff # effective merged config (stub)
guard allowlist list # show effective allowlist (list/rules/disable-rule/...)
guard migrate-log # one-shot rewrite of the JSONL log to schema v1
Development
just check
Runs lint, typecheck, and tests. See CONTRIBUTING.md for setup, test tiers, and commit conventions.
Known limitations
Guard is defense-in-depth, not a security boundary. The validators trade exhaustive coverage for low false-positive rates and stdlib-only portability, which means a determined attacker who controls Claude Code's input can bypass any client-side hook. Pattern-matching is conservative on purpose: rules deny shapes that have a clear safer alternative and pass shapes that are ambiguous. For the threat model, the disclosure process, and a list of areas guard explicitly does not cover, see SECURITY.md.
License
Apache 2.0 — see LICENSE.
Metadata
Release files for tracine-guard 1.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tracine_guard-1.5.0.tar.gz | 490.3 kB | With provenance | Details for tracine_guard-1.5.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tracine_guard-1.5.0-py3-none-any.whl | Python 3 | none | any | Details for tracine_guard-1.5.0-py3-none-any.whl |
Total release size: 704.6 kB
Release files / tracine_guard-1.5.0.tar.gz
| Download URL | tracine_guard-1.5.0.tar.gz |
|---|---|
| Size | 490.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a4d93e7387740f8c99a59bd21b1223bef06d0ddc10fc36f97a278ecea022d551
|
|
BLAKE2b-256 checksum How to use checksums |
8a2fd16d6af563f557a79f8ba846bff6538cbc590c0ffd6cca067a62b1d15634
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.
Transparency logRelease files / tracine_guard-1.5.0-py3-none-any.whl
| Download URL | tracine_guard-1.5.0-py3-none-any.whl |
|---|---|
| Size | 214.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c6aa6e802e9f2e3ffbe9c650a7674b93c2b0fa72b87a63e061f625da9d940150
|
|
BLAKE2b-256 checksum How to use checksums |
ba68bc405aeb0b0462131728ff7abfd9e9e5693affe310a02da25515df2fa790
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.
Transparency logSecurity for tracine-guard 1.5.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tracine_guard-1.5.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 3, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.