Claude Code agents can run shell commands, read files, and spawn subagents—and you usually find out what they did only by scrolling through a transcript. Denied calls vanish entirely.
agent-pd, by Varma Budharaju, installs a hook that records every PostToolUse, PermissionDenied, SubagentStart, and SubagentStop into a per-session, hash-chained JSONL log. The hook exits 0, never blocks, and captures events the transcript can't.
Zero-Token Detectors Catch What Transcripts Miss
Six deterministic detectors run in pure Python with zero LLM tokens: denied calls, out-of-scope reads, credential access, permission bypass, self-permissioning, disallowed tools, and off-task work. Each offense comes with quoted evidence from the log.
pd report replays the audit log forensically; pd watch streams a live "police scanner" feed of all active sessions. In the repo's demo, the engine flagged a sudo rm -rf /tmp/cache as critical permission bypass and a read of ~/.ssh/id_rsa as critical out-of-scope.
Hash-Chained Audit Log with Named Sessions
Every audit line is hash-chained so you can verify chain integrity (pd verify shows "7 event(s) verified"). Sessions are identified by project directory and first user prompt—no opaque UUIDs. An optional off-host append-only sink prevents tampering from inside the agent.
I like that denied calls exist only in the audit log. That's why the hook exists instead of parsing transcripts: Claude Code kills denied tool calls before they appear anywhere else.
Honest by Design: Catch-and-Report, Not a Sandbox
Budharaju is explicit: agent-pd is not a firewall. It raises the bar for observability so you know what an agent actually did, after the fact or live. For teams running Claude Code in production, agent-pd turns agent behavior from a black box into a searchable, replayable record—and it costs nothing to run.
Source: Show HN: A police department for your Claude Code agents
Domain: github.com
Comments load interactively on the live page.