Skip to content

Latest commit

 

History

History
75 lines (50 loc) · 4.55 KB

File metadata and controls

75 lines (50 loc) · 4.55 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What This Project Is

dev-agent is a containerized environment for running AI coding agents (Claude Code or OpenCode) with enforced network isolation. A Squid proxy allowlists specific domains; an iptables firewall inside each agent container blocks all direct internet access, forcing traffic through the proxy.

Architecture

Three Docker Compose services on a shared bridge network (agent-net):

  • proxy (always runs) — Squid forward proxy. Permits HTTP/HTTPS only to domains in allowed-domains.txt. No caching. Uses Docker's embedded DNS at 127.0.0.11.
  • agent (profile: claude) — Claude Code on Node.js 24. Authenticates via AWS Bedrock. Settings mounted from dot-claude/settings.json.
  • opencode (profile: opencode) — OpenCode on Node.js 24. Authenticates via OpenRouter API key. Config mounted from dot-opencode/opencode.json.

run.sh is the sole entry point. It:

  1. Parses CLI flags and resolves the workspace directory
  2. Reads optional .dev-agent/config.yml from the workspace (requires yq on the host) and generates temporary Docker Compose override files in /tmp/dev-agent-<dirname>/
  3. Detects git worktrees and generates a volume mount override for the main .git directory
  4. Stacks all override files via -f flags, with the workspace's own docker-compose.override.yml applied last
  5. Starts background services (docker compose up -d), then runs the agent interactively (docker compose run --rm)
  6. Cleans up containers and temp files on exit via a trap

Each workspace gets an isolated instance named dev-agent-<dirname>, enabling multiple agents to run simultaneously against different projects.

Container Startup Sequence

entrypoint.shsudo init-firewall.shexec "$@" (agent binary)

The firewall script preserves Docker DNS NAT rules, allows traffic to all attached Docker bridge subnets (auto-detected from interfaces), then rejects everything else. It verifies both that direct access is blocked and that proxy access works before handing off to the agent.

Workspace Configuration

Projects can add .dev-agent/config.yml (extra domains, env vars, volumes, external networks) and .dev-agent/docker-compose.override.yml (sidecar services like databases). See example.dev-agent/ for the format.

Building and Running

# Build images and launch Claude Code against a project
./run.sh --build ~/projects/my-app

# Launch OpenCode instead
OPENROUTER_API_KEY=sk-or-... ./run.sh --opencode --build ~/projects/my-app

# Drop into a shell inside the agent container
./run.sh --shell ~/projects/my-app

# Stop containers for a specific project
./run.sh --down ~/projects/my-app

# Hot-reload the Squid domain allowlist after editing allowed-domains.txt
./run.sh --reload-proxy

Rebuild individual services with Docker Compose directly:

docker compose -p dev-agent-my-app --profile claude build agent
docker compose -p dev-agent-my-app --profile opencode build opencode

There are no tests, linters, or CI pipelines in this project.

Key Conventions

  • Bash scripts use set -euo pipefail, quoted variable expansion, and color-coded output (GREEN/YELLOW/RED).
  • Dockerfiles are named <service>.Dockerfile. Both agent images share the same base toolchain (Node.js 24, .NET 8+10, PowerShell 7.4, AWS CLI v2, ripgrep, gh, etc.) and differ only in which agent binary is installed and the CMD.
  • run.sh generates temporary files in /tmp/dev-agent-<dirname>/ — domain merges, compose overrides, worktree mounts. These are always cleaned up on exit.
  • The proxy service has no profiles key so it starts unconditionally. Agent services use profiles to ensure only one runs per instance.
  • Domain entries in allowed-domains.txt use Squid's dstdomain format: a leading dot (.example.com) matches all subdomains.
  • The dot-claude/ and dot-opencode/ directories contain agent configuration files that are bind-mounted into the respective containers. These are not the same as the .claude/ directory (which holds this repo's own Claude Code settings).

Important: run.sh Service Name Variable

Throughout run.sh, the variable $AGENT_SERVICE holds the Docker Compose service name (agent for Claude Code, opencode for OpenCode). When modifying run.sh, use this variable instead of hardcoding service names — it appears in the workspace config override generator, the worktree override heredoc, the background service filter, and the interactive docker compose run commands.