You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 22d2e1b
Browse filesBrowse the repository at this point in the historyBrowse files
fix(claude-code): drop pull_policy:always, pull image via initializeCommand (#109) (#112)
pull_policy: always in the Compose templates is incompatible with updateRemoteUserUID:true on Linux/WSL2. The Dev Containers CLI builds a local-only vsc-...-uid image to remap the node user, and the generated Compose override points image: at that local tag while inheriting pull_policy: always, so 'docker compose up' tries to pull an image that exists only on disk and fails with 'pull access denied'. Masked on macOS/Windows Docker Desktop, where no -uid image is built.
Move image refresh to a host-side initializeCommand in devcontainer.json, which runs before the build (Initialization step) so the -uid image layers on a freshly-pulled base, and drop pull_policy from both Compose files. The '|| exit 0' guard keeps offline/outage opens working and is portable across the host shells the CLI uses for string commands (POSIX sh + Windows cmd.exe). Updates default and sandbox variants and the README.
Closes#109
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: claude-code/README.md
+6-7Lines changed: 6 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -48,13 +48,13 @@ The image rebuilds daily at 5am MT (11:00 UTC) using native runners for both amd
48
48
49
49
### Default variant
50
50
51
-
Copy the example files into your project's `.devcontainer/` directory and customize as needed. Docker Compose with `pull_policy: always` ensures "Rebuild Without Cache" always pulls the latest image. All other config stays in `devcontainer.json` using cross-orchestrator properties (`mounts`, `containerEnv`, `capAdd`, `init`) so you keep devcontainer variable substitution (`${localWorkspaceFolderBasename}`, `${localEnv:...}`).
51
+
Copy the example files into your project's `.devcontainer/` directory and customize as needed. A host-side `initializeCommand` in `devcontainer.json` pulls the prebuilt image before the container is built, so "Rebuild Without Cache" always layers on the latest image. All other config stays in `devcontainer.json` using cross-orchestrator properties (`mounts`, `containerEnv`, `capAdd`, `init`) so you keep devcontainer variable substitution (`${localWorkspaceFolderBasename}`, `${localEnv:...}`).
52
52
53
53
**After copying:** replace `myproject` with your project name in `docker-compose.yml` (the `name:` field) and `devcontainer.json` (volume mount prefixes). This must match across both variants if using the sandbox.
54
54
55
55
Copy these to your project's `.devcontainer/`:
56
56
57
-
-[`.devcontainer/docker-compose.yml`](.devcontainer/docker-compose.yml) — image reference with `pull_policy: always`
57
+
-[`.devcontainer/docker-compose.yml`](.devcontainer/docker-compose.yml) — image reference (kept fresh by the `initializeCommand` pull in `devcontainer.json`)
58
58
-[`.devcontainer/devcontainer.json`](.devcontainer/devcontainer.json) — full config with VS Code extensions, fish shell, OXC formatter, node_modules volume isolation, and lifecycle commands
59
59
60
60
**Key settings included:** fish + bash terminal profiles, OXC formatter (with comments for switching to Biome/Prettier), node_modules/Claude config/fish history volume mounts, and `updateContentCommand` for mise/bun setup.
@@ -114,7 +114,7 @@ Mark as executable: `chmod +x init-plugins.sh`
114
114
115
115
To remove a plugin in your project, delete its entry from the local `init-plugins.sh` — the script is a template, not image-baked, so each consumer controls its own list.
116
116
117
-
> **Why `init-plugins.sh` stays per-project but `patch-playwright-mcp` doesn't:**`init-plugins.sh` carries project-specific configuration (marketplace list, plugin list) — it's *meant* to be edited per project. The patch script has zero project-specific config and is identical across every consumer, so it's baked into the image and flows through the same daily-rebuild + `pull_policy: always` channel as the rest of the image. That boundary is the rule: project-specific config stays per-project; universal logic moves into the image.
117
+
> **Why `init-plugins.sh` stays per-project but `patch-playwright-mcp` doesn't:**`init-plugins.sh` carries project-specific configuration (marketplace list, plugin list) — it's *meant* to be edited per project. The patch script has zero project-specific config and is identical across every consumer, so it's baked into the image and flows through the same daily-rebuild + `initializeCommand` image-pull channel as the rest of the image. That boundary is the rule: project-specific config stays per-project; universal logic moves into the image.
Everything else in `devcontainer.json` (mounts, containerEnv, lifecycle commands, etc.) stays the same — the local image is identical to the pre-built one.
436
+
Everything else in `devcontainer.json` (mounts, containerEnv, lifecycle commands, etc.) stays the same — the local image is identical to the pre-built one. The `initializeCommand` still points at the GHCR image, but `|| exit 0` means a failed pull won't block the open; you can remove it to skip the now-unnecessary pull.
438
437
439
438
### Extending the image for project-specific needs
0 commit comments