@@ -5,95 +5,27 @@ set -eu
55# Based on: https://github.com/anthropics/devcontainer-features/pull/25
66# Combines CLI installation with configuration directory setup
77
8- # Function to detect the package manager and OS type
9- detect_package_manager () {
10- for pm in apt-get apk dnf yum; do
11- if command -v $pm > /dev/null; then
12- case $pm in
13- apt-get) echo " apt" ;;
14- * ) echo " $pm " ;;
15- esac
16- return 0
17- fi
18- done
19- echo " unknown"
20- return 1
21- }
8+ # Function to install Claude Code CLI
9+ install_claude_code () {
10+ echo " Installing Claude Code CLI globally..."
2211
23- # Function to install packages using the appropriate package manager
24- install_packages () {
25- local pkg_manager=" $1 "
26- shift
27- local packages=" $@ "
28-
29- case " $pkg_manager " in
30- apt)
31- apt-get update
32- apt-get install -y $packages
33- ;;
34- apk)
35- apk add --no-cache $packages
36- ;;
37- dnf|yum)
38- $pkg_manager install -y $packages
39- ;;
40- * )
41- echo " WARNING: Unsupported package manager. Cannot install packages: $packages "
42- return 1
43- ;;
44- esac
45-
46- return 0
47- }
12+ # Verify Node.js and npm are available
13+ if ! command -v node > /dev/null || ! command -v npm > /dev/null; then
14+ cat << EOF
4815
49- # Function to install Node.js
50- install_nodejs () {
51- local pkg_manager=" $1 "
52-
53- echo " Installing Node.js using $pkg_manager ..."
54-
55- case " $pkg_manager " in
56- apt)
57- # Debian/Ubuntu - install more recent Node.js LTS
58- install_packages apt " ca-certificates curl gnupg"
59- mkdir -p /etc/apt/keyrings
60- curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
61- 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
62- apt-get update
63- apt-get install -y nodejs
64- ;;
65- apk)
66- # Alpine
67- install_packages apk " nodejs npm"
68- ;;
69- dnf)
70- # Fedora/RHEL
71- install_packages dnf " nodejs npm"
72- ;;
73- yum)
74- # CentOS/RHEL
75- curl -sL https://rpm.nodesource.com/setup_18.x | bash -
76- yum install -y nodejs
77- ;;
78- * )
79- echo " ERROR: Unsupported package manager for Node.js installation"
80- return 1
81- ;;
82- esac
16+ ERROR: Node.js and npm are required but not found!
8317
84- # Verify installation
85- if command -v node > /dev/null && command -v npm > /dev/null; then
86- echo " Successfully installed Node.js and npm"
87- return 0
88- else
89- echo " Failed to install Node.js and npm"
90- return 1
91- fi
92- }
18+ This should not happen as the Node.js feature is automatically installed
19+ via the 'installsAfter' mechanism in devcontainer-feature.json.
9320
94- # Function to install Claude Code CLI
95- install_claude_code () {
96- echo " Installing Claude Code CLI globally..."
21+ Please check:
22+ 1. The devcontainer feature specification is correct
23+ 2. The Node.js feature (ghcr.io/devcontainers/features/node) is available
24+ 3. Your devcontainer build logs for errors
25+
26+ EOF
27+ exit 1
28+ fi
9729
9830 # Install with npm
9931 npm install -g @anthropic-ai/claude-code
@@ -116,9 +48,24 @@ create_claude_directories() {
11648 echo " Creating Claude configuration directories..."
11749
11850 # Determine the target user's home directory
119- # $_REMOTE_USER is set by devcontainer, fallback to 'vscode' or current user
120- local target_home=" ${_REMOTE_USER_HOME:-/ home/ ${_REMOTE_USER:- vscode} } "
51+ # $_REMOTE_USER is set by devcontainer, fallback to 'vscode'
12152 local target_user=" ${_REMOTE_USER:- vscode} "
53+ local target_home=" ${_REMOTE_USER_HOME:-/ home/ ${target_user} } "
54+
55+ # Be defensive: if the resolved home does not exist, fall back to $HOME,
56+ # then to /home/${target_user}, and finally to /tmp as a last resort.
57+ if [ ! -d " $target_home " ]; then
58+ if [ -n " ${HOME:- } " ] && [ -d " $HOME " ]; then
59+ echo " Warning: target_home '$target_home ' does not exist, falling back to \$ HOME: $HOME "
60+ target_home=" $HOME "
61+ elif [ -d " /home/${target_user} " ]; then
62+ echo " Warning: target_home '$target_home ' does not exist, falling back to /home/${target_user} "
63+ target_home=" /home/${target_user} "
64+ else
65+ echo " Warning: No suitable home directory found for '${target_user} ', falling back to /tmp"
66+ target_home=" /tmp"
67+ fi
68+ fi
12269
12370 echo " Target home directory: $target_home "
12471 echo " Target user: $target_user "
@@ -152,44 +99,13 @@ create_claude_directories() {
15299 echo " Claude directories created successfully"
153100}
154101
155- # Print error message about requiring Node.js feature
156- print_nodejs_requirement () {
157- cat << EOF
158-
159- ERROR: Node.js and npm are required but could not be installed!
160- Please add the Node.js feature to your devcontainer.json:
161-
162- "features": {
163- "ghcr.io/devcontainers/features/node:1": {},
164- "./claude-code": {}
165- }
166-
167- EOF
168- exit 1
169- }
170-
171102# Main script starts here
172103main () {
173104 echo " ========================================="
174105 echo " Activating feature 'claude-code' (local)"
175106 echo " ========================================="
176107
177- # Detect package manager
178- PKG_MANAGER=$( detect_package_manager)
179- echo " Detected package manager: $PKG_MANAGER "
180-
181- # Check if Node.js and npm are available
182- if ! command -v node > /dev/null || ! command -v npm > /dev/null; then
183- echo " Node.js or npm not found, attempting to install automatically..."
184- install_nodejs " $PKG_MANAGER " || print_nodejs_requirement
185- else
186- echo " Node.js and npm are already installed"
187- node --version
188- npm --version
189- fi
190-
191- # Install Claude Code CLI
192- # Check if already installed to make this idempotent
108+ # Install Claude Code CLI (or verify it's already installed)
193109 if command -v claude > /dev/null; then
194110 echo " Claude Code CLI is already installed"
195111 claude --version
0 commit comments