Skip to content
Merged
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
7 changes: 6 additions & 1 deletion src/claude-code/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "claude-code",
"version": "1.0.2",
"version": "1.1.0",
"name": "Claude Code CLI",
"description": "Installs the Claude Code CLI on a selectable channel.",
"documentationURL": "https://github.com/hansehart/devcontainer-features/tree/main/src/claude-code",
Expand All @@ -20,6 +20,11 @@
"type": "boolean",
"default": true,
"description": "Set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 to suppress telemetry and other non-essential network calls."
},
"settingsJson": {
"type": "string",
"default": "",
"description": "Claude settings as a JSON object, merged into settings.json."
}
},
"postCreateCommand": "/usr/local/share/claude-code/init.sh"
Expand Down
16 changes: 13 additions & 3 deletions src/claude-code/init.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail

# postCreate hook: create the state dir once the volume is mounted.
if [ -r /etc/profile.d/claude-code.sh ]; then . /etc/profile.d/claude-code.sh; fi
[ -n "${CLAUDE_CONFIG_DIR:-}" ] || exit 0
mkdir -p "${CLAUDE_CONFIG_DIR}"

# Create the state dir once its volume is mounted.
if [ -n "${CLAUDE_CONFIG_DIR:-}" ]; then mkdir -p "${CLAUDE_CONFIG_DIR}"; fi

# Merge the requested settings into settings.json (empty leaves it untouched).
req=/usr/local/share/claude-code/requested-settings.json
if [ -s "$req" ]; then
target="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
mkdir -p "$(dirname "$target")"
prev='{}'
if [ -f "$target" ]; then prev="$(cat "$target")"; fi
printf '%s' "$prev" | jq --argjson add "$(cat "$req")" '. + $add' > "$target"
fi
9 changes: 6 additions & 3 deletions src/claude-code/install.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail

# Options (uppercased by the CLI): VERSION, STATEDIR, DISABLENONESSENTIALTRAFFIC.
# Options (uppercased by the CLI): VERSION, STATEDIR, DISABLENONESSENTIALTRAFFIC, SETTINGSJSON.
STATE_DIR="$STATEDIR"
DISABLE_NONESSENTIAL_TRAFFIC="$DISABLENONESSENTIALTRAFFIC"
SETTINGS_JSON="$SETTINGSJSON"

export DEBIAN_FRONTEND=noninteractive

# Dependencies: packages this feature needs to install and run.
apt-get update
apt-get install -y --no-install-recommends \
ca-certificates \
curl
curl \
jq
rm -rf /var/lib/apt/lists/*

# Install: run the upstream installer as the dev user so claude lands in ~/.local/bin.
Expand All @@ -29,9 +31,10 @@ su - "$_REMOTE_USER" -c "curl -fsSL https://claude.ai/install.sh | bash -s -- '$
} > /etc/profile.d/claude-code.sh
chmod 0644 /etc/profile.d/claude-code.sh

# Hook: install the create-state-dir hook to run once at container create.
# Hook: install the run-once hook and save the requested settings for it to merge.
install -d /usr/local/share/claude-code
install -m 0755 "$(dirname "$0")/init.sh" /usr/local/share/claude-code/init.sh
printf '%s' "$SETTINGS_JSON" > /usr/local/share/claude-code/requested-settings.json

# Verify: claude resolves on PATH (as the dev user).
su - "$_REMOTE_USER" -c "claude --version"
10 changes: 10 additions & 0 deletions test/claude-code/scenarios.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"settings_json": {
"image": "ubuntu:24.04",
"features": {
"claude-code": {
"settingsJson": "{\\\"env\\\":{\\\"IS_DEMO\\\":\\\"1\\\"}}"
}
}
}
}
12 changes: 12 additions & 0 deletions test/claude-code/settings_json.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
set -e

source dev-container-features-test-lib

# The merge runs at postCreate, so invoke the hook here to apply the baked settings.
/usr/local/share/claude-code/init.sh

target="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json"
check "settings merged" jq -e '.env.IS_DEMO == "1"' "$target"

reportResults
Loading