Guardrails for agents that run when nobody is watching.
An agent running in front of you needs no guardrails — you are the guardrail. Put it on a cron and every one of those judgements disappears. Few Parts makes the small, dependency-free pieces that replace them.
Watch the guards catch things
The same checks the kit ships, running in your browser. Try a stray write and watch the hook refuse it before it lands — then send the same write through a shell command, where no hook fires, and watch the diff catch it instead. Then try it with the hook unwired: the panel looks exactly like a clean cycle, because a hook that allowed and a hook that never ran are both silent, and only the trace can tell you which one you got. The last button is the opposite case — a path that is inside the allow-list by every reading of the text, and outside it on disk.
{
"cycles": []
}
The kit
Five modules, about 650 lines, no npm dependencies. Read the whole thing in an afternoon or drop it in and move on.
Agent Guardrails Kit
For anyone running a Claude Code (or any other) agent unattended on a schedule. A ready-to-drop-in PreToolUse hook refuses any write outside your allow-list before it happens, a trace wrapper records every hook invocation so you can tell a hook that allowed a write from one that was never wired up, a scope guard diffs git status before you commit to catch whatever a hook can't see, a cycle guard caps runs per month when there's no per-call dollar figure to meter, and a JSON ledger gives you a full audit trail. Five modules, zero npm dependencies, with a working example and a test suite that exercises every function.
For developers running unattended or scheduled AI agents who want a runaway guard, a write allow-list, a way to prove their hooks are firing, and an audit trail without adopting a framework
The writing is free. So is this. What is it for, then?
Every guard here has been explained in an article on this site, and the code in those articles works — copy it if you would rather. What this is, is the assembled version: five modules wired together instead of five separate explanations, a runnable example agent that uses all of them, and a test suite of 26 checks that asserts each guard actually refuses something. That suite is not decoration. It found five real bugs in code that had already been read and looked correct — a porcelain parser eating the first character of unstaged paths, a hook that failed open on every real payload, a Windows path bug that killed the hook silently, a trace wrapper that recorded 200 characters of a Node stack banner instead of the error message, and a write allow-list that could be walked straight out of through a symlink, because comparing paths as strings never asks the filesystem where they actually go. If you would rather spend the afternoon on your own agent than on those five, take this instead.
- Five modules, wired together and working as one system
- A runnable example agent, not fragments to reassemble
- 26 checks that assert each guard denies, and each trace records
- Five bugs already found and fixed, with tests that keep them fixed
- README.md
- ledger.mjs
- cycleGuard.mjs
- scopeGuard.mjs
- writeGuard.mjs
- traceHook.mjs
- cli.mjs
- deny-outside-scope.mjs
- trace-hook.mjs
- trace-report.mjs
- SKILL.md
- smoke-test.mjs
- trace-test.mjs
claude-hook-doctor
Free, read-only diagnosis of a project's Claude Code hooks. Every way a PreToolUse hook can fail ends in 'the tool call proceeds' — a wrong script path, a matcher with the wrong case, a crash, malformed JSON — and a hook that ran and allowed the call looks identical to one that was never wired up, so none of it is visible from inside a normal session. This reads your settings files and your hook source and reports the failures that leave everything looking fine: 24 checks across configuration, script source, and the gaps that are nobody's bug. No dependencies, no network, writes nothing.
For anyone whose Claude Code hook is supposed to be guarding something and who has never seen it refuse anything
Free. So what is it for?
This diagnoses; it does not guard. It reads your settings files and your hook source and names the ways the hook is configured to permit everything — a script path that points at nothing, a matcher that never fires because `write` is not `Write`, a guard with no `exit(2)` and no deny envelope anywhere in it, a permissions block that denies every write and then allows two directories, in the belief that deny plus allow makes an allow-list. Each check exists because that exact failure shipped in a hook someone had already read and reasoned about. What it cannot do is give you the guards: for that there is the Agent Guardrails Kit, which is the assembled version of every fix this tool recommends.
- 24 checks across settings, hook source, and the Bash gap no hook can close
- 56 tests, each asserting in both directions, and the suite has been seen to fail
- Exit codes for CI: 0 clean, 1 warnings, 2 blockers
- Read-only, no network, no dependencies, one `node` command
- README.md
- doctor.mjs
- findings.mjs
- settings.mjs
- script.mjs
- inspect.mjs
- report.mjs
- doctor-test.mjs
Notes from running one
What actually breaks when an agent runs on a schedule, and the code that catches it.
- Hacker News killed your submission and showed you the normal page Removed posts usually look fine to the person who posted them. The one-command check for HN, dev.to, Reddit and your own site, with the failure modes that fooled us.
- Claude Code hook not firing: four reasons it never reaches your script A hook that never ran and a hook that ran and allowed the call look identical from inside a session. Four static reasons, and how to check each one.
- How to detect a scheduled run that never happened Every line in your agent's log was written by a run that happened. A missed one leaves nothing. Here's absence detection that survives DST, and the case it can't cover.
- A symlink walks straight out of an agent's write allow-list path.resolve never opens anything. A link inside your allow-list reads as in scope, and the write lands outside it — here's the escape, the fix, and the bug the fix invites.
- How to cap a scheduled agent's runs, and the three ways the cap leaks Meter runs, not tokens. A 40-line month-boundary cap, the crash loop that gets past it free, and a race that put 7 runs through a cap of 5.
- How to tell whether a Claude Code hook actually ran A hook that fired and allowed the call looks identical to one that was never wired up. Here's a 60-line wrapper that writes down which it was.
- A Claude Code hook that crashes lets the tool call through Every failure path in the PreToolUse contract ends in 'proceed'. Which failure policy to pick, and a test that proves your hook actually denies.
- How to stop a Claude Code agent writing outside a directory Deny rules can't express an allow-list. A PreToolUse hook can — here's the working code, the protocol it speaks, and the writes it will never see.
- Three guards to add before you let a Claude Code agent run unattended A run cap, a scope check against git status, and a ledger you commit — the guards a scheduled Claude Code agent needs, with working code.