I Built an AI Bouncer for My AI
You can copy this entire post and paste it into Claude Code: “Build this for my system.” It will work.
Claude Code asks permission for everything. Every file write, every bash command, every git operation. You’re supposed to read each one and decide: allow or deny.
Nobody does that.
I run three Claude sessions in parallel. Each one fires 30-40 tool calls per task. That’s a hundred permission dialogs competing for my attention while I’m trying to think. So I click Yes. Yes. Yes. Allow. I don’t read them. My security policy is my attention span.
Claude Code ships a flag for this: --dangerously-skip-permissions. It’s right there in the name. Skip everything. No gate at all. rm -rf /? Sure. Nuke your SSH keys? Go ahead.
I don’t use that flag. But I understand why people do.
The actual problem isn’t permissions. It’s that the only options are “babysit everything” or “allow everything.” There’s no middle.
So I built one. 146 lines of Python. I call it the Bouncer.
I. The Middle Ground
The Bouncer sits between Claude Code and my machine. Every tool call hits it first. It sends the request to a small, fast model (Haiku) and asks: is this safe?
Haiku returns one of three verdicts: allow, ask, or deny.
Allow means the tool runs silently. I never see it. Ask means the normal permission dialog shows up. Deny means it’s blocked.
Takes 1-2 seconds. The 95% of requests that are obviously fine just flow through. I only see the 5% that actually need judgment.
II. Policy as Language
No if tool == “rm -rf”: deny. No pattern matching. No brittle chain of rules that breaks the moment someone spells something differently. The policy is a prompt. Plain English.
POLICY_PROMPT = “”“
You are a security gatekeeper for a developer’s machine.
Evaluate each tool request and return allow, ask, or deny.
ALLOW: file ops in safe dirs, git non-destructive, dev tools, MCP tools
ASK: rm -rf on dirs, git push --force, git reset --hard, sudo
DENY: rm -rf / or ~, system dir writes, .git deletion, ~/.ssh/ mods
Default to ALLOW when uncertain.
“”“To change what the Bouncer allows, I edit English. Not code. Haiku reasons about each request in context. The security policy is a conversation with a small model, not a regex.
III. Infinite Recursion
The recursion problem took a few minutes to see and three lines to fix.
The Bouncer calls Haiku by spawning a claude --print subprocess. Claude Code also triggers the Bouncer hook. So: Claude Code wants to run a tool, Bouncer intercepts, Bouncer calls Haiku, Haiku spawns a claude process, that process triggers the Bouncer hook, which calls Haiku, which spawns a claude process...
The system gating itself gates itself gating itself.
if os.environ.get(”BOUNCER_ACTIVE”):
sys.exit(0)Set an env var before calling Haiku. If present, exit immediately. The recursion collapses on its first step. You don’t find this stuff in a diagram. You find it when the thing hangs.
IV. Fail Open
One design choice I knew would be controversial: timeout behavior.
If Haiku takes more than 12 seconds to respond, the Bouncer auto-allows the request.
except subprocess.TimeoutExpired:
print(make_allow())Every security system you’ve ever used fails closed. Mine fails open. On purpose.
My reasoning: the thing I’m protecting against isn’t “Claude does something dangerous.” It’s “I get interrupted for no reason.” Before the Bouncer, I was already clicking Yes without reading. My security was fail-random. Explicit and imperfect beats implicit and random.
V. 146 Lines
The whole thing is a single file. No dependencies beyond the claude CLI. Hook fires on PermissionRequest, reads JSON from stdin, returns a decision or sys.exit(0) to fall through. Four lines in settings.json to wire it up.
I’ve been running this for weeks across multiple parallel sessions. Haiku hasn’t approved anything it shouldn’t. The tight DENY tier covers the stuff I’d actually lose sleep over. Everything else flows.
Three sessions. Zero babysitting. One Bouncer.
What would you put in the deny tier that I’m missing?
This post is executable. Copy the whole thing, give it to Claude Code, tell it to build a Bouncer for your system. Ship it in 10 minutes.



