Restricted Docker images for running command line interface (coding) agents in hardened containerised environments.
Full documentation: https://docs-agent-containers.anirbanbasu.com/ (or browse docs/ in this repository, starting at docs/index.md).
claude-code— hardened container for running the Claude Code CLI: non-root user, read-only root filesystem, minimal capability set, egress denied by default. Seedocs/container-images/claude-code.md.adal— hardened container for AdaL, SylphAI's terminal coding agent, including browser-based sign-in and persistent session/MCP state. Seedocs/container-images/adal.md.aider— hardened container for Aider, the git-native terminal pair-programming agent. Seedocs/container-images/aider.md.codex— hardened container for the OpenAI Codex CLI, including API-key and device-login workflows. Seedocs/container-images/codex.md.hermes— hardened container for running Hermes Agent, Nous Research's multi-provider agentic CLI, with the same network-containment posture asclaude-code. Seedocs/container-images/hermes.md.kilo-code— hardened container for Kilo CLI, the open-source, provider-neutral terminal coding agent. Seedocs/container-images/kilo-code.md.opencode— hardened container for the provider-agnostic OpenCode terminal coding agent. Seedocs/container-images/opencode.md.qwen-code— hardened container for Qwen Code, the open-source terminal coding agent. Seedocs/container-images/qwen-code.md.agent-gateway— a disposable sibling container that a workload such asadal,aider,claude-code,codex,hermes,kilo-code,opencode, orqwen-codecan tunnel all its egress through over SSH, so egress enforcement lives outside the workload container entirely. Seedocs/container-images/00-agent-gateway.md.volume-bridge— a loopback-only, read-only WebDAV sidecar that exposes selected named agent-home volumes to host tools without granting them Docker access. Seedocs/container-images/01-volume-bridge.md.
Build and run the claude-code image from agent-images/claude-code/Dockerfile. The build needs agent-images/shared supplied as a named build context, since the image pulls a shared egress-allowlist script from it:
docker build --build-context shared=agent-images/shared \
-t claude-code agent-images/claude-code
docker run -it --rm \
--security-opt=no-new-privileges \
--read-only \
--tmpfs /tmp \
--tmpfs /run \
--cap-drop=ALL --cap-add=NET_ADMIN --cap-add=NET_RAW --cap-add=SETUID --cap-add=SETGID \
-v claude-home:/home/claude \
-v "$PWD":"/workspace/$(basename "$PWD")" \
-w "/workspace/$(basename "$PWD")" \
claude-code/home/claude is mounted from a named volume (claude-home) so plugins, settings, Claude's own project memory, and any Python/Node package state persist across container runs; each project is mounted under its own /workspace/<project_name> subdirectory to keep per-project state distinct within that shared volume. See docs/container-images/claude-code.md for the full flag-by-flag rationale, runtime package installation, plugin/model/egress configuration, and the opt-in agent-gateway tunnelling mode.
The build above defaults to UID/GID 1000:1000; if that doesn't match your host account, files the agent writes to the bind-mounted project directory or claude-home won't be owned by you on the host. Add --build-arg UID=$(id -u) --build-arg GID=$(id -g) to the docker build command to fix that — every workload image's Dockerfile supports it and only rebuilds a small final stage per UID, not the whole image. See each image's own docs page (e.g. docs/container-images/claude-code.md#matching-your-host-users-uidgid) for details.
With a running Docker daemon, run the local test matrix with:
just test-imagesIt syntax-checks the shell scripts, builds every image, smoke-tests the
documented hardened runtime profile, and verifies deny-by-default and
allowlisted egress against throwaway HTTP servers on an isolated Docker
network. It requires no agent credentials or public test endpoint. The
gateway end-to-end test is available separately via just test-images-gateway.