Claude Code guardrails: practical controls for tool use, logging, and policy enforcement
If you are looking for claude code guardrails, the problem is usually not prompt quality. The real issue is execution control: what commands the agent can run, where it can write, and how you inspect what happened after the fact. Claude Code is useful, but once it starts invoking tools against a live repository, you need a policy layer outside the model.
A workable approach is to wrap each Claude process with a supervisor that can inspect tool calls, log them, and block actions that violate your rules. That is what agentcheck does. It adds hook-based guardrails around Claude Code, writes every tool call to JSONL, and loads YAML rule packs that define what is allowed or denied.
What guardrails should actually cover?
For a developer workflow, useful Claude Code guardrails are concrete and narrow. They should answer questions like:
- Can the agent write outside the current repo?
- Can it run destructive shell commands such as
rm -rforgit reset --hard? - Can it touch secrets, deployment files, or CI config?
- Can you reconstruct the exact sequence of tool calls later?
That last point matters. Without logs, a blocked or failed run is hard to debug, and a successful run is hard to trust. You want enforcement and observability together, not as separate systems.
Install and run agentcheck
The install path is simple. AgentCheck is distributed directly from GitHub:
npm install -g github:paprika-org/agentcheck
From there, the typical workflow is:
# Example: run Claude Code behind agentcheck with a rules file
agentcheck --rules ./agentcheck.rules.yml -- claude
The exact invocation depends on how you launch Claude Code in your environment, but the pattern is the same: agentcheck sits in front, loads a rule pack, and intercepts tool activity.
Start with a minimal rule pack
The easiest mistake is writing a giant policy before you know what the agent actually does. Start with a short rule pack that blocks obviously risky behavior and lets normal coding work continue.
version: 1
rules:
- id: deny-destructive-shell
tool: shell
match:
command_regex: '(rm -rf|git reset --hard|sudo )'
action: deny
message: 'Destructive or privileged shell command blocked'
- id: deny-secrets
tool: read
match:
path_regex: '(\.env|id_rsa|credentials\.json)'
action: deny
message: 'Secret material is off limits'
- id: restrict-writes
tool: write
match:
path_regex: '^(/workspace/my-repo/|src/|tests/)'
action: allow
- id: deny-other-writes
tool: write
action: deny
message: 'Writes outside approved paths are blocked'
This does not make the agent safe in every context, but it closes off common failure modes. It also forces you to be explicit about scope. If the agent only needs src/ and tests/, do not leave the whole filesystem available.
Use the logs as part of development
One reason people ask for Claude Code guardrails is that they want post-run accountability, not just prevention. AgentCheck logs every tool call to JSONL, which is much easier to query than free-form terminal output.
{"ts":"2026-04-23T09:10:12Z","tool":"read","path":"src/parser.ts","result":"ok"}
{"ts":"2026-04-23T09:10:14Z","tool":"shell","command":"npm test","result":"ok","exit_code":0}
{"ts":"2026-04-23T09:10:18Z","tool":"write","path":"src/parser.ts","result":"denied","rule_id":"deny-other-writes"}
With logs like that, you can answer practical questions quickly:
- Did the agent try to run a forbidden command?
- Was a failure caused by the model or by policy?
- Which files did it read before making an edit?
You can process the JSONL with standard tools:
# Show denied actions
jq 'select(.result == "denied")' .agentcheck/log.jsonl
# Count shell commands by exit code
jq -r 'select(.tool == "shell") | [.exit_code] | @tsv' .agentcheck/log.jsonl | sort | uniq -c
Good guardrails are iterative
A useful pattern is to begin in a mostly permissive mode, inspect the logs, and then tighten the rules based on observed behavior. For example, if the agent keeps trying to read your entire home directory to find config files, add a deny rule. If it only needs test execution, restrict shell to a small command set.
version: 1
rules:
- id: allow-safe-shell
tool: shell
match:
command_regex: '^(npm test|npm run lint|pnpm test|pytest)$'
action: allow
- id: deny-all-other-shell
tool: shell
action: deny
message: 'Shell access is limited to test and lint commands'
This is more reliable than asking the model to “be careful.” Model instructions are advisory. External hooks are enforcement.
Where these controls help most
In practice, Claude Code guardrails are most valuable in a few specific situations:
- Running agents against production-adjacent repositories with deployment scripts, infra code, or secrets nearby.
- Letting multiple developers or CI jobs share the same agent workflow with a consistent baseline policy.
- Debugging why an agent failed after a long run, especially when tool calls matter more than the final answer.
They are less useful if your environment is already fully sandboxed and disposable, or if you only run the agent manually for tiny one-off edits. Even then, logging is still valuable because it gives you a real execution trace instead of guesswork.
What agentcheck does and does not do
AgentCheck is a governance layer, not a replacement for OS sandboxing, container isolation, or human review. It helps constrain agent behavior and record it. You should still use normal engineering controls: separate credentials, least privilege, branch protections, and isolated environments for risky work.
That said, if your current setup is “run Claude Code and hope the prompt is enough,” adding hook-based rules and JSONL audit logs is a substantial improvement. It gives you something concrete to enforce and something concrete to inspect.
If you need claude code guardrails that are explicit, inspectable, and easy to version with your repo, start with AgentCheck. Install it with npm install -g github:paprika-org/agentcheck and review the source at github.com/paprika-org/agentcheck.