Skip to content

container config

github-actions[bot] edited this page Aug 12, 2026 · 4 revisions

Advanced: how the container is configured

Each environment is a Docker container that Forge Fleet assembles from your ffleet.toml and flags. This page explains the pieces so you can tune them.

Image

image (or --image) selects the Docker image the agent runs in. Default: ghcr.io/grzegorz-aniol/forge-fleet-python:latest (pulled from GHCR on first use — no local build required). A Go-dev variant (ghcr.io/grzegorz-aniol/forge-fleet-go:latest, also published to GHCR) overlays a Go toolchain for developing the Go port. Pick or build an image that carries the language runtimes and tools your project needs — the agent can only use what's in the image (plus what it installs at runtime).

Because image is a config-derived setting, you can change it and pick it up on the next revive: ffleet stop SLUG then ffleet up SLUG (see what can change mid-life).

How the published images are built

The two default images are built and pushed to GHCR from the public ffleet-dist repo (its publish-images workflow), where the Dockerfiles live:

  • ghcr.io/grzegorz-aniol/forge-fleet-python:latest — the base image (Debian bookworm-slim). It carries the agent toolbox: the Claude Code and Codex CLIs, Python 3 + uv, Node 22 (with corepack for pnpm/yarn), plus git, gh (GitHub CLI), the docker CLI (client only, for DooD), tmux, jq, make, and a C build toolchain.
  • ghcr.io/grzegorz-aniol/forge-fleet-go:latest — a superset overlay of the base that adds the Go toolchain (for developing the Go port); the rest of the toolbox is identical.

Both run as a non-root user buddy (uid/gid 1000) with home /home/buddy, and /workspace is owned by buddy. That is why credential and cache mounts land under /home/buddy/... (e.g. ~/.claude/home/buddy/.claude), why extra_mounts into the container home use that path, and why host Docker access adds buddy to the host docker group so it can reach the socket (see DooD). If you build a custom image, matching the buddy uid/gid 1000 keeps mounted-file ownership aligned with your host user.

Volumes & mounts

Several things get mounted into the container:

  • The workspace — the git worktree (or, in --here/off mode, your current directory) is mounted at /workspace. This is where the agent does its work.
  • uv_cache_dir — a shared uv cache (default ~/.cache/uv) for faster Python installs across environments.
  • extra_mounts — your own bind mounts, source:target[:ro|:rw] (the only accepted modes are ro and rw, default read-write); target is an absolute container path, a relative source resolves against the repo root, ~ expands to the host home. Use these for shared caches, SSH keys, etc. See secrets for when to mount vs. copy vs. env-file.

Credential directories — authenticating the agent inside

The agent must be logged in inside the container. Forge Fleet handles this by mounting the agent's host credential/config directory:

  • Claude Code[claude].dir (default ~/.claude), plus a credential auth source (auto / keychain / token / api-key / credentials-file / external) that decides which credential ffleet injects. See the [claude].auth table.
  • Codex[codex].dir (default ~/.codex).

Override the mounts per run with --claude-dir / --codex-dir, and the Claude source with --claude-auth. The upshot: because your host login is mounted in, you don't re-authenticate per environment.

extra_hosts

extra_hosts maps hostnames to addresses via docker run --add-host, letting processes inside resolve names to the host or to arbitrary addresses. Each entry is host:address; the special value host-gateway resolves to the host itself — handy for reaching a service running on your machine:

extra_hosts = ["host.docker.internal:host-gateway"]

Host Docker access

docker_host_bind = true (or --docker-host-bind) binds the host Docker socket so the agent can drive the host daemon — this is the Docker-outside-Docker setup; see DooD.

Git identity

Commits made inside the container use the [git] identity (user_name / user_email) if both are set; otherwise identity falls back to your host git config. Set both together or neither.

Putting it together

image = "ghcr.io/grzegorz-aniol/forge-fleet-python:latest"
uv_cache_dir = "~/.cache/uv"
extra_mounts = ["~/.ssh:/home/buddy/.ssh"]
extra_hosts  = ["host.docker.internal:host-gateway"]

[claude]
dir  = "~/.claude"
# auth = "auto"

[git]
user_name  = "Jane Developer"
user_email = "jane@example.com"

Related

Clone this wiki locally