Anthropic’s new Duet agent stops and asks before it sends a message, pays, signs or deletes something. I do something similar in Claude Code, mainly so it doesn’t start coding before I’ve agreed to a plan. This is my setup. For single commands you don’t need any code. Whatever you list under “ask” in .claude/settings.json needs your OK every time: “permissions”: { “ask”: [“Bash(git push *)”, “Bash(npm publish *)”] } } That covers git push and similar. It didn’t help with what bothered me more: Claude writing code for a feature we hadn’t planned yet. I tried putting that into the skill first, something like “read plan.md and stop if its status isn’t approved”. Most of the time that works. In long sessions Claude sometimes decides it’s fine to go ahead anyway, and it always has a reason. So now it’s a PreToolUse hook, also in .claude/settings.json: { “hooks”: { “PreToolUse”: [{ “matcher”: "Write] }] } } gate.py gets the tool call as JSON on stdin, looks at which file is about to be written and checks what has to be true first. For me that’s things like “plan.md only after spec.md is approved”. If the check fails it prints this and exits: {“hookSpecificOutput”: {“hookEventName”: “PreToolUse”, “permissionDecision”: “deny”, “permissionDecisionReason”: “plan.md needs an approved spec.md first”}} Claude Code drops the write and Claude sees the reason. Two things I’d do the same way again. I approve something I can actually read, a spec or a plan with numbered acceptance criteria, and never just “looks good”. And I can override a gate, but only with a line in a file that says who, why and when. Without that I’d have switched the hook off the first time it got in my way. The full version of this is in aSPARK, an open source plugin I wrote. A product owner, an engineering manager, a reviewer and a QA tester run as separate agents, and I sign off the spec, the plan and the release. A second plugin, aspark-guard, is the hook part and also logs every change with a hash. On one real feature (a todo app, 29 acceptance criteria, 47 minutes) the reviewer found a bug the developer had already called done, and it shipped when I typed “Go, release v0.1.0”. https://github.com/a-lottes/aSPARK What do you gate in your setup? And did you remove any gates because they got annoying? submitted by /u/Potential-Beat2841
Originally posted by u/Potential-Beat2841 on r/ClaudeCode
