goga build
Execute a build plan via ralphex inside a Docker container.
Synopsis
goga build PLAN [OPTIONS]
Description
goga build launches the goga build pipeline for a given plan file. It prepares the environment, validates preconditions, and delegates execution to ralphex running inside a Docker container with the goga in-container process as the entry point.
The build pipeline performs these steps:
- Docker check -- Verifies Docker is installed and accessible.
- Config loading -- Reads
.goga/config.ymlfor build settings. - Uncommitted manifest check -- Scans
git statusfor uncommittedCODEMANIFESTfiles (can be skipped). - Agent preconditions -- Sets up agent-specific files (e.g.,
.claude/settings.json,.ralphex/claude-wrapper.shfor Claude). - Defaults copy -- Copies default prompts and agent configurations to
.ralphex/. - Image refresh (optional) -- When
--update/-uis set, the image is refreshed: if a top-leveldockerfileis declared in.goga/config.yml,docker buildruns against it (build failure is fatal — exit 1); otherwisedocker pullruns (a pull failure is logged as a warning and the build proceeds with the locally available image). By default no refresh happens and the local image is used as-is. - Docker execution -- Launches the ralphex command inside the configured Docker image. Credential files for claude, codex, and opencode are detected on the host and bind-mounted read-only into the container automatically (no flag).
Arguments
| Argument | Description |
|---|---|
PLAN |
Path to the build plan file (required). |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--dry-run |
flag | off | Print the assembled command without executing |
--worktree |
flag | off | Enable ralphex worktree mode |
--skip-finalize |
flag | off | Skip finalization step |
--skip-manifest-check |
flag | off | Skip check for uncommitted CODEMANIFEST files |
--session-timeout |
string | config | Session timeout duration |
--idle-timeout |
string | config | Idle timeout duration |
--wait |
string | config | Wait time before starting |
--max-iterations |
int | config | Maximum number of build iterations |
--review-patience |
int | config | Review patience count |
-e, --env |
string | -- | Additional environment variable (KEY=VALUE, repeatable) |
--proxy |
string | config | HTTP/HTTPS proxy URL; overrides build.proxy. Adds HTTP_PROXY/HTTPS_PROXY/NO_PROXY=localhost,127.0.0.1 to the container env-file |
--add-host |
string (repeatable) | -- | Add a docker run --add-host HOST:IP entry; merges on top of build.hosts (CLI wins on key conflict) |
--update, -u |
flag | off | Refresh the image before launch (build if a project Dockerfile is declared, else pull). Default skips the refresh |
-c, --clean |
flag | off | Wipe the persistent ralphex runtime host directory before launch (default preserves state across runs) |
Timeout and iteration options fall back to values in .goga/config.yml when not provided on the command line.
Proxy and hosts
--proxy URL (and build.proxy in .goga/config.yml) route the container's traffic through a corporate proxy. When a proxy is resolved, three variables are written to the container env-file:
| Variable | Value |
|---|---|
HTTP_PROXY |
the resolved proxy URL |
HTTPS_PROXY |
the resolved proxy URL |
NO_PROXY |
localhost,127.0.0.1 (fixed; cannot be overridden) |
--add-host HOST:IP (and build.hosts in .goga/config.yml) translate to docker run --add-host HOST:IP flags. CLI entries are merged on top of config; on host-key conflict, the CLI entry wins. Format is split on the first colon only — Docker reports malformed entries itself.
Credential mounts
Credential files for the supported AI agents are detected on the host and bind-mounted read-only into the container automatically (no flag): claude (~/.claude/.credentials.json), codex (~/.codex/auth.json), and opencode (~/.local/share/opencode/auth.json). Detection is agent-agnostic — it is not filtered by the configured task_executor.agent — and only files that exist are mounted. When none exist, no credential mount is added.
Ralphex runtime isolation
ralphex writes its persistent state to a .ralphex/ directory it auto-detects in its working directory. Rather than letting that state accumulate inside your project directory, goga build bind-mounts a centralized host directory over /workspace/.ralphex, so the bytes physically land on the host under:
~/.goga/runtime/builds/<normalized_project>/<branch>/
<normalized_project> is the project's absolute path with leading slashes stripped and remaining slashes replaced by hyphens; <branch> is the current git branch (slashes replaced with hyphens), or default when git is unavailable, the directory is not a repository, or HEAD is detached.
The directory survives across runs of the same project on the same branch by default, so an interrupted build can be resumed. Pass --clean to wipe and recreate it before launch for a fresh run. The host path never reaches the container except as the /workspace/.ralphex mount source — the container sees only /workspace/.ralphex.
Note: concurrent builds of the same project on the same branch share one runtime directory; run them on different branches or use --clean if isolation is required.
Examples
Run a build plan:
goga build plan.md
Dry run to see the command without executing:
goga build plan.md --dry-run
Run with custom timeouts and an extra environment variable:
goga build plan.md --session-timeout 3600 --max-iterations 50 -e ANTHROPIC_API_KEY=sk-xxx
Skip the uncommitted CODEMANIFEST check:
goga build plan.md --skip-manifest-check
Pull the latest image, then build (default skips the pull):
goga build plan.md --update
Route container traffic through a corporate proxy and add a local host entry:
goga build plan.md --proxy http://corp:3128 --add-host foo.local:127.0.0.1
Wipe persistent ralphex state before launching a fresh build:
goga build plan.md --clean
Configuration
Build settings are loaded from .goga/config.yml. Example configuration:
language: python
image: qarium/goga-python-3.12:1.1
# dockerfile: .goga/Dockerfile # optional — when set, `--update` builds the image from this Dockerfile instead of pulling
pipeline:
agent: claude
build:
task_executor:
agent: claude
env: {}
proxy: http://corp:3128 # optional HTTP/HTTPS proxy URL for the build container
hosts: # optional docker run --add-host entries
foo.local: 127.0.0.1
Only language is required by the loader. goga build additionally requires a build section (it exits with a ClickException when build is absent), a non-None build.task_executor.agent (optional at the loader level — absent/empty/whitespace resolves to None; the command raises a ClickException when it is None, since the build needs an agent to resolve the in-container wrapper), and the top-level image field must be set; otherwise the command exits with an error. The deprecated build.image field is rejected — use the top-level image field. The optional top-level dockerfile field (when set) makes --update build the image locally from that Dockerfile instead of pulling it. The optional build.proxy and build.hosts fields are overridden/augmented by the --proxy and --add-host CLI options respectively.
Exit Codes
| Code | Meaning |
|---|---|
0 |
Build completed successfully |
1 |
Build failed (Docker not found, config error, precondition failure, ralphex error, or a fatal docker build under --update) |