Repository navigation
Image Tags and Rebuild Policy
What latest means, when it moves, and what to pin instead. Read this before depending on any of these images.
Every image publishes :latest, and :latest is repointed on every rebuild. A rebuild happens when:
- A pinned tool releases. Renovate opens a version-bump PR, CI verifies it, it auto-merges, and the merge triggers the image build. No human is involved.
-
A file the image is built from changes on
master— the Dockerfile, or a file it copies in (support scripts, managed settings). Each image's build workflow lists them underon.push.paths. - Someone dispatches the workflow manually from the Actions UI.
Case 1 is the one to understand: @anthropic-ai/claude-code publishes roughly twice a day, so claude-code:latest can move more than once in a day with no commit you would recognize as a change.
If you need reproducibility, do not use :latest.
There are two schemes, because there are two build pipelines.
| Image | Tags |
|---|---|
bun |
latest, bun<BUN>-alpine — e.g. bun1.3.5-alpine
|
claude-bun |
latest, bun<BUN>-slim
|
hugo-bun |
latest, hugo<HUGO>-bun<BUN>-alpine — e.g. hugo0.155.1-bun1.3.8-alpine
|
hugo-bun-node |
latest, hugo<HUGO>-bun<BUN>-node<NODE>-alpine
|
ralphex-fe |
latest, bun<BUN>-hugo<HUGO>
|
The version tag is derived from the ARGs in the Dockerfile at build time. These tags are not immutable — rebuilding without changing a version republishes the same tag. They identify a toolchain, not a build.
| Image | Tags |
|---|---|
claude-code |
latest, <git-sha>, <YYYYMMDD>
|
claude-code-sandbox |
latest, <git-sha>, <YYYYMMDD>
|
No composed version tag, because the project's .mise.toml decides its toolchain — a version in the image tag would be meaningless.
<git-sha> is the only genuinely immutable tag published by this repo. Pin to it if you need a build that cannot change under you:
| Need | Use |
|---|---|
| Reproducible builds, CI, anything auditable | claude-code:<git-sha> |
| A stable toolchain, tolerant of rebuilds | the composed version tag (hugo0.155.1-bun1.3.8-alpine) |
| Newest agent tooling, will tolerate surprises | :latest |
There is no v1-style moving major tag. If you want one, open an issue.
Twelve pinned ARGs across four images. Renovate's only manager is a regex over # renovate: comments in the Dockerfiles, so a version without that comment is never bumped.
| Tool | Source | Images | Update delay |
|---|---|---|---|
@anthropic-ai/claude-code |
npm |
claude-code, ralphex-fe
|
none — always latest |
rtk-ai/rtk |
GitHub releases |
claude-code, ralphex-fe
|
3 days |
umputun/ralphex |
GitHub releases |
claude-code, ralphex-fe
|
3 days |
agent-browser |
npm | claude-code |
3 days |
cli/cli (gh) |
GitHub releases |
claude-code, claude-bun
|
3 days |
github/gh-stack |
GitHub releases | claude-code |
3 days |
cf (Cloudflare CLI) |
npm | claude-code |
3 days |
docker/cli |
GitHub tags | ralphex-fe |
3 days |
go |
Go releases | ralphex-fe |
3 days |
node (24.x only) |
Node.js releases | hugo-bun-node |
3 days |
bun |
npm | ralphex-fe |
3 days |
gohugoio/hugo |
GitHub releases | ralphex-fe |
3 days |
The three-day delay (minimumReleaseAge) is deliberate. These bumps merge without human review and the merge publishes to ghcr.io, so a release is left to soak before adoption. Claude Code is exempt on purpose — it is tracked at latest.
Bumps arrive in two grouped PRs, each carrying whichever tools are currently eligible: devcontainer tools for the first ten rows, and ralphex-fe toolchain for Bun and Hugo, the two versions in ralphex-fe's tag. node is held to 24.x, so a new Node major stays a deliberate change.
Not every baked-in version is tracked: Bun in bun, claude-bun, hugo-bun and hugo-bun-node, and Hugo in the two hugo-bun images, carry no # renovate: comment and move only by hand.
No upstream release means no PR means no rebuild. This replaced an older nightly rebuild cron: images are no longer rebuilt on a timer, so a digest that has not changed means nothing upstream changed.
Base images (node:24-trixie-slim, alpine:3.21) and GitHub Actions pins are not tracked by Renovate — deliberately, to keep the update stream to the tools above.
# What's the current digest of a tag?
docker buildx imagetools inspect ghcr.io/gatezh/devcontainers/claude-code:latest
# What tool versions are inside?
docker run --rm --entrypoint sh ghcr.io/gatezh/devcontainers/claude-code:latest \
-c 'claude --version && rtk --version && ralphex --version && agent-browser --version && gh --version && cf --version && mise --version'Every build also runs a verification step in CI that asserts each tool is present and executable before publishing.
All images are built for linux/amd64 and linux/arm64 on native runners — no QEMU emulation, so arm64 builds are tested rather than assumed. Pre-merge CI builds amd64 only; arm64 is built and verified at merge time.
- #116 — replaced the nightly rebuild cron with Renovate-driven rebuilds
- #120 — documented the four agent tools as pinned, not always-latest
- #121 — first grouped agent-tools bump
- #126 — made auto-merge actually fire; added the 3-day soak with claude-code exempt
-
#134 — Bun and Hugo bumps for
ralphex-fe, as their own group - #146 — widened tracking to gh, the docker CLI, Go and Node
- #167 — gh-stack
-
#204 —
cf, tracked through its npm prereleases while it's in beta -
#205 —
claude-coderebuilds when its managed skill or agent-browser config changes - Tag schemes are defined in
.github/workflows/build-*.yml; the update policy is in.github/renovate.json5
Last verified: 2026-10-08