From ed333ffff833b62a87451f4aba75dd2712002984 Mon Sep 17 00:00:00 2001 From: Manuel Escalante Date: Mon, 16 Feb 2026 16:42:19 +0100 Subject: [PATCH 1/6] feat: replace npm with native installer for Claude Code Migrate from `npm install -g @anthropic-ai/claude-code` to the native installer at https://claude.ai/install.sh, removing the Node.js dependency entirely. - Remove Node.js install/detection functions - Add curl/bash dependency check - Add Alpine-specific deps (libgcc, libstdc++, ripgrep) - Copy binary to /usr/local/bin/ for multi-user access - Remove installsAfter Node.js dependency from feature metadata --- src/claude-code/devcontainer-feature.json | 5 +- src/claude-code/install.sh | 98 ++++++----------------- 2 files changed, 27 insertions(+), 76 deletions(-) diff --git a/src/claude-code/devcontainer-feature.json b/src/claude-code/devcontainer-feature.json index c9ba494..2e07429 100644 --- a/src/claude-code/devcontainer-feature.json +++ b/src/claude-code/devcontainer-feature.json @@ -12,8 +12,5 @@ "anthropic.claude-code" ] } - }, - "installsAfter": [ - "ghcr.io/devcontainers/features/node" - ] + } } diff --git a/src/claude-code/install.sh b/src/claude-code/install.sh index b115c9e..abcd347 100755 --- a/src/claude-code/install.sh +++ b/src/claude-code/install.sh @@ -21,7 +21,7 @@ install_packages() { local pkg_manager="$1" shift local packages="$@" - + case "$pkg_manager" in apt) apt-get update @@ -38,63 +38,24 @@ install_packages() { return 1 ;; esac - - return 0 -} -# Function to install Node.js -install_nodejs() { - local pkg_manager="$1" - - echo "Installing Node.js using $pkg_manager..." - - case "$pkg_manager" in - apt) - # Debian/Ubuntu - install more recent Node.js LTS - install_packages apt "ca-certificates curl gnupg" - mkdir -p /etc/apt/keyrings - curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list - apt-get update - apt-get install -y nodejs - ;; - apk) - # Alpine - install_packages apk "nodejs npm" - ;; - dnf) - # Fedora/RHEL - install_packages dnf "nodejs npm" - ;; - yum) - # CentOS/RHEL - curl -sL https://rpm.nodesource.com/setup_18.x | bash - - yum install -y nodejs - ;; - *) - echo "ERROR: Unsupported package manager for Node.js installation" - return 1 - ;; - esac - - # Verify installation - if command -v node >/dev/null && command -v npm >/dev/null; then - echo "Successfully installed Node.js and npm" - return 0 - else - echo "Failed to install Node.js and npm" - return 1 - fi + return 0 } -# Function to install Claude Code CLI +# Function to install Claude Code CLI using the native installer install_claude_code() { echo "Installing Claude Code CLI..." - npm install -g @anthropic-ai/claude-code + curl -fsSL https://claude.ai/install.sh | bash - if command -v claude >/dev/null; then + # The native installer places the binary in ~/.local/bin (symlink to ~/.local/share/claude/). + # Copy the resolved binary to /usr/local/bin so it is available to all users. + CLAUDE_LOCAL="$HOME/.local/bin/claude" + if [ -e "$CLAUDE_LOCAL" ]; then + CLAUDE_REAL="$(readlink -f "$CLAUDE_LOCAL")" + cp "$CLAUDE_REAL" /usr/local/bin/claude + chmod +x /usr/local/bin/claude echo "Claude Code CLI installed successfully!" - claude --version + /usr/local/bin/claude --version return 0 else echo "ERROR: Claude Code CLI installation failed!" @@ -102,22 +63,6 @@ install_claude_code() { fi } -# Print error message about requiring Node.js feature -print_nodejs_requirement() { - cat </dev/null || ! command -v npm >/dev/null; then - echo "Node.js or npm not found, attempting to install automatically..." - install_nodejs "$PKG_MANAGER" || print_nodejs_requirement + # Ensure curl and bash are available + MISSING_DEPS="" + command -v curl >/dev/null || MISSING_DEPS="$MISSING_DEPS curl" + command -v bash >/dev/null || MISSING_DEPS="$MISSING_DEPS bash" + if [ -n "$MISSING_DEPS" ]; then + echo "Installing missing dependencies:$MISSING_DEPS" + install_packages "$PKG_MANAGER" $MISSING_DEPS + fi + + # Alpine requires additional dependencies for the native installer + if [ "$PKG_MANAGER" = "apk" ]; then + echo "Alpine detected, installing additional dependencies..." + install_packages apk libgcc libstdc++ ripgrep fi # Install Claude Code CLI @@ -137,4 +91,4 @@ main() { } # Execute main function -main \ No newline at end of file +main From 56ee73ece2593be20dacbb39bb792985e57162ac Mon Sep 17 00:00:00 2001 From: Manuel Escalante Date: Mon, 16 Feb 2026 16:42:25 +0100 Subject: [PATCH 2/6] test: remove Node.js dependencies and checks from tests - Remove node:1 feature from test scenarios - Remove node --version and npm --version checks --- test/claude-code/scenarios.json | 3 +-- test/claude-code/test.sh | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/test/claude-code/scenarios.json b/test/claude-code/scenarios.json index 0c894f0..e635a41 100644 --- a/test/claude-code/scenarios.json +++ b/test/claude-code/scenarios.json @@ -2,8 +2,7 @@ "basic": { "image": "mcr.microsoft.com/devcontainers/base:ubuntu", "features": { - "ghcr.io/devcontainers/features/node:1": {}, "claude-code": {} } } -} \ No newline at end of file +} diff --git a/test/claude-code/test.sh b/test/claude-code/test.sh index f546f57..0218936 100755 --- a/test/claude-code/test.sh +++ b/test/claude-code/test.sh @@ -6,10 +6,8 @@ set -e source dev-container-features-test-lib # Feature-specific tests -check "node version" node --version -check "npm version" npm --version check "claude cli installed" command -v claude check "claude version" claude --version # Report results -reportResults \ No newline at end of file +reportResults From 741c9cdf340026630994717c87523b76f823f70c Mon Sep 17 00:00:00 2001 From: Manuel Escalante Date: Mon, 16 Feb 2026 16:42:31 +0100 Subject: [PATCH 3/6] docs: update documentation for native installer migration - Rewrite NOTES.md removing all Node.js references - Add Alpine Linux and deprecation notice sections - Remove Requirements section from README.md --- README.md | 6 +----- src/claude-code/NOTES.md | 30 ++++++------------------------ 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 8a7a84b..3066039 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,6 @@ To use this feature in your devcontainer, add it to your `devcontainer.json` fil } ``` -## Requirements - -The feature automatically depends on Node.js and will install it if not already present. - ## Building and Testing You can build and test the feature using the [dev container CLI](https://github.com/devcontainers/cli): @@ -35,4 +31,4 @@ devcontainer feature publish -n anthropics/devcontainer-features . ## License -This project is licensed under the MIT License - see the LICENSE file for details. \ No newline at end of file +This project is licensed under the MIT License - see the LICENSE file for details. diff --git a/src/claude-code/NOTES.md b/src/claude-code/NOTES.md index b8fbe88..418b138 100644 --- a/src/claude-code/NOTES.md +++ b/src/claude-code/NOTES.md @@ -1,37 +1,19 @@ # Using Claude Code in devcontainers -## Requirements +## Installation -This feature requires Node.js and npm to be available in the container. You need to either: - -1. Use a base container image that includes Node.js, or -2. Add the Node.js feature to your devcontainer.json -3. Let this feature attempt to install Node.js automatically (best-effort, works on Debian/Ubuntu, Alpine, Fedora, RHEL, and CentOS) - -Note: When auto-installing Node.js, a compatible LTS version (Node.js 18.x) will be used. - -## Recommended configuration - -For most setups, we recommend explicitly adding both features: +This feature installs Claude Code using the [native installer](https://claude.ai/install.sh). No additional features or dependencies need to be added to your devcontainer configuration. ```json "features": { - "ghcr.io/devcontainers/features/node:1": {}, "ghcr.io/anthropics/devcontainer-features/claude-code:1": {} } ``` -## Using with containers that already have Node.js - -If your container already has Node.js installed (for example, a container based on a Node.js image or one using nvm), you can use the Claude Code feature directly without adding the Node.js feature: - -```json -"features": { - "ghcr.io/anthropics/devcontainer-features/claude-code:1": {} -} -``` +## Alpine Linux -## Using with nvm +On Alpine-based containers, this feature automatically installs the required additional dependencies: `libgcc`, `libstdc++`, and `ripgrep`. -When using with containers that have nvm pre-installed, you can use the Claude Code feature directly, and it will use the existing Node.js installation. +## Deprecation notice +The previous NPM-based installation method (`npm install -g @anthropic-ai/claude-code`) has been deprecated. This feature now uses the native installer. For more information, see the [official documentation](https://code.claude.com/docs/en/getting-started#npm-installation-deprecated). From a68ef0c24735fdca29d13338043e49dd147c980a Mon Sep 17 00:00:00 2001 From: Manuel Escalante Date: Mon, 16 Feb 2026 17:15:25 +0100 Subject: [PATCH 4/6] chore: bump version to 1.0.6 --- src/claude-code/devcontainer-feature.json | 24 +++++++++++------------ 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/claude-code/devcontainer-feature.json b/src/claude-code/devcontainer-feature.json index 2e07429..1d4c15a 100644 --- a/src/claude-code/devcontainer-feature.json +++ b/src/claude-code/devcontainer-feature.json @@ -1,16 +1,14 @@ { - "name": "Claude Code CLI", - "id": "claude-code", - "version": "1.0.5", - "description": "Installs the Claude Code CLI globally", - "options": {}, - "documentationURL": "https://github.com/anthropics/devcontainer-features/tree/main/src/claude-code", - "licenseURL": "https://github.com/anthropics/devcontainer-features/blob/main/LICENSE", - "customizations": { - "vscode": { - "extensions": [ - "anthropic.claude-code" - ] - } + "name": "Claude Code CLI", + "id": "claude-code", + "version": "1.0.6", + "description": "Installs the Claude Code CLI globally", + "options": {}, + "documentationURL": "https://github.com/anthropics/devcontainer-features/tree/main/src/claude-code", + "licenseURL": "https://github.com/anthropics/devcontainer-features/blob/main/LICENSE", + "customizations": { + "vscode": { + "extensions": ["anthropic.claude-code"] } + } } From 35181b9f82b0a007321bec4a7d0094a512746fae Mon Sep 17 00:00:00 2001 From: Manuel Escalante Date: Mon, 23 Mar 2026 16:56:15 +0100 Subject: [PATCH 5/6] format: clean up README formatting and remove unnecessary whitespace --- src/claude-code/README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/claude-code/README.md b/src/claude-code/README.md index c383602..e7a957d 100644 --- a/src/claude-code/README.md +++ b/src/claude-code/README.md @@ -1,4 +1,3 @@ - # Claude Code CLI (claude-code) Installs the Claude Code CLI globally @@ -14,8 +13,7 @@ Installs the Claude Code CLI globally ## Options | Options Id | Description | Type | Default Value | -|-----|-----|-----|-----| - +| ---------- | ----------- | ---- | ------------- | ## Customizations @@ -60,8 +58,6 @@ If your container already has Node.js installed (for example, a container based When using with containers that have nvm pre-installed, you can use the Claude Code feature directly, and it will use the existing Node.js installation. - - --- -_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/anthropics/devcontainer-features/blob/main/src/claude-code/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ +_Note: This file was auto-generated from the [devcontainer-feature.json](https://github.com/anthropics/devcontainer-features/blob/main/src/claude-code/devcontainer-feature.json). Add additional notes to a `NOTES.md`._ From efa36eee018c90a4747bc2d3e5f88ea343e48bb3 Mon Sep 17 00:00:00 2001 From: Manuel Escalante Date: Mon, 23 Mar 2026 17:15:49 +0100 Subject: [PATCH 6/6] fix: update install_claude_code function to use remote user for installation --- src/claude-code/install.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/claude-code/install.sh b/src/claude-code/install.sh index abcd347..9844038 100755 --- a/src/claude-code/install.sh +++ b/src/claude-code/install.sh @@ -45,11 +45,12 @@ install_packages() { # Function to install Claude Code CLI using the native installer install_claude_code() { echo "Installing Claude Code CLI..." - curl -fsSL https://claude.ai/install.sh | bash + su - "$_REMOTE_USER" -c 'curl -fsSL https://claude.ai/install.sh | bash' # The native installer places the binary in ~/.local/bin (symlink to ~/.local/share/claude/). # Copy the resolved binary to /usr/local/bin so it is available to all users. - CLAUDE_LOCAL="$HOME/.local/bin/claude" + REMOTE_USER_HOME=$(eval echo "~$_REMOTE_USER") + CLAUDE_LOCAL="$REMOTE_USER_HOME/.local/bin/claude" if [ -e "$CLAUDE_LOCAL" ]; then CLAUDE_REAL="$(readlink -f "$CLAUDE_LOCAL")" cp "$CLAUDE_REAL" /usr/local/bin/claude