Claude Code Advanced
30 minutes
linux
macos
windows

Understanding Permissions

Deep dive into Claude Code's permission system, including when and how to use --dangerously-skip-permissions safely.

What you'll accomplish

Understand the risks and proper use of Claude Code permissions and the skip-permissions flag.

Prerequisites

  • Completed Configuration Deep Dive lesson
  • Familiarity with Docker (for safe usage)

The Permission System

By default, Claude Code asks permission before:

  • Writing files: Creating or modifying any file
  • Executing commands: Running anything in the terminal
  • Accessing sensitive locations: Reading certain files

This is a safety feature, not an annoyance. It keeps you in control.

Warning

Important: Claude Code is an AI assistant. Like any tool, it can make mistakes. The permission system is your chance to catch those mistakes before they happen.

Permission Levels

Read Operations

Claude Code typically auto-approves reading files it needs for context. You can control this:

json
{
  "autoApprove": {
    "read": true
  }
}

Setting this to false would require approval for every file read - usually too restrictive.

Write Operations

Writing files (create, modify, delete) requires explicit approval:

Claude wants to create file: src/components/Button.tsx

[y] Yes  [n] No  [v] View content  [e] Edit first

Options:

  • y - Approve the write
  • n - Reject the write
  • v - See the full file content before deciding
  • e - Edit the content before saving

Execute Operations

Running commands requires explicit approval:

Claude wants to run: npm install react

[y] Yes  [n] No  [m] Modify command

Options:

  • y - Run the command
  • n - Don't run it
  • m - Edit the command before running

The Danger: --dangerously-skip-permissions

The --dangerously-skip-permissions flag tells Claude Code to automatically approve all operations without asking.

bash
claude --dangerously-skip-permissions

When enabled, Claude Code will:

  • ✓ Create, modify, and delete any file
  • ✓ Run any command without confirmation
  • ✓ Execute destructive operations automatically
  • ✓ Make changes you can't easily review

Why It Exists

The flag is useful for:

  1. Automated pipelines (CI/CD) where human approval isn't possible
  2. Containerized environments where damage is contained
  3. Rapid prototyping where you trust the context completely
  4. Batch operations on disposable environments

Why It's Dangerous

Real risks include:

ScenarioWhat Could Happen
Misunderstood requestClaude deletes files you wanted to keep
Overeager cleanup"Remove unused code" deletes your tests
Command chainingInnocent command + mistake = disaster
Sensitive file accessSecrets logged or exposed
Runaway modificationsSmall change spirals into large refactor

Imagine giving someone your house keys and saying:

  • "Reorganize my stuff however you think best"
  • "I trust your judgment completely"
  • "Don't ask me before throwing anything away"

Even with the best intentions, they might:

  • Throw away something you wanted to keep
  • Move things where you can't find them
  • Misunderstand what "organize" means to you

The permission system is like saying "show me what you're about to change first."

Safe Usage: Isolated Environments

Strongly prefer disposable or isolated environments when using --dangerously-skip-permissions. This includes:

  • Docker containers (most common)
  • Virtual machines
  • Throwaway Git branches (where you can easily discard all changes)
  • Cloned project directories (not your main working copy)

The key principle is limiting the blast radius—if Claude makes unwanted changes, you should be able to easily discard them without affecting your real work.

Why Docker Is Popular for This

Docker is the most common choice because it provides:

  1. Isolation: The container is separate from your real system
  2. Disposability: If something goes wrong, delete the container
  3. Reversibility: Your actual files are untouched
  4. Reproducibility: Containers can be rebuilt from scratch

Basic Docker Setup

Dockerfile:

dockerfile
FROM node:20-slim

# Install Claude Code
RUN npm install -g @anthropic-ai/claude-code

# Create workspace
WORKDIR /workspace

# Run as non-root user
RUN useradd -m coder
USER coder

# Default command
CMD ["claude", "--dangerously-skip-permissions"]

Build and run:

bash
# Build the image
docker build -t claude-dev .

# Run with your project mounted
docker run -it \
  -v $(pwd):/workspace \
  -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
  claude-dev
Warning

Even with Docker, be careful about volume mounts. If you mount your home directory (-v ~:/workspace), Claude has access to everything in it.

Docker Compose Setup

For a more complete setup:

yaml
# docker-compose.yml
version: '3.8'

services:
  claude:
    build: .
    volumes:
      - ./project:/workspace
    environment:
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
    stdin_open: true
    tty: true

Run with:

bash
docker-compose run claude

Recommended Volume Strategy

Mount only what Claude needs:

bash
# Good: Only the project directory
docker run -it -v ./my-project:/workspace claude-dev

# Bad: Your whole home directory
docker run -it -v ~:/workspace claude-dev  # DON'T DO THIS

Alternative: Selective Auto-Approve

Instead of skipping all permissions, selectively auto-approve safe operations:

json
{
  "autoApprove": {
    "read": true,
    "write": {
      "patterns": ["src/**/*.ts", "src/**/*.tsx"],
      "exclude": ["*.env*", "*.secret*", "package-lock.json"]
    },
    "execute": {
      "commands": ["npm run", "npx prettier", "npx eslint"],
      "exclude": ["rm", "sudo", "git push"]
    }
  }
}

This approach:

  • Auto-approves writes to specific directories
  • Excludes sensitive files
  • Allows specific safe commands
  • Still requires approval for everything else

Permission Best Practices

1. Start Restrictive

Begin with default permissions. Only relax them after you understand the workflow.

2. Review Before Approving

Take time to read what Claude is proposing. A few seconds of review can prevent hours of cleanup.

3. Use Git as a Safety Net

Always work in a Git repository. If something goes wrong:

bash
# See what changed
git diff

# Undo all changes
git checkout .

# Or undo specific files
git checkout src/important-file.ts

4. Test in Isolation First

Before running --dangerously-skip-permissions on a real project:

  1. Clone the repo to a temporary location
  2. Run Claude there first
  3. Review the changes
  4. Apply to the real project if satisfied

5. Set Up Hooks for Safety

Use pre-execute hooks to block dangerous commands:

json
{
  "hooks": {
    "pre-execute": {
      "command": "./scripts/command-safety.sh {{command}}",
      "failBehavior": "block"
    }
  }
}

When to Use Each Approach

ScenarioRecommendation
Learning / exploringDefault permissions (ask for everything)
Normal developmentAuto-approve reads, manual approve writes
Trusted, simple taskAuto-approve matching patterns
Docker container--dangerously-skip-permissions OK
CI/CD pipeline--dangerously-skip-permissions OK
Production systemNever use skip-permissions
Shared machineDefault permissions only

Recovering from Mistakes

If Claude makes unwanted changes:

With Git (Recommended)

bash
# See what changed
git status
git diff

# Undo all uncommitted changes
git checkout .
git clean -fd

# Undo specific file
git checkout path/to/file.ts

# Undo last commit (keep changes staged)
git reset --soft HEAD~1

# Undo last commit (discard changes)
git reset --hard HEAD~1

Without Git

If you're not using Git (please start!):

  1. Check your IDE's local history (VS Code: File > Local History)
  2. Check system backups (Time Machine, etc.)
  3. Manually review and fix changes

In Docker

bash
# Delete the container (changes in container are lost)
docker rm container_name

# Changes in mounted volumes persist - use git

# Start fresh
docker run -it claude-dev

Common Issues

Frequently Asked Questions

If you're using Git, yes - use git checkout . to revert. Without Git or Docker isolation, recovery may be difficult or impossible for destructive changes.

Yes, when prompted you can often type:

  • y - approve this one
  • a - approve all (for this session)
  • n - reject this one

Check the prompt for available options.

Yes, use hooks with failBehavior: "block":

json
{
  "hooks": {
    "pre-write": {
      "command": "./scripts/check-write.sh {{file}}",
      "failBehavior": "block"
    }
  }
}

You're always in control. If Claude suggests something risky:

  1. Reject the operation (n)
  2. Explain why it's problematic
  3. Ask for an alternative approach
  4. Exit the session if needed (/exit)

Be cautious of:

  • rm -rf (especially with /, ~, *)
  • sudo anything
  • git push --force
  • Commands with > (overwrites files)
  • Package install commands from unknown sources
  • Commands that modify system files

Verify Your Understanding

You've completed this lesson if you can:

0/5

Next: Running Claude Code in Docker containers for isolation.