codeforge-dev 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,6 +17,9 @@ SETUP_ALIASES=true
17
17
  # Setup: install official Anthropic plugins
18
18
  SETUP_PLUGINS=true
19
19
 
20
+ # Setup: auto-update Claude Code CLI to latest on container start (runs in background)
21
+ SETUP_UPDATE_CLAUDE=true
22
+
20
23
  # Plugin blacklist (comma-separated plugin names to skip during auto-install)
21
24
  # Example: PLUGIN_BLACKLIST="workflow-enhancer,auto-formatter"
22
- PLUGIN_BLACKLIST="workflow-enhancer"
25
+ PLUGIN_BLACKLIST="workflow-enhancer,planning-reminder"
@@ -1,5 +1,14 @@
1
1
  # CodeForge Devcontainer Changelog
2
2
 
3
+ ## [v1.5.2] - 2026-02-06
4
+
5
+ ### Fixed
6
+
7
+ - **cc/claude aliases**: Converted from shell functions to simple aliases — functions were not reliably invoked across shell contexts (tmux, docker exec, external terminals), causing Claude to launch without config
8
+ - **CLAUDE_CONFIG_DIR export**: Now exported in `.bashrc`/`.zshrc` directly, so credentials are found in all shells (not just VS Code terminals where `remoteEnv` applies)
9
+
10
+ ---
11
+
3
12
  ## [v1.5.0] - 2026-02-06
4
13
 
5
14
  ### Added
@@ -16,6 +25,10 @@
16
25
  - Creates `claude-teams` session on container start
17
26
  - **Biome feature**: Fast JS/TS/JSON/CSS formatter via global `@biomejs/biome` install
18
27
  - **External terminal connectors**: Bash (`.sh`) and PowerShell (`.ps1`) scripts to connect host terminals to devcontainer tmux sessions
28
+ - **Claude Code auto-update**: `setup-update-claude.sh` checks for newer Claude Code native binary on every container start
29
+ - Runs non-blocking in background via `setup.sh`
30
+ - Downloads from GCS, verifies SHA256 checksum, atomic binary replacement
31
+ - Controlled by `SETUP_UPDATE_CLAUDE` env var in `.env` (default: `true`)
19
32
 
20
33
  #### Plugins
21
34
  - **code-directive plugin**: Replaces `codedirective-skills` with expanded hook infrastructure
@@ -32,6 +45,7 @@
32
45
  - **Default model**: Claude Opus 4-5 → **Claude Opus 4-6** (frontier)
33
46
  - **Max output tokens**: 64,000 → **128,000**
34
47
  - **Container memory**: 3GB → **4GB** (`--memory-swap` raised to 8GB)
48
+ - **External terminal connectors**: Now run as `vscode` user and auto-launch `cc` on new tmux sessions
35
49
  - **Auto-formatter**: Switched from PostToolUse (`format-file.py`) to Stop hook (`format-on-stop.py`)
36
50
  - Added Biome support for JS/TS/CSS alongside existing Black and gofmt
37
51
  - Batch-formats all edited files when Claude stops instead of formatting on every edit
@@ -72,6 +72,15 @@ Write-Host ""
72
72
  Write-Host "======================================"
73
73
  Write-Host ""
74
74
 
75
- # Connect to container with tmux
76
- # -A attaches to existing session or creates new one
77
- docker exec -it $CONTAINER_ID tmux new-session -A -s $TMUX_SESSION
75
+ # Connect to container with tmux as vscode user (where aliases are defined)
76
+ # If session exists, reattach. Otherwise create in /workspaces and auto-run cc.
77
+ docker exec -it --user vscode $CONTAINER_ID bash -c "
78
+ if tmux has-session -t '$TMUX_SESSION' 2>/dev/null; then
79
+ tmux attach-session -t '$TMUX_SESSION'
80
+ else
81
+ tmux new-session -d -s '$TMUX_SESSION' -c /workspaces
82
+ sleep 0.5
83
+ tmux send-keys -t '$TMUX_SESSION' 'cc' Enter
84
+ tmux attach-session -t '$TMUX_SESSION'
85
+ fi
86
+ "
@@ -64,6 +64,15 @@ echo ""
64
64
  echo "======================================"
65
65
  echo ""
66
66
 
67
- # Connect to container with tmux
68
- # -A attaches to existing session or creates new one
69
- exec docker exec -it "$CONTAINER_ID" tmux new-session -A -s "$TMUX_SESSION"
67
+ # Connect to container with tmux as vscode user (where aliases are defined)
68
+ # If session exists, reattach. Otherwise create in /workspaces and auto-run cc.
69
+ exec docker exec -it --user vscode "$CONTAINER_ID" bash -c "
70
+ if tmux has-session -t '$TMUX_SESSION' 2>/dev/null; then
71
+ tmux attach-session -t '$TMUX_SESSION'
72
+ else
73
+ tmux new-session -d -s '$TMUX_SESSION' -c /workspaces
74
+ sleep 0.5
75
+ tmux send-keys -t '$TMUX_SESSION' 'cc' Enter
76
+ tmux attach-session -t '$TMUX_SESSION'
77
+ fi
78
+ "
@@ -1,80 +1,67 @@
1
1
  #!/bin/bash
2
- # Setup claude/cc functions for claude with local system prompt support
2
+ # Setup cc/claude/ccraw aliases for claude with local system prompt support
3
3
 
4
4
  CLAUDE_DIR="${CLAUDE_CONFIG_DIR:?CLAUDE_CONFIG_DIR not set}"
5
5
 
6
6
  echo "[setup-aliases] Configuring Claude aliases..."
7
7
 
8
- # Shared function for claude with local config (used by both cc and claude)
9
- CLAUDE_FUNCTION='_claude_with_config() {
10
- local LOCAL_PROMPT=".claude/system-prompt.md"
11
- local DEFAULT_PROMPT="/workspaces/.devcontainer/config/main-system-prompt.md"
12
- local LOCAL_SETTINGS=".claude/settings.json"
13
- local DEFAULT_SETTINGS="/workspaces/.devcontainer/config/settings.json"
14
-
15
- mkdir -p .claude
16
-
17
- if [ ! -f "$LOCAL_PROMPT" ]; then
18
- cp "$DEFAULT_PROMPT" "$LOCAL_PROMPT"
19
- echo "[claude] Created $LOCAL_PROMPT from default"
20
- fi
21
-
22
- if [ ! -f "$LOCAL_SETTINGS" ]; then
23
- cp "$DEFAULT_SETTINGS" "$LOCAL_SETTINGS"
24
- echo "[claude] Created $LOCAL_SETTINGS from default"
25
- fi
26
-
27
- command claude --system-prompt-file "$LOCAL_PROMPT" --permission-mode plan --allow-dangerously-skip-permissions "$@"
28
- }
29
-
30
- # cc: shorthand for claude with config
31
- cc() { _claude_with_config "$@"; }
32
-
33
- # claude: override to use config (use ccraw for vanilla)
34
- claude() { _claude_with_config "$@"; }
35
-
36
- # ccraw: vanilla claude without any config
37
- alias ccraw="command claude"'
8
+ # Simple alias definitions (not functions functions don't behave reliably across shell contexts)
9
+ ALIAS_CC='alias cc='"'"'command claude --system-prompt-file .claude/system-prompt.md --permission-mode plan --allow-dangerously-skip-permissions'"'"''
10
+ ALIAS_CLAUDE='alias claude='"'"'command claude --system-prompt-file .claude/system-prompt.md --permission-mode plan --allow-dangerously-skip-permissions'"'"''
11
+ ALIAS_CCRAW='alias ccraw="command claude"'
38
12
 
39
13
  for rc in ~/.bashrc ~/.zshrc; do
40
14
  if [ -f "$rc" ]; then
41
- # Remove old cc alias/function if present
15
+ # --- Cleanup old definitions ---
16
+
17
+ # Remove old cc alias
42
18
  if grep -q "alias cc=" "$rc" 2>/dev/null; then
43
19
  sed -i '/alias cc=/d' "$rc"
44
20
  echo "[setup-aliases] Removed old cc alias from $(basename $rc)"
45
21
  fi
22
+ # Remove old cc function (single-line or multi-line)
46
23
  if grep -q "^cc()" "$rc" 2>/dev/null; then
47
- # Remove old cc function (multi-line)
48
24
  sed -i '/^cc() {/,/^}/d' "$rc"
49
25
  echo "[setup-aliases] Removed old cc function from $(basename $rc)"
50
26
  fi
51
- # Remove old specwright alias if present
52
- if grep -q "alias specwright=" "$rc" 2>/dev/null; then
53
- sed -i '/alias specwright=/d' "$rc"
54
- echo "[setup-aliases] Removed specwright alias from $(basename $rc)"
55
- fi
56
- # Remove old _claude_with_config function if present
27
+ # Remove old _claude_with_config function
57
28
  if grep -q "^_claude_with_config()" "$rc" 2>/dev/null; then
58
29
  sed -i '/^_claude_with_config() {/,/^}/d' "$rc"
30
+ echo "[setup-aliases] Removed old _claude_with_config function from $(basename $rc)"
59
31
  fi
60
- # Remove old claude function override if present
32
+ # Remove old claude function override
61
33
  if grep -q "^claude() {" "$rc" 2>/dev/null; then
62
34
  sed -i '/^claude() { _claude_with_config/d' "$rc"
35
+ echo "[setup-aliases] Removed old claude function from $(basename $rc)"
36
+ fi
37
+ # Remove old claude alias
38
+ if grep -q "alias claude=" "$rc" 2>/dev/null; then
39
+ sed -i '/alias claude=/d' "$rc"
63
40
  fi
64
- # Remove old ccraw alias if present
41
+ # Remove old ccraw alias
65
42
  if grep -q "alias ccraw=" "$rc" 2>/dev/null; then
66
43
  sed -i '/alias ccraw=/d' "$rc"
67
44
  fi
68
- # Add functions if not present
69
- if ! grep -q "^_claude_with_config()" "$rc" 2>/dev/null; then
70
- echo "" >> "$rc"
71
- echo "$CLAUDE_FUNCTION" >> "$rc"
72
- echo "[setup-aliases] Added claude functions to $(basename $rc)"
45
+ # Remove old specwright alias
46
+ if grep -q "alias specwright=" "$rc" 2>/dev/null; then
47
+ sed -i '/alias specwright=/d' "$rc"
48
+ fi
49
+
50
+ # --- Add environment and aliases ---
51
+ echo "" >> "$rc"
52
+ echo "# Claude Code environment and aliases (managed by setup-aliases.sh)" >> "$rc"
53
+ # Export CLAUDE_CONFIG_DIR so it's available in all shells (not just VS Code remoteEnv)
54
+ if ! grep -q 'export CLAUDE_CONFIG_DIR=' "$rc" 2>/dev/null; then
55
+ echo "export CLAUDE_CONFIG_DIR=\"${CLAUDE_CONFIG_DIR}\"" >> "$rc"
73
56
  fi
57
+ echo "$ALIAS_CC" >> "$rc"
58
+ echo "$ALIAS_CLAUDE" >> "$rc"
59
+ echo "$ALIAS_CCRAW" >> "$rc"
60
+ echo "[setup-aliases] Added aliases to $(basename $rc)"
74
61
  fi
75
62
  done
76
63
 
77
64
  echo "[setup-aliases] Aliases configured:"
78
- echo " claude -> claude with local .claude/system-prompt.md (auto-created from defaults)"
79
- echo " cc -> shorthand for claude with config"
65
+ echo " cc -> claude with local .claude/system-prompt.md"
66
+ echo " claude -> claude with local .claude/system-prompt.md"
80
67
  echo " ccraw -> vanilla claude without any config"
@@ -0,0 +1,123 @@
1
+ #!/bin/bash
2
+ # Update Claude Code CLI to the latest version (native binary only)
3
+ # Runs non-blocking in background by default via setup.sh
4
+ # All failures are warnings — this script never blocks container startup
5
+
6
+ echo "[update-claude] Checking for Claude Code updates..."
7
+
8
+ # === CLEANUP TRAP ===
9
+ cleanup() {
10
+ rm -f /tmp/claude-update 2>/dev/null || true
11
+ rm -f /tmp/claude-update-manifest.json 2>/dev/null || true
12
+ }
13
+ trap cleanup EXIT
14
+
15
+ # === VERIFY CLAUDE IS INSTALLED ===
16
+ if ! command -v claude &>/dev/null; then
17
+ echo "[update-claude] Claude Code not found, skipping update"
18
+ exit 0
19
+ fi
20
+
21
+ # === DETECT INSTALL METHOD ===
22
+ CLAUDE_PATH=$(command -v claude)
23
+ if [[ "$CLAUDE_PATH" != "/usr/local/bin/claude" ]]; then
24
+ echo "[update-claude] Non-native install detected ($CLAUDE_PATH), skipping"
25
+ exit 0
26
+ fi
27
+
28
+ # === VALIDATE DEPENDENCIES ===
29
+ for dep in curl jq sha256sum sudo; do
30
+ if ! command -v "$dep" &>/dev/null; then
31
+ echo "[update-claude] WARNING: $dep not available, skipping update"
32
+ exit 0
33
+ fi
34
+ done
35
+
36
+ # === GET CURRENT VERSION ===
37
+ CURRENT_VERSION=$(claude --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")
38
+ echo "[update-claude] Current version: ${CURRENT_VERSION}"
39
+
40
+ # === FETCH LATEST VERSION ===
41
+ BASE_URL="https://storage.googleapis.com/claude-code-dist-86c565f3-f756-42ad-8dfa-d59b1c096819/claude-code-releases"
42
+
43
+ LATEST_VERSION=$(curl -fsSL "${BASE_URL}/stable" 2>/dev/null)
44
+ if [ -z "$LATEST_VERSION" ]; then
45
+ echo "[update-claude] WARNING: Failed to fetch latest version, skipping"
46
+ exit 0
47
+ fi
48
+
49
+ echo "[update-claude] Latest version: ${LATEST_VERSION}"
50
+
51
+ # === COMPARE VERSIONS ===
52
+ if [ "$CURRENT_VERSION" = "$LATEST_VERSION" ]; then
53
+ echo "[update-claude] Already up to date (${CURRENT_VERSION})"
54
+ exit 0
55
+ fi
56
+
57
+ echo "[update-claude] Updating from ${CURRENT_VERSION} to ${LATEST_VERSION}..."
58
+
59
+ # === DETECT PLATFORM ===
60
+ ARCH=$(uname -m)
61
+ case "${ARCH}" in
62
+ x86_64)
63
+ PLATFORM="linux-x64"
64
+ ;;
65
+ aarch64|arm64)
66
+ PLATFORM="linux-arm64"
67
+ ;;
68
+ *)
69
+ echo "[update-claude] WARNING: Unsupported architecture: ${ARCH}, skipping"
70
+ exit 0
71
+ ;;
72
+ esac
73
+
74
+ # Detect musl (Alpine Linux)
75
+ if ldd --version 2>&1 | grep -qi musl; then
76
+ PLATFORM="${PLATFORM}-musl"
77
+ fi
78
+
79
+ echo "[update-claude] Platform: ${PLATFORM}"
80
+
81
+ # === DOWNLOAD MANIFEST ===
82
+ MANIFEST_URL="${BASE_URL}/${LATEST_VERSION}/manifest.json"
83
+
84
+ if ! curl -fsSL "${MANIFEST_URL}" -o /tmp/claude-update-manifest.json 2>/dev/null; then
85
+ echo "[update-claude] WARNING: Failed to download manifest, skipping"
86
+ exit 0
87
+ fi
88
+
89
+ # === EXTRACT AND VERIFY CHECKSUM ===
90
+ EXPECTED_CHECKSUM=$(jq -r ".platforms.\"${PLATFORM}\".checksum" /tmp/claude-update-manifest.json)
91
+ if [ -z "${EXPECTED_CHECKSUM}" ] || [ "${EXPECTED_CHECKSUM}" = "null" ]; then
92
+ echo "[update-claude] WARNING: Platform ${PLATFORM} not found in manifest, skipping"
93
+ exit 0
94
+ fi
95
+
96
+ # === DOWNLOAD BINARY ===
97
+ BINARY_URL="${BASE_URL}/${LATEST_VERSION}/${PLATFORM}/claude"
98
+
99
+ if ! curl -fsSL "${BINARY_URL}" -o /tmp/claude-update 2>/dev/null; then
100
+ echo "[update-claude] WARNING: Failed to download binary, skipping"
101
+ exit 0
102
+ fi
103
+
104
+ # === VERIFY CHECKSUM ===
105
+ ACTUAL_CHECKSUM=$(sha256sum /tmp/claude-update | cut -d' ' -f1)
106
+
107
+ if [ "${ACTUAL_CHECKSUM}" != "${EXPECTED_CHECKSUM}" ]; then
108
+ echo "[update-claude] WARNING: Checksum verification failed, skipping"
109
+ echo "[update-claude] Expected: ${EXPECTED_CHECKSUM}"
110
+ echo "[update-claude] Actual: ${ACTUAL_CHECKSUM}"
111
+ exit 0
112
+ fi
113
+
114
+ # === INSTALL (atomic replace) ===
115
+ chmod +x /tmp/claude-update
116
+ if ! sudo mv /tmp/claude-update /usr/local/bin/claude; then
117
+ echo "[update-claude] WARNING: Failed to install update (sudo mv failed), skipping"
118
+ exit 0
119
+ fi
120
+
121
+ # === VERIFY UPDATE ===
122
+ INSTALLED_VERSION=$(claude --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "unknown")
123
+ echo "[update-claude] Updated Claude Code: ${CURRENT_VERSION} → ${INSTALLED_VERSION}"
@@ -21,8 +21,9 @@ fi
21
21
  : "${SETUP_ALIASES:=true}"
22
22
  : "${OVERWRITE_CONFIG:=false}"
23
23
  : "${SETUP_PLUGINS:=true}"
24
+ : "${SETUP_UPDATE_CLAUDE:=true}"
24
25
 
25
- export CLAUDE_CONFIG_DIR CONFIG_SOURCE_DIR SETUP_CONFIG SETUP_ALIASES OVERWRITE_CONFIG SETUP_PLUGINS
26
+ export CLAUDE_CONFIG_DIR CONFIG_SOURCE_DIR SETUP_CONFIG SETUP_ALIASES OVERWRITE_CONFIG SETUP_PLUGINS SETUP_UPDATE_CLAUDE
26
27
 
27
28
 
28
29
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@@ -53,6 +54,17 @@ run_script "$SCRIPT_DIR/setup-aliases.sh" "$SETUP_ALIASES"
53
54
  run_script "$SCRIPT_DIR/setup-plugins.sh" "$SETUP_PLUGINS"
54
55
  run_script "$SCRIPT_DIR/setup-irie-claude.sh" "true"
55
56
 
57
+ # Non-blocking: check for Claude Code updates in background
58
+ if [ "$SETUP_UPDATE_CLAUDE" = "true" ]; then
59
+ if [ -f "$SCRIPT_DIR/setup-update-claude.sh" ]; then
60
+ echo "Running setup-update-claude (background)..."
61
+ bash "$SCRIPT_DIR/setup-update-claude.sh" &
62
+ disown
63
+ fi
64
+ else
65
+ echo "Skipping setup-update-claude (disabled)"
66
+ fi
67
+
56
68
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
57
69
  echo " Setup Complete"
58
70
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeforge-dev",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "Complete development container that sets up Claude Code with modular devcontainer features, modern dev tools, and persistent configurations. Drop it into any project and get a production-ready AI development environment in minutes.",
5
5
  "main": "setup.js",
6
6
  "bin": {