Gaëtan Wittebolle.FR
← guides
Claude Code, the guide
Chapter 9 / 16

Part 1 · Foundations

  • 01What is Claude Code?
  • 02Step-by-step installation
  • 03CLAUDE.md, the brain of your project

Part 2 · Communicate and plan

  • 04How to talk to Claude Code
  • 05Plan before coding
  • 06The daily work cycle

Part 3 · Advanced tools

  • 07Specialized agents
  • 08The shortcuts that speed everything up
  • 09Permissions

Part 4 · Mastery

  • 10Memory between sessions
  • 11Case study, a feature from A to Z
  • 12The 11 fatal mistakes to avoid

Part 5 · Going to production

  • 13The checklists
  • 14Setting up infrastructure

Part 6 · Bonus, a power user's setup

  • 15Generating images from Claude Code
  • 16My complete setup

Part 3 · Advanced tools

Permissions

Chapter 9 · 5 min reading

🎯

This chapter explains how Claude Code's permission system works, what it can do on its own and what needs your approval. You always stay in control. Reading time: 5 minutes.

Claude always asks before acting

Claude Code will never do anything risky without explicitly asking you. That's a fundamental safety rule.

But there's a practical issue: by default, it asks for confirmation on every command, even the most mundane ones. Run a typecheck? Confirmation. Run lint? Confirmation. Read a file? Confirmation. After 50 confirmations in 1 hour, you go nuts.

The solution: pre-authorize safe commands while keeping validation for risky actions.

The 3 risk levels

🟢

Safe, automatic

Claude does this freely, without asking you anything:

  • Read files
  • Navigate the code
  • Analyze the project
  • Search for patterns in the code
🟡

Moderate, asks for confirmation

Claude shows you what it's about to do and waits for your OK:

  • Modify files
  • Install packages
  • Run commands (tests, build, migrations)
  • Create new files
🔴

Risky, always asked

Claude explains in detail and waits for your explicit validation:

  • Push code to GitHub (git push)
  • Delete files or branches
  • Irreversible actions (database reset, etc.)
  • Unknown or unusual commands

Pre-authorize safe commands

To avoid clicking "Yes" 50 times per session, create a config file that automatically allows repetitive, risk-free commands.

Create the file

Create the file .claude/settings.local.json at the root of your project:

{
  "permissions": {
    "allow": [
      "Bash(npm run *)",
      "Bash(npx supabase *)",
      "Bash(npx vitest *)",
      "Bash(git status*)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(git add *)",
      "Bash(git commit*)"
    ]
  }
}
💡

Wildcard syntax: use * as a wildcard. Bash(npm run *) allows npm run dev, npm run build, npm run test, etc. with a single rule. No need to list every variant.

What it allows

CommandWhy it's safe
npm run typecheckChecks types, modifies nothing
npm run lintChecks style, modifies nothing
npm run testRuns tests, modifies nothing
npm run buildCompiles the app, doesn't change source code
npx supabaseLocal Supabase commands
git status/diff/logRead-only on Git state
git add/commitLocal save (no push)

What still asks for confirmation

  • git push (sending code online)
  • npm install (adding dependencies)
  • File deletion
  • Unknown commands

Trust mode

If you're in a heavy dev session and you fully trust Claude, you can switch to "trust" mode from the interface. Claude won't ask for confirmation on anything anymore.

⚠️

Watch out: trust mode is powerful but risky. Use it only when you know exactly what Claude is going to do (e.g. running a plan you've validated). Don't leave it on permanently.

The day-to-day experience

With a well-configured permissions file, here's what it looks like in practice:

  • Claude writes code → you see files getting modified live in VS Code
  • Claude runs typecheck → goes through automatically, no confirmation
  • Claude runs lint → goes through automatically
  • Claude wants to install a package → asks "Install framer-motion?" → you approve
  • Claude wants to commit → goes through automatically with the right message
  • Claude wants to push → asks "Push to branch feat/streak?" → you approve

The result: you only click on decisions that actually matter.

The safety net: the deny list

More powerful than the allowlist: the deny list. It blocks dangerous commands even in full trust mode. It's your ultimate safeguard.

In your ~/.claude/settings.json (global, for all projects):

{
  "permissions": {
    "deny": [
      "Bash(rm -rf*)",
      "Bash(sudo*)",
      "Bash(supabase db reset*)",
      "Bash(git push --force*)",
      "Bash(git push -f*)",
      "Bash(git reset --hard*)",
      "Bash(git clean -f*)"
    ]
  }
}
🛡️

These commands are blocked no matter what, even if you're in trust mode, even if Claude thinks it's necessary. rm -rf can wipe out your entire project. supabase db reset destroys all data and credentials. git push --force can overwrite your team's work. Better safe than sorry.

The difference between allow and deny:

  • allow (.claude/settings.local.json per project): commands allowed without confirmation
  • deny (~/.claude/settings.json global): commands forbidden everywhere, even in trust mode
💡

Takeaway: configure the allowlist once per project and the deny list once globally. You eliminate 90% of useless confirmations while blocking dangerous commands. It's the perfect balance between flow and safety.

← Chapter 8

The shortcuts that speed everything up

Chapter 10 →

Memory between sessions