Receber por email
← Voltar para o catálogo

sandboxed-claude

Create a Podman dev container that runs Claude Code inside a sandboxed environment. Use when setting up a containerized development environment for any project, when the user asks about running Claude in a container, wants to isolate Claude's filesystem access, or needs a reproducible dev setup with Podman. Also use when the user mentions dev containers, Containerfiles, or sandboxed development wo

0estrelas
Atualizado há 6 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add bensimpson-ch/claude-skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/sandboxed-claude/svg)](https://www.skillteca.com.br/skills/sandboxed-claude)
#ai

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Sandboxed Claude

Create a Podman dev container where Claude Code runs inside a controlled, reproducible environment. The container bind-mounts the project source, caches dependencies in named volumes, and persists Claude's own configuration across restarts. One script launches the whole thing.

See [reference.md](reference.md) for annotated Containerfile and dev.sh templates.

Why Sandbox

Running Claude Code inside a container gives you three things:

  1. Reproducibility. Every collaborator gets the same toolchain -- same Node, same JDK, same

Maven -- without polluting their host. No "works on my machine."

  1. Isolation. Claude operates within the container's filesystem boundaries. It can read and

write the project (bind-mounted) but nothing else on the host.

  1. Speed. Named Podman volumes store dependency trees (node_modules, .m2/repository) as

Linux-native filesystems, avoiding the overhead of macOS filesystem translation on every file read.

The Two-File Pattern

Every sandboxed-claude setup produces exactly two files:

infra/devcontainer/
├── Containerfile   # Image definition: base + runtimes + tools + non-root user
└── dev.sh          # Launch script: volumes, mounts, container lifecycle

The Containerfile builds once and is reused. dev.sh handles everything else: creating volumes, building the image on first run, tearing down stale containers, and starting a fresh interactive session.

Workflow

1. Detect the Tech Stack

Read the project to identify what runtimes and tools are needed:

| Signal | Runtime to Install | |--------|--------------------| | package.json | Node.js (check engines field or .nvmrc for version) | | pom.xml | Java JDK + Maven | | build.gradle / build.gradle.kts | Java JDK + Gradle | | go.mod | Go | | Cargo.toml | Rust toolchain | | requirements.txt / pyproject.toml | Python | | angular.json | Node.js + Angular CLI (match project version from devDependencies) |

Most projects need one or two runtimes. A fullstack app typically needs Node + a backend runtime.

2. Choose the Base Image

Pick the base that gives you the most for free:

| Primary Runtime | Base Image | Why | |-----------------|------------|-----| | Node.js | node:22-bookworm | Node pre-installed, Debian for easy apt-get of other tools | | Python | python:3.12-bookworm | Python pre-installed, Debian base | | Go | golang:1.22-bookworm | Go pre-installed, Debian base | | Java only | eclipse-temurin:21-jdk-bookworm | JDK pre-installed | | Rust | rust:1.78-bookworm | Rust toolchain pre-installed |

Use -bookworm (Debian 12) variants. They have apt-get for installing additional tools. Alpine images are smaller but cause friction with native dependencies and missing shared libraries.

3. Write the Containerfile

The Containerfile follows a fixed structure. Each section has a clear purpose:

Base image (primary runtime)
  → System dependencies (curl, git, ssh, ca-certificates, jq)
  → Secondary runtimes (JDK, Maven, etc.)
  → CLI tools (Angular CLI, Claude Code)
  → Non-root user setup
  → Working directory + config directories

Principles:

  • Pin versions. Use build ARGs for runtime versions so they're visible and changeable at

the top of the file. Pin CLI tools to the version matching the project.

  • Clean apt caches. End every apt-get install with && rm -rf /var/lib/apt/lists/* to

keep the image small.

  • Non-root user. Create a dev user and switch to it before setting up workspace directories.

Claude Code should never run as root inside the container.

  • Prepare mount points. Create /home/dev/.claude and /home/dev/.ssh (if needed) with

correct permissions before the user runs anything.

4. Write dev.sh

dev.sh is the single entry point. It handles the full container lifecycle:

#!/usr/bin/env bash
set -euo pipefail

The script does five things in order:

  1. Resolve paths. Compute PROJECT_ROOT relative to the script location so it works from

any working directory.

  1. Create named volumes. Use podman volume exists || podman volume create for each

dependency cache. Named volumes are Linux-native filesystems inside the Podman VM -- they bypass macOS filesystem translation entirely.

  1. Build the image. Only if it doesn't already exist (podman image exists). Rebuilding

is explicit: the user deletes the image when they want a fresh build.

  1. Remove stale container. podman rm -f the previous container if it exists. Containers

are ephemeral; volumes persist the state that matters.

  1. Launch. podman run -it with all mounts and flags.

5. Configure Mounts and Volumes

This is where the decisions matter. There are three categories:

Bind mounts (source code):

-v "$PROJECT_ROOT:/workspace:z"

The entire project tree, read-write. The :z suffix is required for SELinux relabeling on Podman (harmless on systems without SELinux).

Named volumes (dependency caches):

-v "myproject-node-modules:/workspace/app/node_modules:z"
-v "myproject-m2-repo:/home/dev/.m2/repository:z"

Each dependency tree gets its own named volume. This serves two purposes: dependencies install fast (native filesystem, not macOS FUSE), and they persist across container restarts without re-downloading.

Mount the volume at the exact path where the package manager writes dependencies:

  • npm/pnpm: <project>/node_modules
  • Maven: ~/.m2/repository
  • Gradle: ~/.gradle/caches
  • Go: /home/dev/go/pkg/mod
  • Cargo: /home/dev/.cargo/registry
  • pip: varies (use a venv path)

Claude config (persistence):

-v "$HOME/.claude-container/myproject:/home/dev/.claude:z"

Store Claude's auth tokens, settings, and conversation history in a host directory. This survives container rebuilds. Keep it per-project under ~/.claude-container/ so different projects don't collide.

6. Essential Flags

podman run -it \
    --name myproject-dev \
    --hostname myproject-dev \
    --userns keep-id \
    ...
  • --userns keep-id: Maps the container's dev user to your host UID. Without this, files

created inside the container are owned by a different UID on the host, causing permission headaches. Required on macOS.

  • --hostname: Sets a recognizable prompt inside the container.
  • --name: Allows podman rm -f by name on next launch.

7. Optional: SSH Key Mounting

If the project deploys via SSH or needs git access over SSH:

-v "$HOME/.ssh/id_ed25519_myproject:/home/dev/.ssh/id_ed25519:ro,z"
-e "SSH_KEY=/home/dev/.ssh/id_ed25519"

Mount the key read-only (:ro). If the project deploys through CI/CD (GitHub Actions, etc.), skip this entirely.

8. Print First-Run Instructions

dev.sh should print what the user needs to do on first launch:

First run: execute inside the container:
  cd /workspace/app && npm ci
  cd /workspace/services && mvn dependency:go-offline
  claude auth login

These commands populate the named volumes. After the first run, subsequent launches are instant.

Adaptation Checklist

When creating a sandboxed-claude setup for a new project:

  • [ ] Read package.json / pom.xml / go.mod to identify runtimes and versions
  • [ ] Choose base image matching the primary runtime
  • [ ] Pin CLI tool versions to match the project (e.g., Angular CLI from devDependencies)
  • [ ] Create one named volume per dependency cache
  • [ ] Mount node_modules at the exact path (watch for monorepo structures)
  • [ ] Set --userns keep-id for macOS compatibility
  • [ ] Include claude auth login in first-run instructions
  • [ ] Test: build the image, launch, run npm ci / mvn compile, verify Claude Code works

What This Skill Does Not Cover

  • Production containers. This skill is about dev environments. Production Dockerfiles are

multi-stage builds optimized for size; dev containers are optimized for tooling.

  • Docker Compose for services. If the projec
Compartilhar X LinkedIn