all: switch wallfacer to the unified sandbox-agents image#6
Merged
Conversation
Wallfacer used to maintain two parallel sandbox images (sandbox-claude and sandbox-codex), choosing between them per task by rewriting "sandbox-claude" → "sandbox-codex" in image names. The new sandbox-agents image (latere-ai/images PR #2, released as v0.0.6+) ships both Claude Code and Codex CLIs under a single `agent` user and dispatches at startup via WALLFACER_AGENT. This change cuts wallfacer over to that image and deletes the per-agent rewrite paths. Behaviour changes: - The runner injects WALLFACER_AGENT={claude,codex} into every sub-agent container so the unified entrypoint launches the right CLI. - All `/home/claude/...` and `/home/codex/...` mount targets become `/home/agent/...`, including the claude-config named volume, the codex auth bind-mount, and the dependency-cache volumes. - The codex auth mount now bind-mounts only `~/.codex/auth.json` (read-only) instead of the whole `~/.codex/` directory. Codex 0.120+ writes config.toml at startup, so the in-container directory must remain writable; mounting only auth.json keeps host state untouched. - `wallfacer doctor` reports a single sandbox image instead of two and no longer probes CODEX_SANDBOX_IMAGE separately. - `GetImageStatus`, `PullImage`, `DeleteImage` operate on the single image; the API still accepts a `sandbox` field for backward compatibility but ignores it. Code cuts: - Deleted `cli.codexImageFromClaude`, `cli.resolveSandboxImageForExec`, `runner.sandboxImageForSandbox`, `runner.entrypointForSandbox`, `handler.testCodexImage`, `handler.fallbackCodexSandboxImage`, and the test families that asserted their behaviour. The Codex/Claude type enum is preserved — only image-name rewriting goes away. - `Makefile` pulls and tags one image (`sandbox-agents`) instead of two. Build & docs: - Default image: `ghcr.io/latere-ai/sandbox-agents:latest`. - README, CLAUDE.md, getting-started, configuration, development, workspaces-and-config, api-and-transport, and git-worktrees all document the unified image and the WALLFACER_AGENT dispatch contract. Net: -601 / +298 lines across 32 files; full backend test suite (3714 tests in 46 packages) passes; `make lint` clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cuts wallfacer over to the unified
sandbox-agentsimage (latere-ai/images PR #2, released as v0.0.6+) and deletes the per-agent image-rewrite paths. The Claude vs. Codex sandbox type still matters at runtime — it just no longer maps to two distinct images.Required: ship the
latere-ai/imagessandbox-agentsrelease first. Until that GHCR image is published,make pull-imagesand the on-startup auto-pull will fail.Behaviour changes
WALLFACER_AGENT={claude,codex}into every sub-agent container so the unified entrypoint launches the right CLI./home/claude/...and/home/codex/...mount targets become/home/agent/..., including theclaude-confignamed volume, the codex auth bind-mount, and the dependency-cache volumes (npm, pip, cargo, go-build).~/.codex/auth.json(read-only) instead of the whole~/.codex/directory. Codex 0.120+ writesconfig.tomlat startup, so the in-container directory must remain writable; mounting onlyauth.jsonkeeps host state untouched. (This is the same fix shipped in latere-ai/images PR [Fixed] Test (Codex) fails behind Clash/local proxy on macOS + Podman #2 for the standalonesandbox-codeximage.)wallfacer doctorreports a single sandbox image instead of two and no longer probesCODEX_SANDBOX_IMAGEseparately.GetImageStatus,PullImage,DeleteImageoperate on the single image. The API still accepts asandboxfield for backward compatibility but ignores it.Code cuts
Deleted as dead with the unified image:
cli.codexImageFromClaudecli.resolveSandboxImageForExecrunner.sandboxImageForSandboxrunner.entrypointForSandboxhandler.testCodexImagehandler.fallbackCodexSandboxImageTestCodexImageFromClaude,TestResolveSandboxImageForExec_*,TestSandboxImageForTest_CodexResolution,TestBuildBaseContainerSpecClaudeVsCodexImageDiffersrewritten to assert WALLFACER_AGENT injection instead of image divergence).The
sandbox.Typeenum (Claude,Codex) is preserved unchanged — only image-name rewriting goes away. Per-activity sandbox routing (WALLFACER_SANDBOX_IMPLEMENTATIONetc.) keeps its semantics; it now flows intoWALLFACER_AGENTinstead of choosing an image.Build & docs
ghcr.io/latere-ai/sandbox-agents:latest.Makefile:IMAGE,GHCR_IMAGEswitched tosandbox-agents;CODEX_IMAGE,GHCR_CODEX_IMAGEdeleted;pull-imagespulls one image.CLAUDE.md,docs/guide/getting-started.md,docs/guide/configuration.md,docs/internals/development.md,docs/internals/workspaces-and-config.md,docs/internals/api-and-transport.md,docs/internals/git-worktrees.mdall document the unified image and theWALLFACER_AGENTdispatch contract.Verification
go test ./...— 3714 tests pass across 46 packages.make lint— clean (golangci-lint + Biome).sandbox-agents:testimage earlier in this session confirmed Codex dispatch viaWALLFACER_AGENT=codexreturns a valid Claude-Code JSON envelope, and Claude dispatch honoursCLAUDE_DEFAULT_MODEL.Test plan
latere-ai/imagesrelease publishessandbox-agents:vX.Y.Z, runmake buildend-to-end on a clean machine to confirm the auto-pull picks up the right tag (the existingcli.SandboxTagldflag plumbing still resolves via the GitHub API or build-time embed).make e2e-lifecycle SANDBOX=claudeandSANDBOX=codexagainst a running server to verify both dispatch paths complete a real task end-to-end.make e2e-dependency-dagto confirm conflict resolution / autosync still work with the new image.Follow-ups (not in this PR)
WALLFACER_TASK_WORKERS=true) to switchWALLFACER_AGENTmid-life so a single long-lived worker can serve different agent types across activities. Today each worker is still pinned to one agent type at create time, even though the image now supports both.ui/js/images.jscurrently shows the entry under the legacy "Claude" header; could be relabelled "Sandbox").