Claude Code supports a PreToolUse hook: a command that runs before every tool
call and can block the call by exiting with a non-zero status. agentjail is
designed to sit exactly there, and Claude Code is the only agent with a
turnkey installer today (macOS only).
How it works
When agentjail is installed for Claude Code, it registers agentjail-hook as
the PreToolUse hook. Before each tool invocation Claude Code writes a JSON
event to the hook’s stdin; agentjail-hook evaluates it against your local
Rego policy and responds with a decision. A denial exits 2, which causes Claude
Code to stop the call and surface the block reason instead of running the
command.
For a full explanation of the hook protocol and how to test your policy interactively, see the generic hook guide.
Install
Quick install (recommended):
curl -fsSL https://agentjail.io/install.sh | sh
The script downloads the release tarball, verifies the SHA256 checksum,
installs binaries to ~/.agentjail/bin/, and runs agentjail install --for claude-code.
Homebrew:
brew install agentjail/tap/agentjail
agentjail install --for claude-code
Both paths are macOS-only. Linux support is not yet available.
What the installer writes
agentjail install --for claude-code adds the following entry to
~/.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "~/.agentjail/bin/agentjail-hook"
}
]
}
]
}
}
Every tool call Claude Code makes will pass through agentjail-hook before
execution.
Verify it is working
You can test agentjail-hook directly from the terminal (the daemon must be
running). Pipe a synthetic PreToolUse event to the hook and inspect the
output:
echo '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' \
| agentjail-hook
The hook prints a JSON response:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "..."
}
}
Exit 0 means allow or ask; exit 2 means deny. A denial from the test above confirms that agentjail is evaluating policy correctly.
To confirm the live hook is gated, trigger a tool call inside Claude Code that your policy should block and verify the agent stops rather than proceeding.