Back Original

Running Claude Code dangerously (safely)

I’ve been using Claude Code more and more recently. At some point I realized that rather than do something else until it finishes, I would constantly check on it to see if it was asking for yet another permission, which felt like it was missing the point of having an agent do stuff. So I wanted to use Claude Code with the --dangerously-skip-permissions flag.

If you haven’t used it, this flag does exactly what it says: it lets Claude Code do whatever it wants without asking permission first. No more “May I install this package?”, “Should I modify this config?”, “Can I delete these files?”

It just… does it.

Which is great for flow since I don’t have to worry that it stopped doing stuff just to ask a permission question.

But also, you know, dangerous.

I like my filesystem intact, so the obvious solution is to not run this thing directly on my OS account.

Docker

First instinct: throw it in a Docker container. Containers are for isolation, right?

Except I want Claude to be able to build Docker images. And run containers. And maybe orchestrate some stuff.

So now you need Docker-in-Docker, which means --privileged mode, which defeats the entire purpose of sandboxing. That means trading “Claude might mess up my filesystem” for “Claude has root-level access to my container runtime.”

Not great.

There’s also the nested networking weirdness, volume mounting permissions that make you question your life choices, and the general feeling that you’re fighting the tool instead of using it.

Other options

I also briefly considered:

Then I remembered about a project that I’ve used before Docker became all the rage: Vagrant.

If you weren’t around back then, Vagrant gives you proper VM isolation with a reproducible config file. It’s basically infrastructure as code for your local dev environment.

You get:

I hadn’t used VirtualBox in years since Docker containers covered all requirements until now, so I grabbed the latest version (7.2.4) and got started.

First vagrant up and… the VM is pegging my CPU at 100%+ while completely idle.

I spent an hour turning off various VM features, tweaking settings, googling asking LLMs random combinations of “virtualbox high cpu idle”, you know, the usual.

Eventually I found this GitHub issue. VirtualBox 7.2.4 shipped with a regression that causes high CPU usage on idle guests. What are the odds.

Vagrantfile

Here’s what my simple Vagrantfile looks like:

vm_name = File.basename(Dir.getwd)

Vagrant.configure("2") do |config|
  config.vm.box = "bento/ubuntu-24.04"

  #config.vm.network "forwarded_port", guest: 3000, host: 3000, auto_correct: true
  config.vm.synced_folder ".", "/agent-workspace", type: "virtualbox"

  config.vm.provider "virtualbox" do |vb|
    vb.memory = "4096"
    vb.cpus = 2
    vb.gui = false
    vb.name = vm_name
    vb.customize ["modifyvm", :id, "--audio", "none"]
    vb.customize ["modifyvm", :id, "--usb", "off"]
  end
  
  config.vm.provision "shell", inline: <<-SHELL
    export DEBIAN_FRONTEND=noninteractive

    apt-get update
    apt-get install -y docker.io nodejs npm git unzip
    npm install -g @anthropic-ai/claude-code --no-audit

    usermod -aG docker vagrant
    chown -R vagrant:vagrant /agent-workspace

  SHELL
end

Now I just run:

cd ~/my-project
vagrant up
vagrant ssh
claude --dangerously-skip-permissions
# tell Claude what you want and let it run wild with no babysitting

First boot takes a few minutes to provision everything, and you need to sign in to Claude once for each project, but after that, vagrant up is quite fast.

Then, when you are done for the day:

So, what can Claude do with these newfound powers?

Since it’s running in a VM, I also gave it sudo access and instructed it that it has the power to do anything: install system packages, modify configs, create files, run Docker containers, whatever.

It has:

All things I’d be nervous about on my host machine, especially with the “just do it” flag enabled.

And now I feel Claude is much more effective since it has the extra context, it’s not relying on me to run the command, return the output or error message, and then iterate. It just does it by itself.

Claude Code isn’t exactly a resource hog, and the VM has plenty of headroom. The shared folder sync works fine, no lag or weirdness when files change. This is under Linux with VirtualBox, YMMV for other platforms.

What you’re protecting against:

What you’re NOT protecting against:

Threat model: I don’t trust myself to always catch what the agent is doing when I’m in the zone and just want stuff to work. This setup is about preventing accidents, not sophisticated attacks.

Since all my projects are in git I don’t care if it messes something up in the project. Plus you get the benefit of being able to use your regular git tooling/flows/whatever, without having to add credentials to the VM.

But if you need something stricter, config.vm.synced_folder also supports type: "rsync", one-time one-way sync from the machine running to the machine being started by Vagrant, but then it’s on you to sync it back or whatever is needed.

This took a bit to get right, mostly because of the VirtualBox CPU bug. But now it’s frictionless. I can let Claude Code do whatever it wants without fear, and if something goes sideways, I just nuke the VM and start fresh.

The Vagrantfile is short and reproducible. Drop it in any project directory, vagrant up, and you’re sandboxed.

If you’re using Claude Code with the dangerous flag, I’d recommend something like this. Even if you’re careful about what you approve, it only takes one moment to mess things up.