agentsclimarketplace

Sandboxed claude

Skill bensimpson-ch/claude-skills/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 workflows.From its SKILL.md

Install
npx -y skills add bensimpson-ch/claude-skills --skill sandboxed-claude

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

8.7 KB, ~2.0k tokens by cl100k_base, as published. Nobody here has run it

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 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."
  2. Isolation. Claude operates within the container's filesystem boundaries. It can read and write the project (bind-mounted) but nothing else on the host.
  3. 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:

SignalRuntime to Install
package.jsonNode.js (check engines field or .nvmrc for version)
pom.xmlJava JDK + Maven
build.gradle / build.gradle.ktsJava JDK + Gradle
go.modGo
Cargo.tomlRust toolchain
requirements.txt / pyproject.tomlPython
angular.jsonNode.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 RuntimeBase ImageWhy
Node.jsnode:22-bookwormNode pre-installed, Debian for easy apt-get of other tools
Pythonpython:3.12-bookwormPython pre-installed, Debian base
Gogolang:1.22-bookwormGo pre-installed, Debian base
Java onlyeclipse-temurin:21-jdk-bookwormJDK pre-installed
Rustrust:1.78-bookwormRust 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.
  2. 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.
  3. 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.
  4. Remove stale container. podman rm -f the previous container if it exists. Containers are ephemeral; volumes persist the state that matters.
  5. 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 project needs a database or message broker alongside the dev container, that's a separate compose file. The dev container is for the human (and Claude) to write code in.
  • VS Code devcontainers. The .devcontainer/devcontainer.json format is IDE-specific. This skill produces standalone Podman containers that work from any terminal.

What ships with it: 1 file

8.0 KB alongside SKILL.md

Keep looking

Skills are one crate of 326,537. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.