Skip to content

goga build

Execute a build plan inside an isolated 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 the build engine running inside a Docker container with the goga in-container process as the entry point.

The build pipeline performs these steps:

  1. Docker check -- Verifies Docker is installed and accessible.
  2. Config loading -- Reads .goga/config.yml for build settings. The optional machine-wide home config (~/.goga/config.yml) layers underneath: home.env is the base (lowest-priority) layer of the container env-file, home.docker.run is appended to every docker run, home.docker.build is forwarded to image builds. Git identity env (GIT_AUTHOR_NAME/EMAIL, GIT_COMMITTER_NAME/EMAIL) is layered in, tolerating absent git config.
  3. Uncommitted manifest check -- Scans git status for uncommitted CODEMANIFEST files (can be skipped).
  4. Agent preconditions -- Resolves the configured agent to its in-container wrapper (the wrappers ship inside the image). A review executor with a set agent that differs from the task executor, or that declares a non-empty env, combined with an active worktree (--worktree or build.worktree: true) is rejected host-side with exit 1, before any container launch — review execution cannot follow a worktree branch. The guard is config-level and skip-independent: --skip-review does not bypass it.
  5. Defaults copy -- Fully rewrites the engine's prompt and agent defaults from the configured build.prompts_dir/build.agents_dir, or from the defaults shipped with goga. When build.review_executor.roles is set, the review prompts are filtered to the selected roles.
  6. Image refresh (optional) -- When --update/-u is set, the image is refreshed: if a top-level dockerfile is declared in .goga/config.yml, docker build runs against it (build failure is fatal — exit 1); otherwise docker pull runs (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.
  7. First-run safety net -- Runs unconditionally at launch entry: when the configured image is absent locally AND a project dockerfile is declared, the image is built once before launch (fatal on failure — the launch is skipped). This closes the corner case where a Dockerfile is declared but the image was never built and --update is not passed.
  8. Docker execution -- Launches the build inside the configured Docker image, after the shared pre-launch host–image version check (see Runtime — Pre-launch version check). Credential files for claude, codex, and opencode are detected on the host and bind-mounted read-only into the container automatically (no flag). Persistent build state is isolated from the project directory (see Runtime state isolation). The pass structure: one full-cycle pass by default; --skip-review runs a single tasks-only pass; a review executor agent differing from the task agent, or a non-empty build.review_executor.env, runs two passes — tasks, then the review pass with the review env overlaid for that subprocess only (a failed first pass skips the second).
  9. Plan relocation -- After a successful final pass the plan file moves to <plan_dir>/completed/<plan_name> (atomic replace, idempotent by name). A failed run or a dry run leaves the plan in place so the build can resume.

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 Run the build on an isolated git worktree branch
--skip-finalize flag off Skip finalization step
--skip-manifest-check flag off Skip check for uncommitted CODEMANIFEST files
--skip-review / --no-skip-review bool pair (tri-state) unset Skip the review phase (--skip-review — a tasks-only run) or force the full cycle (--no-skip-review). Overrides build.review_executor.skip in .goga/config.yml; when neither is given, the config decides
--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
--base-ref string config Review diff base (branch name or commit hash); overrides build.review_executor.base_ref
-e, --env string (repeatable) -- 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)
-u, --update 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 build's persistent runtime directory on the host 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.

--review-patience and --base-ref are review-scoped: they resolve with precedence CLI > build.review_executor.* in .goga/config.yml > omit, and they apply to review-carrying passes only — the single full-cycle pass, or the review pass of a two-pass run; a tasks-only run carries neither. The legacy build.review_patience key is not parsed (the setting moved to build.review_executor.patience).

Proxy and hosts

--proxy and --add-host (with build.proxy / build.hosts in .goga/config.yml) follow the shared container contract — see Runtime — Proxy and hosts.

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) — see Runtime — Credential mounts.

Runtime state isolation

The build engine 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.

Pre-launch version check

Before the working container starts, goga build runs the shared host–image version check — the goga versions on the host and inside the image must agree at the (major, minor) level, or the launch is refused. The full behavior table and the GOGA_SKIP_VERSION_CHECK=1 escape hatch live in Runtime — Pre-launch version check.

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 1h --max-iterations 50 -e ANTHROPIC_API_KEY=sk-xxx

Skip the uncommitted CODEMANIFEST check:

goga build plan.md --skip-manifest-check

Skip the review phase (run tasks only):

goga build plan.md --skip-review

Review against a specific branch or commit instead of the detected default:

goga build plan.md --base-ref origin/1.2.x

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 build 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.3
# 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, invalid review configuration, two-pass review combined with worktree, an execution-engine error — a missing engine binary inside the image or a rejected launch surfaces as a clean one-line message with exit code 1 — a fatal docker build under --update, or the pre-launch version check refusing the launch: a host–image (major, minor) mismatch, an image that cannot answer the version probe, or an undeterminable host version — see Runtime — Pre-launch version check)