No description
  • Shell 80.3%
  • PHP 10.1%
  • Go 9.6%
Find a file
2026-04-11 21:35:41 +02:00
.claude initial commit 2026-04-11 21:35:41 +02:00
cc initial commit 2026-04-11 21:35:41 +02:00
cc-cleanup initial commit 2026-04-11 21:35:41 +02:00
docker-compose.postgres.yml initial commit 2026-04-11 21:35:41 +02:00
docker-compose.yml initial commit 2026-04-11 21:35:41 +02:00
Dockerfile.go initial commit 2026-04-11 21:35:41 +02:00
Dockerfile.node initial commit 2026-04-11 21:35:41 +02:00
Dockerfile.php initial commit 2026-04-11 21:35:41 +02:00
entrypoint.sh initial commit 2026-04-11 21:35:41 +02:00
README.md initial commit 2026-04-11 21:35:41 +02:00

Claude Code Worktree Runner

Run Claude Code in --dangerously-skip-permissions mode inside a Docker container, against an isolated Git worktree of your project. Each feature branch gets its own worktree, container, and Postgres database.

Supports PHP (Symfony), Node.js, and Go projects.

Prerequisites

  • Docker with Compose v2 (docker compose)
  • Git
  • An active Claude Code login (claude CLI authenticated on the host)

Installation

  1. Clone or copy this directory somewhere permanent:
cp -r /path/to/docker ~/Work/docker
  1. Add the directory to your PATH, or symlink the scripts:
# Option A: add to PATH (in ~/.bashrc or ~/.zshrc)
export PATH="$HOME/Work/docker:$PATH"

# Option B: symlink into a directory already on PATH
ln -s ~/Work/docker/cc ~/.local/bin/cc
ln -s ~/Work/docker/cc-cleanup ~/.local/bin/cc-cleanup
  1. Build the Docker images (one-time, per language you use):
cd ~/Work/docker

# Build only what you need:
docker compose --profile php build
docker compose --profile node build
docker compose --profile go build

Rebuild after modifying a Dockerfile:

docker compose --profile php build --no-cache

Usage

Run from the root of any Git repository:

# Auto-detects language from project files (composer.json / package.json / go.mod)
cc feat/new-api

# Explicit language override
cc -l php feat/auth-rework

# Custom host port (default: 8000)
cc -p 8001 feat/second-feature

This will:

  1. Create a Git worktree at ../<project>.feat-new-api with a new branch feat/new-api
  2. Copy .env.local into the worktree (if present)
  3. Start the shared Postgres container (if not already running)
  4. Create a Postgres database named after the project and branch
  5. Start the language-appropriate container with:
    • Dependencies installed (composer install / npm install / go mod download)
    • Dev server running on :8000
    • Claude Code launched interactively

You'll be dropped directly into the Claude Code interface.

Dev servers

Language Server Bind address
PHP Symfony CLI (symfony server:start) 0.0.0.0:8000
Node npm run dev or npm start 0.0.0.0:8000 (via HOST env var)
Go air (if config exists) or go run . Application-defined

Note: Node and Go dev servers must be configured in your project to listen on 0.0.0.0:8000 for the port mapping to work from the host. The HOST=0.0.0.0 and PORT=8000 environment variables are set automatically, but not all frameworks read them. Check your framework's docs if the dev server is unreachable.

Running multiple worktrees simultaneously

Each worktree gets its own container and database. Use -p to avoid port collisions:

cc feat/api-v2                 # port 8000
cc -p 8001 feat/admin-panel    # port 8001

Environment variables

The following are available inside the container:

Variable Value
DATABASE_URL postgresql://claude:claude@cc-postgres:5432/<db_name>
CC_DB_NAME Database name (derived from project + branch)
CC_LANG php, node, or go
APP_ENV dev (PHP only)
PGPASSWORD claude
ANTHROPIC_API_KEY Passed through from host (if set)

Cleanup

Run from the same project directory where you ran cc:

cc-cleanup feat/new-api

This will:

  1. Drop the Postgres database for the branch
  2. Stop and remove the app container
  3. Remove the Git worktree
  4. Optionally delete the Git branch (prompts for confirmation)

Stopping the shared Postgres

Postgres runs independently and persists across worktrees. To stop it:

docker compose -f ~/Work/docker/docker-compose.postgres.yml down

To stop it and delete all data:

docker compose -f ~/Work/docker/docker-compose.postgres.yml down -v

Pruning the Go module cache

Go modules are cached in a Docker volume to avoid re-downloading. To clear it:

docker volume rm cc-gomod

File layout

~/Work/docker/
  cc                          Main script (add to PATH)
  cc-cleanup                  Cleanup script
  docker-compose.yml          App containers (profiles: php, node, go)
  docker-compose.postgres.yml Shared Postgres 17
  Dockerfile.php              PHP 8.5 + Symfony CLI + Composer
  Dockerfile.node             Node.js 24 LTS
  Dockerfile.go               Go 1.26 + air + golangci-lint
  entrypoint.sh               Shared container entrypoint

How it works

Host                                    Docker
----                                    ------
~/projects/myapp/                       
  |                                     cc-net (Docker network)
  |-- cc feat/xyz                       |
  |     |                               |-- cc-postgres (shared, persistent)
  |     |-- git worktree add            |     Postgres 17, volume: cc-pgdata
  |     |     ../myapp.feat-xyz         |
  |     |                               |-- myapp-feat-xyz-php (per worktree)
  |     |-- docker compose run          |     /app -> ../myapp.feat-xyz
  |     |     php                       |     ~/.claude mounted
  |     |                               |     Dev server on :8000
  |     +-- Claude Code session         |     Claude Code (interactive)
  |                                     |
  ~/projects/myapp.feat-xyz/            |-- myapp-feat-xyz-go (another worktree)
     (git worktree)                     |     ...

Troubleshooting

Port already in use: Use -p to pick a different port, or check what's running with ss -tlnp | grep :8000.

Postgres not starting: Check if another Postgres is running on the host: ss -tlnp | grep :5432. The shared Postgres container does not bind to the host network, so this should not conflict unless the Docker network has issues. Run docker logs cc-postgres to inspect.

Dev server unreachable from host: The server inside the container must listen on 0.0.0.0, not 127.0.0.1. Configure your framework accordingly.

File permission errors: The container user's UID/GID is matched to your host user at build time. If you change host users, rebuild the images.

Claude Code authentication: Auth tokens are mounted from ~/.claude on the host. If you see login prompts, run claude on the host first to authenticate. Alternatively, set ANTHROPIC_API_KEY in your shell environment.