Skip to content

perf: prebuild the agent image and unify tool installation - #4

Open
akalipetis wants to merge 4 commits into
feature-agent-kitfrom
feature-prebuilt-image
Open

perf: prebuild the agent image and unify tool installation#4
akalipetis wants to merge 4 commits into
feature-agent-kitfrom
feature-prebuilt-image

Conversation

@akalipetis

Copy link
Copy Markdown
Contributor

Stacked on #2, which is stacked on #1 — merge in order. Base is feature-agent-kit, so this PR's diff is only the image work.

Why

Tool installation ran inline in setup.install on every sandbox creation: the Pi installer, two npm installs, and a Webi fetch — roughly 60–90s each time.

The main change: one script, two consumers

Rather than duplicating installs between a Dockerfile and setup.install, tool installation now lives in exactly one place — files/home/.lambda/install-tools.sh:

  • the Dockerfile COPYs and runs it, baking the tools into cached layers
  • setup.install runs the same script, so the kit still works on a plain shell-docker base or if an image pull fails

Static files under files/home/ land before install commands, which is what makes sharing possible. Every step is command -v guarded and idempotent, so the script no-ops against an image that already has the tools.

setup.install drops from 10 commands to 6, and every survivor needs runtime state an image cannot have:

Command Why it can't move into the image
ownership chown volumes mount at runtime
npm proxy config reads $HTTP_PROXY
install-tools.sh no-ops on a prebuilt image; the fallback path
Codex config.toml kept beside the Claude seeding
~/.claude.json reads $WORKSPACE_DIR
settings.json paired with the above

Image publishing

.github/workflows/image.yml builds linux/amd64 + linux/arm64 and pushes to ghcr.io/withlogicco/sbx-kit-lambda on pushes to main, on tags, weekly (tool versions float), and on workflow_dispatch. Public, so no registry credential. The workflow asserts the agent-image contract against the pushed digest — agent is UID 1000, all four binaries resolve, and lambda really points at pi.

On sandbox.build

It's declared alongside image so the image's origin is discoverable from the spec, but it buys no behavior. sbx accepts it and warns:

WARN: field "sandbox.build" is accepted but not yet implemented: Dockerfile
      builds are accepted in the schema but not yet built by the runtime;
      the image is taken from sandbox.image

That notice on every validate/inspect is expected, not a regression. Declaring build without image is not an option — the kit fails validation outright:

INVALID: artifact: sandbox.build is accepted in the schema but not yet
         implemented — specify sandbox.image

Worth revisiting if sbx ever implements it: for a kit consumed over git+https://, honouring build would switch every user from pulling a cached multi-arch image to building locally on first create. Pulling from GHCR is the better end state, not a stopgap.

Two things to know before merging

⚠️ Unverified: that sbx prefers a local image over pulling. sandbox.image names a GHCR tag that doesn't exist yet. The intent is that a local docker build -t ghcr.io/withlogicco/sbx-kit-lambda:latest . satisfies it, so nothing changes when CI takes over — and the lambda shell helper builds on demand, with --build to force a rebuild. This could not be tested: the Docker daemon was down. If sbx always pulls, point image back at docker/sandbox-templates:shell-docker until CI publishes; the guarded script makes that a one-line change.

The image has never been built. Same reason. The workflow's contract check is its first real test, so expect to iterate on the Dockerfile if that step fails.

Also note a local build masquerades as the published tag, so docker image inspect is the only way to tell whether you're on a local build or the real one.

🤖 Generated with Claude Code

Tool installation ran inline in `setup.install` on every sandbox creation: the
Pi installer plus two npm installs plus a Webi fetch, roughly 60-90s each time.

It now lives in one place, `files/home/.lambda/install-tools.sh`, with two
consumers: the Dockerfile bakes it into cached layers, and `setup.install` runs
the same script so the kit still works on a plain shell-docker base. Static
files under `files/home/` land before install commands, which is what makes
sharing possible. Every step stays guarded and idempotent, so the script no-ops
against an image that already has the tools. `setup.install` drops from ten
commands to six, and every remaining one depends on runtime state: volume-mount
ownership, npm proxy configuration, and config seeding that reads WORKSPACE_DIR.

`sandbox.image` points at ghcr.io/withlogicco/sbx-kit-lambda:latest, built by
.github/workflows/image.yml for linux/amd64 and linux/arm64 on pushes to main,
on tags, weekly, and on manual dispatch. The image is public, so no registry
credential is needed, and the workflow asserts the agent-image contract and
every expected binary against the pushed digest. Until CI publishes the tag the
`lambda` shell helper builds it locally under the same name, so no spec change
is needed when CI takes over.

`sandbox.build` is declared alongside `image` so the image's origin is
discoverable from the spec. sbx does not act on it and emits one notice saying
the image is taken from sandbox.image; that notice is expected. Declaring
`build` without `image` is not an option — the kit fails validation outright.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T15:45:16.817896Z f3793cd PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3793cd768

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Bust the install cache during weekly refreshes

On scheduled runs where the Dockerfile, installer, and base-image digest are unchanged, this GHA cache allows BuildKit to reuse the existing RUN sh /tmp/install-tools.sh layer; remote Pi/npm/Webi releases are not cache-key inputs. The weekly workflow therefore republishes the same tool versions instead of performing its stated refresh, potentially leaving the image stale indefinitely. Disable caching for the installation stage or add a schedule-specific cache-busting input.

Useful? React with 👍 / 👎.

Comment on lines +7 to +9
paths:
- Dockerfile
- .github/workflows/image.yml

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Trigger image builds when the installer changes

When files/home/.lambda/install-tools.sh changes on main, this path filter skips the image workflow because it lists only the Dockerfile and workflow. New sandboxes consequently keep receiving the old baked tools and installation behavior until a scheduled or manual build runs; add the shared installer (and other effective build-context inputs) to this filter.

AGENTS.md reference: AGENTS.md:L25-L29

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant