· 6 min read · André Flitsch

Running Claude Code in YOLO Mode Without the Actual YOLO

A glowing Docker container floating in a dark cinematic environment, representing isolated AI agent execution

I love --dangerously-skip-permissions. No confirmation prompts, no “are you sure?” dialogs. Just Claude doing what you asked, full speed. The flag is called “dangerous” for a reason though. An unconstrained AI agent with shell access to your actual machine can do real damage. One hallucinated rm -rf and your afternoon gets a lot more interesting.

I wanted the speed without the risk. So I built a Docker wrapper that runs Claude Code in full YOLO mode inside an isolated container. If Claude nukes everything, it nukes a disposable box, not my Mac Studio.

pixelhed/claude-container
Shell00

It lives as a git submodule inside your projects, so every project gets the same base setup while keeping its own config separate. Here’s how it works and why I built it the way I did.

Why Not Just Run It On Your Machine?

When you run claude --dangerously-skip-permissions on bare metal, Claude has access to everything you do. SSH keys, git credentials, your entire filesystem. For quick throwaway tasks, that’s fine. For serious project work where Claude is installing packages, running builds, modifying files across a codebase, I wanted a boundary.

Docker gives you that boundary for free. The container can only see what you mount into it. The tradeoff is setup complexity, and that’s what claude-container eliminates.

How It’s Structured

my-project/
├── claude-container/          # git submodule (template)
│   ├── bin/                   # lifecycle scripts
│   ├── Dockerfile
│   ├── docker-compose.yml
│   ├── build.conf             # defaults (tracked)
│   ├── settings.container.json
│   └── .env                   # your credentials (gitignored)
└── workspace/                 # your actual code

Your code lives in workspace/, bind-mounted into the container at /workspace. The submodule owns the container definition. You never edit template files per project. All customization goes through gitignored overlay files. This means I can push improvements to the template and every project picks them up with bin/update.

Only Install What You Need

The base image is node:20-bookworm-slim with Claude Code installed via the native installer. Build-arg flags control which runtimes get added:

# build.conf — template defaults
INSTALL_PHP=false
INSTALL_PYTHON=true
INSTALL_COMPOSER=false

I work on Magento projects, so for those I create a build.local.conf:

INSTALL_PHP=true
INSTALL_COMPOSER=true

Run bin/rebuild and PHP + Composer are available. Python-only project? Leave the defaults. Image stays lean.

Settings That Layer Properly

This was one of the things I spent the most time on. Claude Code’s settings.json controls hooks, MCP servers, and preferences. In claude-container, settings use a two-file merge:

  • settings.container.json for template defaults (tracked)
  • settings.container.local.json for your project overlay (gitignored)

The entrypoint merges them at startup with jq. The merge strategy matters. Hooks append per event, so template hooks and project hooks both fire. MCP servers get replaced per key, so the project definition wins. Everything else is last-write-wins.

A Magento project might add a PHP formatter hook and enable the n8n MCP server:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [{ "type": "command", "command": "php-cs-fixer fix $FILE_PATH --quiet" }]
      }
    ]
  },
  "mcpServers": {
    "n8n": { "enabled": true }
  }
}

The template’s own session hooks still fire. The project just layers on top.

The Ecosystem Mount

I maintain a claude-ecosystem directory on my machine. Global commands, skills, rules, agent definitions that I want everywhere. The container mounts it read-only and the entrypoint symlinks everything into ~/.claude/ on startup. My custom slash commands, coding standards, refactoring skills, all available in every containerized project without copying files around.

This is one of those things where once you have it, you can’t go back. I’m constantly adding new skills and rules and they just show up everywhere.

What Survives a Restart

Auth tokens, plugin state, and bash history persist in Docker volumes. You run claude auth login once and it sticks across bin/stop / bin/start cycles. Your project code is a bind mount so that’s never at risk. bin/destroy is the nuclear option. It removes volumes too, so you’d need to re-authenticate.

The Firewall (Optional)

There’s an iptables-based firewall script you can activate from inside the container:

sudo init-firewall

Restricts outbound traffic to a whitelist: Anthropic API, npm, PyPI, GitHub, SSH. Everything else gets dropped. Most of the time I don’t use it because development workflows need broader access, but for anything security-sensitive it’s there.

Day to Day

Once it’s set up, it’s three commands:

cd my-project/claude-container
bin/start
bin/claude

Or just bin/claude. It auto-starts the container if it’s not running. Headless mode works too:

bin/claude -p "fix all PHPStan level 6 errors"

bin/shell gives you bash inside the container for debugging. bin/status shows what’s installed and running.

Extending Per Project

Two extension points handle project-specific stuff without touching the template.

Workspace Dockerfile. Create workspace/Dockerfile to extend the base image. The build system detects it, builds the base first, then layers your additions. Need PostgreSQL client? Redis tools? Just add them here.

Workspace scripts. Put scripts in workspace/bin/ and run them from the host with bin/exec:

bin/exec migrate --fresh --seed
bin/exec deploy staging

The entrypoint adds /workspace/bin to PATH inside the container, so these scripts are callable directly during shell sessions too.

What Gets Auto-Installed

The entrypoint installs a few plugins on first boot. Superpowers for workflow skills like brainstorming, TDD, and debugging. Context7 for library docs lookup. And n8n-mcp-skills, because I use n8n heavily for automation. Plus GSD is installed globally. All of this persists in the Docker volume so subsequent starts skip the install.

Who Needs This

If you’re using Claude Code for quick one-off questions, you don’t need this. The Docker overhead isn’t worth it.

But if you’re running Claude Code as a real development tool, multi-file refactoring, dependency management, headless CI-adjacent workflows, the isolation is worth the five minutes of setup. Full speed of --dangerously-skip-permissions with the confidence that the worst case scenario is rebuilding a container, not restoring your machine from a backup.

Setup is git submodule add, bin/setup, bin/claude. Give it a go on a side project and see if it clicks.