Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM mcr.microsoft.com/devcontainers/base:jammy

ARG PIXI_VERSION
ARG PIXI_VERSION=v0.62.2

RUN curl -L -o /usr/local/bin/pixi -fsSL --compressed "https://github.com/prefix-dev/pixi/releases/download/${PIXI_VERSION}/pixi-$(uname -m)-unknown-linux-musl" \
&& chmod +x /usr/local/bin/pixi \
Expand Down
41 changes: 8 additions & 33 deletions .devcontainer/claude-code/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ These files **must be writable** to enable:

## Usage

### Basic Setup
### Setup

Add this feature to your `devcontainer.json`:

Expand All @@ -63,19 +63,7 @@ Add this feature to your `devcontainer.json`:
}
```

### Recommended Setup (with Node.js)

For better compatibility, include the Node.js feature:

```json
{
"features": {
"ghcr.io/devcontainers/features/node:1": {},
"./claude-code": {}
},
"runArgs": ["--network=host"]
}
```
**Note**: Node.js is automatically installed via the `installsAfter` dependency mechanism - you don't need to explicitly add it to your features.

### Why `--network=host` is Required

Expand Down Expand Up @@ -140,14 +128,14 @@ touch ~/.claude/settings.json

### Container

- **Node.js 18+** and **npm** must be available (will be auto-installed if possible)
- Supported base images: Debian, Ubuntu, Alpine, Fedora, RHEL, CentOS
- **Node.js 18+** and **npm** are automatically installed via the `installsAfter` dependency mechanism
- No manual configuration required

## Assumptions

1. **User**: The feature assumes the container user is `vscode` (standard for Dev Containers)
- Files are mounted to `/home/vscode/.claude/`
- If your container uses a different user, you may need to adjust the mount paths
1. **Container User**: This feature assumes the container user is `vscode` (standard for Dev Containers)
- Configuration files are mounted to `/home/vscode/.claude/`
- If your container uses a different user (e.g., `root`, `codespace`), you'll need to customize the mounts in your `devcontainer.json`

2. **HOME Environment Variable**: Must be set on the host machine (standard on Unix systems)

Expand Down Expand Up @@ -385,19 +373,6 @@ Then use both:

## Troubleshooting

### "Node.js not found" error

**Solution**: Add the Node.js feature explicitly:

```json
{
"features": {
"ghcr.io/devcontainers/features/node:1": {},
"./claude-code": {}
}
}
```

### OAuth callback hangs at "Paste code here"

**Problem**: Browser clicks "Authorize" but container never receives the callback.
Expand All @@ -422,7 +397,7 @@ See "Why `--network=host` is Required" section above for details.

### VS Code extensions don't install with `--network=host`

**Known Issue**: [Using runArg network=host prevents extensions from installing](https://github.com/microsoft/vscode-remote-release/issues/9212)
**Known Issue**: [Using runArgs network=host prevents extensions from installing](https://github.com/microsoft/vscode-remote-release/issues/9212)

**Workarounds:**
1. **Rebuild without runArgs first**, let extensions install, then add runArgs (extensions persist)
Expand Down
154 changes: 35 additions & 119 deletions .devcontainer/claude-code/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,95 +5,27 @@ set -eu
# Based on: https://github.com/anthropics/devcontainer-features/pull/25
# Combines CLI installation with configuration directory setup

# Function to detect the package manager and OS type
detect_package_manager() {
for pm in apt-get apk dnf yum; do
if command -v $pm >/dev/null; then
case $pm in
apt-get) echo "apt" ;;
*) echo "$pm" ;;
esac
return 0
fi
done
echo "unknown"
return 1
}
# Function to install Claude Code CLI
install_claude_code() {
echo "Installing Claude Code CLI globally..."

# Function to install packages using the appropriate package manager
install_packages() {
local pkg_manager="$1"
shift
local packages="$@"

case "$pkg_manager" in
apt)
apt-get update
apt-get install -y $packages
;;
apk)
apk add --no-cache $packages
;;
dnf|yum)
$pkg_manager install -y $packages
;;
*)
echo "WARNING: Unsupported package manager. Cannot install packages: $packages"
return 1
;;
esac

return 0
}
# Verify Node.js and npm are available
if ! command -v node >/dev/null || ! command -v npm >/dev/null; then
cat <<EOF

# 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
ERROR: Node.js and npm are required but not found!

# 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
}
This should not happen as the Node.js feature is automatically installed
via the 'installsAfter' mechanism in devcontainer-feature.json.

# Function to install Claude Code CLI
install_claude_code() {
echo "Installing Claude Code CLI globally..."
Please check:
1. The devcontainer feature specification is correct
2. The Node.js feature (ghcr.io/devcontainers/features/node) is available
3. Your devcontainer build logs for errors

EOF
exit 1
fi

# Install with npm
npm install -g @anthropic-ai/claude-code
Expand All @@ -116,9 +48,24 @@ create_claude_directories() {
echo "Creating Claude configuration directories..."

# Determine the target user's home directory
# $_REMOTE_USER is set by devcontainer, fallback to 'vscode' or current user
local target_home="${_REMOTE_USER_HOME:-/home/${_REMOTE_USER:-vscode}}"
# $_REMOTE_USER is set by devcontainer, fallback to 'vscode'
local target_user="${_REMOTE_USER:-vscode}"
local target_home="${_REMOTE_USER_HOME:-/home/${target_user}}"

# Be defensive: if the resolved home does not exist, fall back to $HOME,
# then to /home/${target_user}, and finally to /tmp as a last resort.
if [ ! -d "$target_home" ]; then
if [ -n "${HOME:-}" ] && [ -d "$HOME" ]; then
echo "Warning: target_home '$target_home' does not exist, falling back to \$HOME: $HOME"
target_home="$HOME"
elif [ -d "/home/${target_user}" ]; then
echo "Warning: target_home '$target_home' does not exist, falling back to /home/${target_user}"
target_home="/home/${target_user}"
else
echo "Warning: No suitable home directory found for '${target_user}', falling back to /tmp"
target_home="/tmp"
fi
fi

echo "Target home directory: $target_home"
echo "Target user: $target_user"
Expand Down Expand Up @@ -152,44 +99,13 @@ create_claude_directories() {
echo "Claude directories created successfully"
}

# Print error message about requiring Node.js feature
print_nodejs_requirement() {
cat <<EOF

ERROR: Node.js and npm are required but could not be installed!
Please add the Node.js feature to your devcontainer.json:

"features": {
"ghcr.io/devcontainers/features/node:1": {},
"./claude-code": {}
}

EOF
exit 1
}

# Main script starts here
main() {
echo "========================================="
echo "Activating feature 'claude-code' (local)"
echo "========================================="

# Detect package manager
PKG_MANAGER=$(detect_package_manager)
echo "Detected package manager: $PKG_MANAGER"

# Check if Node.js and npm are available
if ! command -v node >/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
else
echo "Node.js and npm are already installed"
node --version
npm --version
fi

# Install Claude Code CLI
# Check if already installed to make this idempotent
# Install Claude Code CLI (or verify it's already installed)
if command -v claude >/dev/null; then
echo "Claude Code CLI is already installed"
claude --version
Expand Down
7 changes: 2 additions & 5 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
"name": "python_template",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"PIXI_VERSION": "v0.62.2"
}
"context": ".."
},
"customizations": {
"vscode": {
Expand All @@ -21,7 +18,7 @@
}
},
"features": {
"ghcr.io/devcontainers/features/node:1": {},
// "ghcr.io/devcontainers/features/node:1": {},
"./claude-code": {}
// "ghcr.io/devcontainers/features/docker-in-docker:2": {}
// "ghcr.io/devcontainers/features/common-utils:2": {},
Expand Down
Loading