Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/stuartleeks/dev-container-features/shell-history:0": {},
"ghcr.io/devcontainers/features/github-cli:latest": {}
"ghcr.io/devcontainers/features/github-cli:latest": {},
"ghcr.io/jsburckhardt/devcontainer-features/opencode:latest": {},
"ghcr.io/jsburckhardt/devcontainer-features/just": {},
"ghcr.io/devcontainers/features/copilot-cli": {}
},
"updateContentCommand": "npm install -g @devcontainers/cli",
"remoteUser": "node",
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
- bat
- just
- opencode
- claude-code
baseImage:
- debian:latest
- ubuntu:latest
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This repository contains a _collection_ of Features.
| UV/UVX | https://docs.astral.sh/uv/ | An extremely fast Python package and project manager, written in Rust. A single tool to replace pip, pip-tools, pipx, poetry, pyenv, virtualenv, and more. |
| Ruff | https://docs.astral.sh/ruff/ | An extremely fast Python linter and code formatter, written in Rust. |
| OpenCode | https://opencode.ai/ | AI coding agent, built for the terminal. An open-source alternative to Claude Code with support for multiple LLM providers. |
| Claude Code | https://code.claude.com/docs/en/overview | Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows -- all through natural language commands. |
| Codex-cli | https://github.com/openai/codex | Codex CLI is an experimental project under active development. |


Expand Down Expand Up @@ -302,6 +303,23 @@ Running `opencode` inside the built container will allow you to use the AI codin
opencode --version
```

### `claude-code`

Running `claude` inside the built container will allow you to use the Claude Code agentic coding tool.

```jsonc
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/jsburckhardt/devcontainer-features/claude-code:1": {}
}
}
```

```bash
claude --version
```

### `Codex-CLI`

Running `codex` inside the built container will print the help menu of codex.
Expand Down
14 changes: 14 additions & 0 deletions src/claude-code/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "Claude Code",
"id": "claude-code",
"version": "1.0.0",
"description": "Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster.",
"documentationURL": "https://code.claude.com/docs/en/overview",
"options": {
"version": {
"type": "string",
"default": "latest",
"description": "Version of Claude Code to install (e.g., 1.0.58 or latest)"
}
}
}
110 changes: 110 additions & 0 deletions src/claude-code/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#!/usr/bin/env bash

# Variables
CLAUDE_VERSION="${VERSION:-"latest"}"

set -euo pipefail

if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi

# Clean up
rm -rf /var/lib/apt/lists/*

# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" >/dev/null 2>&1; then
if [ "$(find /var/lib/apt/lists/* | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update -y
fi
apt-get -y install --no-install-recommends "$@"
fi
}

echo "Installing Claude Code version: $CLAUDE_VERSION"

# Check if Node.js/npm is installed, if not install from Ubuntu repositories
if ! command -v npm >/dev/null 2>&1; then
echo "npm not found. Installing Node.js and npm..."
check_packages nodejs npm
echo "Node.js installed: $(node --version 2>/dev/null || echo 'N/A')"
echo "npm installed: $(npm --version)"
fi

# Install Claude Code via npm
# The npm package @anthropic-ai/claude-code includes a bundled Node.js runtime
# This is the official installation method for Claude Code
echo "Installing Claude Code via npm..."

# Try with strict SSL first
NPM_INSTALL_SUCCESS=false
if [ "$CLAUDE_VERSION" = "latest" ]; then
if npm install -g @anthropic-ai/claude-code --loglevel=error 2>/dev/null; then
NPM_INSTALL_SUCCESS=true
fi
else
if npm install -g @anthropic-ai/claude-code@"$CLAUDE_VERSION" --loglevel=error 2>/dev/null; then
NPM_INSTALL_SUCCESS=true
fi
fi

# If strict SSL fails (common in build environments), retry without strict SSL verification
if [ "$NPM_INSTALL_SUCCESS" = "false" ]; then
echo "Standard npm install failed, retrying with relaxed SSL settings for build environments..."
if [ "$CLAUDE_VERSION" = "latest" ]; then
npm install -g @anthropic-ai/claude-code --loglevel=error --strict-ssl=false || {
echo "ERROR: npm installation failed even with relaxed SSL settings."
echo "This may indicate network issues or that the package is not available."
echo "In production environments with proper network access, this should work."
echo "Manual installation: npm install -g @anthropic-ai/claude-code"
exit 1
}
else
npm install -g @anthropic-ai/claude-code@"$CLAUDE_VERSION" --loglevel=error --strict-ssl=false || {
echo "ERROR: npm installation of version $CLAUDE_VERSION failed."
echo "In production environments with proper network access, this should work."
exit 1
}
fi
fi

# Find where npm installed the binary and create symlink to /usr/local/bin
NPM_BIN_DIR=$(npm bin -g 2>/dev/null || npm root -g 2>/dev/null | sed 's/lib\/node_modules$/bin/')

if [ -n "$NPM_BIN_DIR" ] && [ -d "$NPM_BIN_DIR" ]; then
if [ -f "$NPM_BIN_DIR/claude" ]; then
echo "Creating symlink from $NPM_BIN_DIR/claude to /usr/local/bin/claude"
ln -sf "$NPM_BIN_DIR/claude" /usr/local/bin/claude
chmod +x /usr/local/bin/claude
elif [ -f "$NPM_BIN_DIR/claude-code" ]; then
echo "Creating symlink from $NPM_BIN_DIR/claude-code to /usr/local/bin/claude"
ln -sf "$NPM_BIN_DIR/claude-code" /usr/local/bin/claude
chmod +x /usr/local/bin/claude
fi
fi

# Clean up
rm -rf /var/lib/apt/lists/*

# Verify installation
echo "Verifying installation..."
if command -v claude >/dev/null 2>&1; then
echo "Claude Code installation completed successfully!"
echo "The 'claude' command is now available at: $(which claude)"
claude --version 2>/dev/null || echo "Claude is installed (version command may not be supported)"
else
# Check if installed via npm even if not in PATH
if npm list -g @anthropic-ai/claude-code 2>/dev/null | grep -q "@anthropic-ai/claude-code"; then
echo "Claude Code installed via npm successfully."
echo "Note: The 'claude' command may require a shell restart or PATH update."
npm list -g @anthropic-ai/claude-code
else
echo "WARNING: Claude Code installation could not be verified."
echo "This may be normal in restricted build environments."
fi
fi

echo "Done!"
1 change: 1 addition & 0 deletions test/_global/all-tools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ check "zarf" zarf version
check "codex" codex --version
check "just" just --version
check "opencode" opencode --version
check "claude-code" claude --version

reportResults
7 changes: 7 additions & 0 deletions test/_global/claude-code-specific-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

set -e
source dev-container-features-test-lib
check "claude-code with specific version" /bin/bash -c "claude --version | grep '1.0.58'"

reportResults
11 changes: 10 additions & 1 deletion test/_global/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"zarf": {},
"codex": {},
"just": {},
"opencode": {}
"opencode": {},
"claude-code": {}
}
},
"flux-specific-version": {
Expand Down Expand Up @@ -147,5 +148,13 @@
"version": "1.0.107"
}
}
},
"claude-code-specific-version": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"claude-code": {
"version": "1.0.58"
}
}
}
}
7 changes: 7 additions & 0 deletions test/claude-code/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

set -e

source dev-container-features-test-lib
check "claude-code" claude --version
reportResults