New 🐳 Now also supports Docker — Podman or Docker, your choice
Open Source · Built with Rust

Claude Code,
containerized & safe

ai-pod runs Claude Code inside isolated containers (Podman or Docker) so your AI has exactly the tools it needs — and nothing it shouldn't touch.

Get started View on GitHub
$ curl -fsSL https://raw.githubusercontent.com/mismosmi/ai-pod/main/install.sh | bash

Everything Claude needs.
Nothing you don't want it to have.

Each workspace gets its own container with full isolation, persistent state, and fine-grained host access — all managed automatically.

📦

Per-workspace isolation

Every directory gets a dedicated container (Podman or Docker), named by a hash of its path. Projects can't interfere with each other.

💾

Persistent Claude state

A named volume preserves ~/.claude across sessions — your login, memory, settings, and conversation history survive container restarts.

🔐

Credential scanning

Before mounting your workspace, ai-pod scans for secrets and credential files and prompts you to review or abort — keeping sensitive data out of the container.

🐳

Custom Dockerfiles per project

Add an ai-pod.Dockerfile to any project, starting from any base image. Node, Python, Rust, Playwright — whatever your project needs.

⚙️

Settings & CLAUDE.md merging

Your host ~/.claude/settings.json and CLAUDE.md are merged with container defaults at launch, so your personal Claude preferences follow you everywhere.

🖥️

Host command execution

The bundled host-tools binary lets Claude run commands on the host machine. Every command requires your explicit approval — with a persistent allowlist for trusted ones.

🔔

Desktop notifications

When a Claude session ends, ai-pod sends a native desktop notification to the host so you know exactly when to come back.

🌐

Transparent host networking

Containers reach host services at host.containers.internal (Podman) or host.docker.internal (Docker), so Claude can hit your local dev server, database, or API without any manual port mapping.

🔄

Auto-update checks

ai-pod silently checks for new releases on startup and lets you know when there's a newer version available — no manual polling needed.

Background daemon management

Claude can start long-running processes on the host — dev servers, file watchers, build pipelines — and track them by ID. Daemons are stopped automatically when the session ends.


From zero to Claude in a container

Four steps. Two commands. One minute from install to your first session.

Install ai-pod

You'll need Podman or Docker already installed. Then grab ai-pod with the one-line install script at the top of this page.

Create a project Dockerfile

cd into your project and run ai-pod init. This drops an ai-pod.Dockerfile in the workspace that you can edit — pick your base image, install the tools Claude should have, and add any MCP servers. See the example in Usage.

Launch the container

Run ai-pod. It scans the workspace for credentials, builds the image, starts the shared background server, and drops you into a Claude Code session inside the container. The first run takes a minute; later runs are instant unless the Dockerfile changed.

Come back any time

Next time, just run ai-pod again from the same directory. Use ai-pod run claude resume to pick up your last session, or ai-pod run bash to poke around inside the container.


Zero config to get started

ai-pod handles container lifecycle, image building, server management, and credential checking automatically. You just run it.

Scan for credentials

The workspace is scanned for secrets before anything is mounted into a container.

Build the image

Your ai-pod.Dockerfile is used to build a project-specific image. Rebuilt only when the file changes.

Start the shared server

A lightweight background server starts on the host, bridging host-interaction requests from all containers.

Launch the container

Your workspace is mounted, settings are injected, and Claude Code starts inside the isolated container.


Simple CLI, powerful options

One command to launch. A handful more for everything else.

Common commands
# Launch Claude in current directory
ai-pod

# Launch in a specific directory
ai-pod --workdir /path/to/project

# Force rebuild the container image
ai-pod --rebuild

# Resume the last Claude session
ai-pod run claude resume

# Open a shell in the container
ai-pod run bash
Project setup & management
# Create a custom Dockerfile
ai-pod init

# Build image without launching
ai-pod build

# List all Claude containers
ai-pod list

# Remove container for current workspace
ai-pod clean

# Skip credential scan
ai-pod --no-credential-check
host-tools (inside container)
# Run a command on the host
host-tools run-command ls ~/Desktop

# Open a URL in the host browser
host-tools run-command open https://example.com

# List previously approved commands
host-tools run-command --list

# Send a desktop notification
host-tools notify-user "Build finished"
Daemon management (inside container)
# Start a background process, get its ID
host-tools daemon start npm run dev
  → a3f91c820b4e

# Stream its output (follows until exit)
host-tools daemon output a3f91c820b4e

# Check status and exit code
host-tools daemon status a3f91c820b4e

# List all daemons for this project
host-tools daemon list

# Stop one or all daemons
host-tools daemon stop a3f91c820b4e
host-tools daemon stop-all
ai-pod.Dockerfile example
# Start from any base image you need
FROM node:22

# Add Playwright for browser testing
RUN npx playwright install --with-deps

# Install a project-specific MCP server
RUN npm install -g @my-org/mcp-server

Safe by default

ai-pod is built around the assumption that you shouldn't have to fully trust the AI with your whole machine. Defense-in-depth, not just a checkbox.

  • Credential scanning before mount Detects .env files, API keys, SSH keys, and other secrets in your workspace before they reach the container.
  • Explicit host command approval Claude can only run host commands that you have explicitly approved. A persistent allowlist means you only say yes once per command.
  • Container-level isolation Each project lives in its own container. Compromised dependencies in one project can't reach another.
  • Symlink trick for .env files Move secrets outside the workspace and symlink them back. The container never sees them; your app still works.
  • Rootless containers Works with Podman's rootless mode out of the box, and supports Docker too. Keeps the blast radius small even if something goes wrong.

When something goes wrong

Known issues and how to work around them. If you hit something that isn't here, open an issue on GitHub.

🔑

Permission denied on workspace files

Your workspace is bind-mounted into the container at /app. The claude user inside the container has its own uid, and if that uid doesn't line up with the host uid that owns the files, Claude can't write to /app — or new files end up with an owner you can't edit on the host.

There are three independent knobs for fixing this. Pick the one that matches where you want the fix to live: per-project, per-run, or globally.

1. Pin the uid in your Dockerfile

Pass -u <uid> to useradd so the claude user is built with a specific uid instead of the distro default. Check your host uid first with id -u. Most surgical fix — stays inside the one project.

ai-pod.Dockerfile
RUN useradd -u 1000 -ms /bin/bash claude \
    && chown -R claude /app

2. Set PODMAN_USERNS globally

PODMAN_USERNS is a standard Podman environment variable. When set, it becomes the --userns value for every podman run — including the ones ai-pod makes. Use this to configure user namespace mapping across every project.

~/.bashrc or ~/.zshrc
export PODMAN_USERNS=keep-id:uid=1000,gid=1000

Debugging uid mismatches

To see exactly where the mismatch is, compare the host view and the container view:

Diagnose
# On the host
id -u                     # your host uid
ls -ln ai-pod.Dockerfile  # numeric owner of your files

# Inside the container
ai-pod run bash
id                        # uid/gid of the claude user
ls -ln /app               # what the container sees as owner

If the uid from id inside the container doesn't match the numeric owner of /app, that's the gap — apply one of the three fixes above.


One line to install

Works on Linux and macOS. Requires Podman or Docker.

$ curl -fsSL https://raw.githubusercontent.com/mismosmi/ai-pod/main/install.sh | bash
View on GitHub Releases