feat: initial Claude Code DevContainer Feature implementation#1
Merged
feat: initial Claude Code DevContainer Feature implementation#1
Conversation
…ainer Feature Comprehensive DevContainer Feature for installing Claude Code into any devcontainer. Includes design spec (3 rounds of review) and implementation plan (4 rounds of expert review covering shell, security, CI/CD, and DevContainer ecosystem compliance).
…l, persist install script
…o CI, add registry README
…r dep, fix completions hang - Change shebang to #!/bin/sh so Alpine's ash can execute the bootstrap preamble; the existing re-exec-with-bash preamble was already correct but unreachable with #!/usr/bin/env bash (Alpine has no bash pre-installed) - Add -ln bash flag to shfmt in CI and pre-commit so bash constructs (local, arrays) are not flagged as POSIX violations despite the /bin/sh shebang - pacman -Sy: sync package database before install (archlinux:latest has no DB) - Add tar to rhel dependency check (amazonlinux:2023 ships without tar) - Add timeout 30 and </dev/null to claude completions calls to prevent hang on first-run interactive prompts in fresh containers
((var++)) returns exit code 1 when var is 0, killing test.sh under set -Eeuo pipefail after the first assertion's echo. Replace with $((var + 1)) assignment which is always safe under strict mode. Also extend CI grep pattern to catch "Failed:" so the devcontainer CLI's own test report line (❌ Failed: 'claude-code') is detected and causes the job to exit 1 rather than silently passing.
npm global install creates the bin wrapper with 777 permissions. Explicitly chmod 755 after install so the binary is not world-writable.
- check_permissions: stat -Lc '%a' follows symlinks to the real file (Linux symlinks always show 0777 via lstat; chmod modifies the target) - check_file_owner: stat -Lc '%U' for the same reason - CI grep: add ' FAIL:' pattern so test assertion failures are caught even if the devcontainer CLI swallows the test script exit code
- duplicate.sh: satisfies devcontainer framework's idempotency test (sources test.sh and runs core_assertions after a second feature install) - test-arm64: switch from ubuntu-24.04-arm64 (native, never picked up) to ubuntu-latest + docker/setup-qemu-action v3.7.0 with DOCKER_DEFAULT_PLATFORM=linux/arm64; increase timeout to 60m for QEMU
When install.sh is re-run from its persisted path
(/usr/local/share/devcontainer-features/claude-code/install.sh),
the `cp "$0" "${PERSIST_DIR}/install.sh"` was a same-file copy
that exits non-zero under `set -e`, failing the second run ~5s in.
Resolve canonical paths via readlink -f and skip the copy when
source and destination are the same file.
devcontainer CLI v0.85.0 hardcodes --platform linux/amd64 in its internal updateUID.Dockerfile step, which remaps the non-root vscode user UID. On arm64 this step fails with "Failed to launch container". Raw OS images (ubuntu, alpine) have no pre-existing non-root user so the UID fixup is skipped and arm64 works. Remove the two devcontainer base images that trigger the remapping until the CLI bug is fixed.
Add 'Annotate install warnings' step (if: always()) to all three test jobs. Greps the log for '[claude-code feature] WARNING:' lines and emits ::warning:: annotations — visible as yellow in the PR checks UI without blocking the build.
- install.sh: gate zsh completions behind 'command -v zsh' so the attempt is skipped entirely on images without zsh (mkdir -p was silently creating the dir and causing a spurious WARNING on every raw OS image) - test.yml: add continue-on-error: true + exit 1 when warnings found so the Annotate step shows orange/yellow while the overall job stays green
- setup_mount_docs: replace log_info 'WARNING: ...' with log_warn so the API keys notice is emitted via the same code path as all other warnings - CI annotation steps: drop continue-on-error + exit 1 (misleading orange step); annotations are the signal, job stays cleanly green or red - Add sort -u to deduplicate repeated warnings within a single job run
Warnings now appear as a formatted list in the job Summary tab (GITHUB_STEP_SUMMARY) in addition to the ::warning:: annotations, so they are visible without expanding the Annotations section.
Docker log lines contain \r (CRLF), causing sort -u to treat identical warning messages as distinct lines. Pipe through tr -d '\r' before sort -u so duplicate warnings collapse to a single annotation entry.
The API keys message is documentation printed when mountHostConfig=true is explicitly set by the user. It is expected output, not an install failure. Emitting it as WARNING caused CI annotation noise whenever the mount_host_config scenario ran.
…laims Add "Why Not Just Use the Official Image?" section explaining the golden image, size overhead (~120 MB vs 1.5 GB replacement), and composability arguments. Document known limitations: nodeVersion ignored on Alpine/Arch, arm64 via QEMU only, readonly mount prevents write-back. Fix arm64 count (2 images, not 4). Correct the CI badge alt text to match workflow name.
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
Test plan
src/claude-code/devcontainer-feature.jsonreferencesclaude-devcontainer(notclaude-code-devcontainer)README.mdbadge and GHCR refs useclaude-devcontainer