← Writing

Most AI dev tools use an allowlist model that turns you into a full-time approver. A deny list inverts the equation and gets out of your way.


How many times a day do you hit “approve” on a command you already know is safe?

That’s not a security measure. That’s friction you’ve learned to ignore.

The Allowlist Problem

Most AI dev tools ship with an allowlist model. Nothing runs until you explicitly approve it. On paper this sounds responsible. In practice, it means you’re approving every git commit, every npm install, every npm test — things you’d approve a thousand times without hesitation.

You become a button that exists to confirm things that were never in question.

The average developer using an allowlist-based AI tool makes dozens of approval decisions per hour. Almost none of them represent real risk. All of them break flow.

Flipping the Model

I switched to a deny list. Block what’s actually dangerous, let everything else run.

Here’s the complete settings.json that governs my entire Claude Code setup:

Allow everything:

"allow": ["Bash(*)", "Read(*)", "Edit(*)", "Write(*)"]

Deny 11 specific things:

  • git push --force to main or master
  • rm -rf on non-temp directories
  • git branch -D on main
  • chmod 777
  • kill -9 on arbitrary processes
  • Reading .env files
  • Dropping production databases
  • A few more destructive patterns

That’s it. Eleven rules covering the things that are genuinely hard to undo.

The Math

Before: hundreds of daily approvals for commands I’d never say no to.

After: zero interruptions on the 95% of operations that were never risky. The 11 deny rules still protect against the 5% that matter.

The default assumption in AI tooling is “block everything, approve selectively.” That model optimizes for the edge case at the cost of the happy path. A deny list inverts the ratio — it optimizes for flow while guarding the things that actually need guarding.

What to Put on Your Deny List

A practical deny list for most developers:

  1. Anything touching production databases without explicit flags
  2. Force pushes to protected branches
  3. Recursive deletion outside temp/build directories
  4. Reading secret files (.env, credential files, key files)
  5. Killing processes by PID without context

Most other things can run. If they break, git reset or a rebuild recovers you in minutes. The things on the deny list break things in ways that are genuinely hard to fix.

The question isn’t “is this command safe?” — it’s “if this goes wrong, how long does recovery take?” That’s the right bar for what earns a deny rule.


AI Minus the Friction #2. Read the full series.