claudepod 1.0.2 → 1.1.1

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.
@@ -6,59 +6,152 @@ set -euo pipefail
6
6
 
7
7
  echo "🚀 Starting ClaudePod post-create setup..."
8
8
 
9
- # Source NVM to make npm available
10
- # The Node.js feature installs via NVM at /usr/local/share/nvm
11
- export NVM_DIR="/usr/local/share/nvm"
12
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
9
+ # Source environment file if it exists
10
+ if [ -f "/workspace/.devcontainer/.env" ]; then
11
+ echo "📋 Loading environment variables from .devcontainer/.env"
12
+ set -a # Export all variables
13
+ source "/workspace/.devcontainer/.env"
14
+ set +a # Stop exporting
15
+ fi
16
+
17
+ # Source shared utility functions
18
+ source "/workspace/.devcontainer/scripts/utils.sh"
19
+
20
+ # State tracking directory
21
+ STATE_DIR="/workspace/.devcontainer/state"
13
22
 
14
- # Retry function for resilient installations
15
- retry_command() {
16
- local max_attempts=${1:-3}
17
- local delay=${2:-5}
18
- shift 2
19
- local attempt=1
23
+ # Function to create state marker
24
+ create_state_marker() {
25
+ local component="$1"
26
+ local method="${2:-unknown}"
20
27
 
21
- while [ $attempt -le $max_attempts ]; do
22
- if "$@"; then
23
- return 0
24
- fi
25
- echo "⚠️ Command failed (attempt $attempt/$max_attempts): $*"
26
- if [ $attempt -lt $max_attempts ]; then
27
- echo " Retrying in ${delay}s..."
28
- sleep $delay
29
- fi
30
- ((attempt++))
31
- done
32
- return 1
28
+ mkdir -p "$STATE_DIR"
29
+ echo "$(date '+%Y-%m-%d %H:%M:%S') - $method" > "$STATE_DIR/${component}.installed"
30
+ chown -R node:node "$STATE_DIR"
33
31
  }
34
32
 
35
- # Function to install Claude Code
36
- install_claude_code() {
37
- echo "📦 Installing Claude Code..."
33
+ # Function to check if component is already installed
34
+ is_component_installed() {
35
+ local component="$1"
38
36
 
39
- # Ensure PATH includes npm global bin directory
40
- export PATH="/home/node/.local/bin:$PATH"
37
+ [ -f "$STATE_DIR/${component}.installed" ]
38
+ }
39
+
40
+ # Source configuration modules
41
+ source "/workspace/.devcontainer/scripts/config/claude-core.sh"
42
+ source "/workspace/.devcontainer/scripts/config/serena.sh"
43
+ source "/workspace/.devcontainer/scripts/config/taskmaster.sh"
44
+ source "/workspace/.devcontainer/scripts/config/searxng.sh"
45
+
46
+ # Source installation modules
47
+ source "/workspace/.devcontainer/scripts/install/claude-code.sh"
48
+
49
+ # Source NVM to make Node.js and npm available
50
+ export NVM_DIR="/usr/local/share/nvm"
51
+ # Wait for NVM to be available (up to 30 seconds)
52
+ for i in {1..30}; do
53
+ [ -s "$NVM_DIR/nvm.sh" ] && break
54
+ echo "⏳ Waiting for NVM installation... (attempt $i/30)"
55
+ sleep 1
56
+ done
57
+
58
+ if [ -s "$NVM_DIR/nvm.sh" ]; then
59
+ echo "🔧 Sourcing NVM..."
60
+ . "$NVM_DIR/nvm.sh"
41
61
 
42
- # Install Claude Code globally with retry logic
43
- if retry_command 3 5 npm install -g @anthropic-ai/claude-code; then
44
- echo "✅ Claude Code installed successfully"
62
+ # Verify npm is now available
63
+ if command -v npm &> /dev/null; then
64
+ echo "✅ npm is available: $(which npm)"
65
+ echo "📌 npm version: $(npm --version)"
66
+ echo "📌 node version: $(node --version)"
45
67
 
46
- # Verify installation with updated PATH
47
- if command -v claude &> /dev/null || [ -f "/home/node/.local/bin/claude" ]; then
48
- local version=$(/home/node/.local/bin/claude --version 2>/dev/null || echo "installed")
49
- echo "📌 Claude Code version: $version"
50
- return 0
51
- else
52
- echo "⚠️ Claude Code installed but 'claude' command not found"
53
- echo "📍 Checking installation location..."
54
- find /home/node/.local -name "claude" -type f 2>/dev/null || echo " No claude binary found"
55
- return 1
68
+ # Setup npm permissions immediately after npm becomes available
69
+ echo "🔧 Setting up npm directories and permissions..."
70
+
71
+ # Create npm directories with correct ownership
72
+ npm_dirs=(
73
+ "/home/node/.npm"
74
+ "/home/node/.npm/_cacache"
75
+ "/home/node/.npm/_logs"
76
+ "/home/node/.config"
77
+ "/home/node/.local"
78
+ "/home/node/.local/bin"
79
+ "/home/node/.cache"
80
+ )
81
+
82
+ for dir in "${npm_dirs[@]}"; do
83
+ mkdir -p "$dir"
84
+ chown -R node:node "$dir"
85
+ chmod -R 755 "$dir"
86
+ done
87
+
88
+ # Remove any existing .npmrc directory/file and create .npmrc file
89
+ # Use NVM-compatible configuration (no prefix setting to avoid NVM conflicts)
90
+ rm -rf /home/node/.npmrc
91
+
92
+ # Also clear any existing npm config that might conflict with NVM
93
+ npm config delete prefix 2>/dev/null || true
94
+ npm config delete globalconfig 2>/dev/null || true
95
+
96
+ cat > /home/node/.npmrc << 'EOF'
97
+ cache=/home/node/.npm/_cacache
98
+ update-notifier=false
99
+ # Note: prefix and globalconfig settings removed to avoid NVM conflicts
100
+ EOF
101
+
102
+ # Set environment variable to suppress NVM warnings about prefix
103
+ export NVM_SUPPRESS_PREFIX_WARNING=1
104
+ echo "export NVM_SUPPRESS_PREFIX_WARNING=1" >> /home/node/.profile
105
+ echo "export NVM_SUPPRESS_PREFIX_WARNING=1" >> /home/node/.bashrc
106
+ echo "export NVM_SUPPRESS_PREFIX_WARNING=1" >> /home/node/.zshrc
107
+
108
+ # Set proper ownership for .npmrc
109
+ chown node:node /home/node/.npmrc
110
+ chmod 644 /home/node/.npmrc
111
+
112
+ # Fix NVM symlink permissions issue PROPERLY
113
+ echo "🔧 Fixing NVM symlink permissions..."
114
+ if [ -d "/usr/local/share/nvm" ]; then
115
+ # Remove the problematic root-owned symlink if it exists
116
+ rm -f "/usr/local/share/nvm/current" 2>/dev/null || true
117
+
118
+ # More aggressive permissions fix: make node user owner of NVM directory
119
+ chown -R node:node "/usr/local/share/nvm"
120
+ chmod -R 755 "/usr/local/share/nvm"
121
+
122
+ # Pre-create the current symlink as the node user to avoid permission issues
123
+ if command -v node &> /dev/null; then
124
+ node_version=$(node --version | sed 's/v//')
125
+ node_path="/usr/local/share/nvm/versions/node/v${node_version}"
126
+ if [ -d "$node_path" ]; then
127
+ ln -sf "$node_path" "/usr/local/share/nvm/current" 2>/dev/null || true
128
+ chown -h node:node "/usr/local/share/nvm/current" 2>/dev/null || true
129
+ fi
130
+ fi
131
+
132
+ echo "✅ NVM directory now owned by node user with symlink pre-created"
56
133
  fi
134
+
135
+ echo "✅ npm directories and permissions configured (NVM conflicts resolved)"
57
136
  else
58
- echo "❌ Failed to install Claude Code after multiple attempts"
59
- return 1
137
+ echo "❌ npm still not found after sourcing NVM"
138
+ exit 1
60
139
  fi
61
- }
140
+ else
141
+ echo "❌ NVM not found at $NVM_DIR/nvm.sh"
142
+ exit 1
143
+ fi
144
+
145
+ # Set environment for Node.js operations (using PATH helper to avoid duplicates)
146
+ add_to_path "/home/node/.local/bin"
147
+ export npm_config_prefix="/home/node/.local"
148
+
149
+ # Claude Code installation is now handled by focused functions:
150
+ # - install_claude_code_native(): Native binary installation
151
+ # - install_claude_code_npm(): NPM fallback installation
152
+ # - verify_claude_installation(): Installation verification
153
+ # - install_claude_code(): Main orchestrator function
154
+ # See: /workspace/.devcontainer/scripts/install/claude-code.sh
62
155
 
63
156
  # Function to setup workspace directories for bind mounts
64
157
  setup_workspace_directories() {
@@ -144,60 +237,379 @@ EOF
144
237
  fi
145
238
  }
146
239
 
147
- # Function to setup Claude configuration directory
148
- setup_claude_config() {
149
- echo "🔧 Setting up Claude configuration..."
240
+ # Function to create configuration backup
241
+ create_config_backup() {
242
+ local config_file="$1"
243
+ local backup_dir="/workspace/.devcontainer/config/backups"
244
+
245
+ if [ -f "$config_file" ]; then
246
+ mkdir -p "$backup_dir"
247
+ local filename=$(basename "$config_file")
248
+ # Include path to distinguish home vs workspace configs
249
+ local path_prefix=$(echo "$config_file" | sed 's|/|_|g' | sed 's|^_||')
250
+ local timestamp=$(date +"%Y%m%d_%H%M%S")
251
+ local backup_file="${backup_dir}/${path_prefix}.${timestamp}.backup"
252
+
253
+ cp "$config_file" "$backup_file"
254
+ chown node:node "$backup_file"
255
+ chmod 600 "$backup_file"
256
+ echo "📦 Created backup: $backup_file"
257
+
258
+ # Keep only the last 5 backups for each unique file path
259
+ local base_name="${backup_dir}/${path_prefix}"
260
+ ls -t ${base_name}.*.backup 2>/dev/null | tail -n +6 | xargs -r rm -f
261
+ fi
262
+ }
263
+
264
+ # Configuration is now handled by focused modules:
265
+ # - claude-core.sh: Claude directory and core config files
266
+ # - serena.sh: Serena MCP server configuration
267
+ # - taskmaster.sh: TaskMaster AI configuration
268
+
269
+ # Function to install ccusage CLI tool
270
+ install_ccusage() {
271
+ # Check if ccusage is already installed
272
+ if is_component_installed "ccusage"; then
273
+ echo "✅ ccusage already installed (marker found)"
274
+ if command -v ccusage &> /dev/null; then
275
+ local version=$(ccusage --version 2>/dev/null || echo "installed")
276
+ echo "📌 ccusage version: $version"
277
+ return 0
278
+ else
279
+ echo "⚠️ Marker exists but verification failed, reinstalling..."
280
+ rm -f "$STATE_DIR/ccusage.installed"
281
+ fi
282
+ fi
150
283
 
151
- # Claude Code uses multiple possible config locations
152
- local claude_dirs=(
153
- "/home/node/.claude"
154
- "/home/node/.config/claude"
284
+ echo "📊 Installing ccusage..."
285
+
286
+ # Ensure npm uses the correct directories for the node user
287
+ export npm_config_prefix="/home/node/.local"
288
+
289
+ # Task 1: Clean ccusage directory conflicts before installation attempts
290
+ echo "🧹 Cleaning any existing ccusage directories to prevent ENOTEMPTY errors..."
291
+ local ccusage_dirs=(
292
+ "/home/node/.local/lib/node_modules/ccusage"
293
+ "/home/node/.local/lib/node_modules/.ccusage-*"
294
+ "/home/node/.npm/_cacache/index-v5/*/ccusage"
155
295
  )
156
296
 
157
- for dir in "${claude_dirs[@]}"; do
158
- if [ ! -d "$dir" ]; then
159
- mkdir -p "$dir"
160
- echo "📁 Created configuration directory: $dir"
297
+ for pattern in "${ccusage_dirs[@]}"; do
298
+ if [ -d "$pattern" ] || ls $pattern >/dev/null 2>&1; then
299
+ echo "🗑️ Removing existing directory: $pattern"
300
+ rm -rf $pattern 2>/dev/null || true
161
301
  fi
162
- # Set proper permissions
163
- chown -R node:node "$dir"
164
- chmod -R 700 "$dir"
165
302
  done
166
303
 
167
- # Copy optimized settings.json from devcontainer config
168
- local settings_source="/workspace/.devcontainer/config/claude/settings.json"
169
- local settings_target="/home/node/.claude/settings.json"
304
+ # Clear npm cache for ccusage specifically
305
+ npm cache clean --force --silent 2>/dev/null || true
306
+
307
+ # Task 2: Add proper error handling for npm ENOTEMPTY issues
308
+ echo "📦 Attempting ccusage installation with ENOTEMPTY error handling..."
309
+ local install_success=false
310
+ local attempts=3
311
+
312
+ for attempt in $(seq 1 $attempts); do
313
+ echo "📦 Installation attempt $attempt/$attempts..."
314
+
315
+ if npm install -g ccusage 2>/dev/null; then
316
+ install_success=true
317
+ break
318
+ else
319
+ local exit_code=$?
320
+
321
+ # Check for ENOTEMPTY error in npm logs
322
+ local latest_log=$(find /home/node/.npm/_logs -name "*debug*.log" -type f -exec ls -t {} + | head -1 2>/dev/null)
323
+ if [ -n "$latest_log" ] && grep -q "ENOTEMPTY" "$latest_log" 2>/dev/null; then
324
+ echo "⚠️ ENOTEMPTY error detected, cleaning npm directories..."
325
+
326
+ # Remove conflicting directories more aggressively
327
+ rm -rf /home/node/.local/lib/node_modules/ccusage* 2>/dev/null || true
328
+ rm -rf /home/node/.local/lib/node_modules/.ccusage* 2>/dev/null || true
329
+
330
+ # Clear npm cache completely
331
+ npm cache clean --force --silent 2>/dev/null || true
332
+ rm -rf /home/node/.npm/_cacache/* 2>/dev/null || true
333
+
334
+ if [ $attempt -lt $attempts ]; then
335
+ echo "🔄 Retrying installation after cleanup..."
336
+ sleep 2
337
+ fi
338
+ else
339
+ echo "⚠️ Installation failed with exit code $exit_code (attempt $attempt/$attempts)"
340
+ if [ $attempt -lt $attempts ]; then
341
+ echo "🔄 Retrying installation..."
342
+ sleep 2
343
+ fi
344
+ fi
345
+ fi
346
+ done
170
347
 
171
- if [ -f "$settings_source" ]; then
172
- cp "$settings_source" "$settings_target"
173
- chown node:node "$settings_target"
174
- chmod 600 "$settings_target"
175
- echo "📋 Copied optimized Claude settings (79 tools allowed)"
348
+ if [ "$install_success" = "true" ]; then
349
+ echo " ccusage installed successfully"
350
+
351
+ # Task 3: Verify installations work after fixes
352
+ echo "🔍 Performing comprehensive installation verification..."
353
+
354
+ # Wait for filesystem consistency
355
+ sleep 1
356
+
357
+ # Check multiple installation indicators
358
+ local verification_passed=false
359
+ local ccusage_bin="/home/node/.local/bin/ccusage"
360
+ local ccusage_module="/home/node/.local/lib/node_modules/ccusage"
361
+
362
+ if [ -f "$ccusage_bin" ] && [ -d "$ccusage_module" ]; then
363
+ echo "✓ Binary and module directory both exist"
364
+
365
+ # Test if the command actually works
366
+ if "$ccusage_bin" --version >/dev/null 2>&1; then
367
+ local version=$("$ccusage_bin" --version 2>/dev/null || echo "installed")
368
+ echo "📌 ccusage version: $version"
369
+ echo "✓ Command execution test passed"
370
+ verification_passed=true
371
+ else
372
+ echo "⚠️ Binary exists but command execution failed"
373
+ fi
374
+ elif command -v ccusage &> /dev/null; then
375
+ local version=$(ccusage --version 2>/dev/null || echo "installed")
376
+ echo "📌 ccusage version: $version"
377
+ echo "✓ Command found in PATH"
378
+ verification_passed=true
379
+ else
380
+ echo "❌ Installation verification failed:"
381
+ echo " - Binary check: $([ -f "$ccusage_bin" ] && echo "FOUND" || echo "MISSING")"
382
+ echo " - Module check: $([ -d "$ccusage_module" ] && echo "FOUND" || echo "MISSING")"
383
+ echo " - PATH check: $(command -v ccusage &> /dev/null && echo "FOUND" || echo "MISSING")"
384
+ fi
385
+
386
+ if [ "$verification_passed" = "true" ]; then
387
+ echo "✅ ccusage installation verification passed"
388
+ create_state_marker "ccusage" "npm"
389
+ return 0
390
+ else
391
+ echo "❌ ccusage installation verification failed"
392
+ return 1
393
+ fi
176
394
  else
177
- echo "⚠️ Claude settings template not found, using defaults"
395
+ echo " Failed to install ccusage after $attempts attempts"
396
+ echo "💡 Manual installation command: npm install -g ccusage"
397
+ return 1
398
+ fi
399
+ }
400
+
401
+ # Function to install cchistory CLI tool
402
+ install_cchistory() {
403
+ # Check if cchistory is already installed
404
+ if is_component_installed "cchistory"; then
405
+ echo "✅ cchistory already installed (marker found)"
406
+ if command -v cchistory &> /dev/null; then
407
+ local version=$(cchistory --help 2>/dev/null | grep -i version || echo "installed")
408
+ echo "📌 cchistory version: installed"
409
+ return 0
410
+ else
411
+ echo "⚠️ Marker exists but verification failed, reinstalling..."
412
+ rm -f "$STATE_DIR/cchistory.installed"
413
+ fi
178
414
  fi
179
415
 
180
- echo " Claude configuration directories ready"
416
+ echo "📊 Installing cchistory (Claude Code prompt analyzer)..."
417
+
418
+ # Ensure npm uses the correct directories for the node user
419
+ export npm_config_prefix="/home/node/.local"
420
+
421
+ # Clean any existing cchistory directories to prevent conflicts
422
+ echo "🧹 Cleaning any existing cchistory directories..."
423
+ local cchistory_dirs=(
424
+ "/home/node/.local/lib/node_modules/@mariozechner/cchistory"
425
+ "/home/node/.local/lib/node_modules/.@mariozechner-cchistory-*"
426
+ "/home/node/.npm/_cacache/index-v5/*/cchistory"
427
+ )
428
+
429
+ for pattern in "${cchistory_dirs[@]}"; do
430
+ if [ -d "$pattern" ] || ls $pattern >/dev/null 2>&1; then
431
+ echo "🗑️ Removing existing directory: $pattern"
432
+ rm -rf $pattern 2>/dev/null || true
433
+ fi
434
+ done
435
+
436
+ # Install cchistory with error handling
437
+ echo "📦 Attempting cchistory installation..."
438
+ local install_success=false
439
+ local attempts=2
440
+
441
+ for attempt in $(seq 1 $attempts); do
442
+ echo "📦 Installation attempt $attempt/$attempts..."
443
+
444
+ if npm install -g @mariozechner/cchistory 2>/dev/null; then
445
+ install_success=true
446
+ break
447
+ else
448
+ local exit_code=$?
449
+ echo "⚠️ Installation failed with exit code $exit_code (attempt $attempt/$attempts)"
450
+ if [ $attempt -lt $attempts ]; then
451
+ echo "🔄 Retrying installation..."
452
+ sleep 2
453
+ fi
454
+ fi
455
+ done
456
+
457
+ if [ "$install_success" = "true" ]; then
458
+ echo "✅ cchistory installed successfully"
459
+
460
+ # Verify installation
461
+ echo "🔍 Verifying cchistory installation..."
462
+
463
+ # Wait for filesystem consistency
464
+ sleep 1
465
+
466
+ # Check installation indicators
467
+ local verification_passed=false
468
+ local cchistory_bin="/home/node/.local/bin/cchistory"
469
+ local cchistory_module="/home/node/.local/lib/node_modules/@mariozechner/cchistory"
470
+
471
+ if [ -f "$cchistory_bin" ] && [ -d "$cchistory_module" ]; then
472
+ echo "✓ Binary and module directory both exist"
473
+
474
+ # Test if the command actually works
475
+ if "$cchistory_bin" --help >/dev/null 2>&1; then
476
+ echo "📌 cchistory: Claude Code prompt analyzer"
477
+ echo "✓ Command execution test passed"
478
+ verification_passed=true
479
+ else
480
+ echo "⚠️ Binary exists but command execution failed"
481
+ fi
482
+ elif command -v cchistory &> /dev/null; then
483
+ echo "📌 cchistory: Claude Code prompt analyzer"
484
+ echo "✓ Command found in PATH"
485
+ verification_passed=true
486
+ else
487
+ echo "❌ Installation verification failed:"
488
+ echo " - Binary check: $([ -f "$cchistory_bin" ] && echo "FOUND" || echo "MISSING")"
489
+ echo " - Module check: $([ -d "$cchistory_module" ] && echo "FOUND" || echo "MISSING")"
490
+ echo " - PATH check: $(command -v cchistory &> /dev/null && echo "FOUND" || echo "MISSING")"
491
+ fi
492
+
493
+ if [ "$verification_passed" = "true" ]; then
494
+ echo "✅ cchistory installation verification passed"
495
+ create_state_marker "cchistory" "npm"
496
+ return 0
497
+ else
498
+ echo "❌ cchistory installation verification failed"
499
+ return 1
500
+ fi
501
+ else
502
+ echo "❌ Failed to install cchistory after $attempts attempts"
503
+ echo "💡 Manual installation command: npm install -g @mariozechner/cchistory"
504
+ return 1
505
+ fi
181
506
  }
182
507
 
183
- # Function to install ccusage CLI tool
184
- install_ccusage() {
185
- echo "📊 Installing ccusage..."
508
+ # Function to install claude-trace CLI tool
509
+ install_claude_trace() {
510
+ # Check if claude-trace is already installed
511
+ if is_component_installed "claude-trace"; then
512
+ echo "✅ claude-trace already installed (marker found)"
513
+ if command -v claude-trace &> /dev/null; then
514
+ local version=$(claude-trace --version 2>/dev/null || echo "installed")
515
+ echo "📌 claude-trace version: $version"
516
+ return 0
517
+ else
518
+ echo "⚠️ Marker exists but verification failed, reinstalling..."
519
+ rm -f "$STATE_DIR/claude-trace.installed"
520
+ fi
521
+ fi
186
522
 
187
- if retry_command 3 5 npm install -g ccusage; then
188
- echo "✅ ccusage installed successfully"
523
+ echo "🔍 Installing claude-trace (Claude Code interaction recorder)..."
524
+
525
+ # Ensure npm uses the correct directories for the node user
526
+ export npm_config_prefix="/home/node/.local"
527
+
528
+ # Clean any existing claude-trace directories to prevent conflicts
529
+ echo "🧹 Cleaning any existing claude-trace directories..."
530
+ local claude_trace_dirs=(
531
+ "/home/node/.local/lib/node_modules/@mariozechner/claude-trace"
532
+ "/home/node/.local/lib/node_modules/.@mariozechner-claude-trace-*"
533
+ "/home/node/.npm/_cacache/index-v5/*/claude-trace"
534
+ )
535
+
536
+ for pattern in "${claude_trace_dirs[@]}"; do
537
+ if [ -d "$pattern" ] || ls $pattern >/dev/null 2>&1; then
538
+ echo "🗑️ Removing existing directory: $pattern"
539
+ rm -rf $pattern 2>/dev/null || true
540
+ fi
541
+ done
542
+
543
+ # Install claude-trace with error handling
544
+ echo "📦 Attempting claude-trace installation..."
545
+ local install_success=false
546
+ local attempts=2
547
+
548
+ for attempt in $(seq 1 $attempts); do
549
+ echo "📦 Installation attempt $attempt/$attempts..."
550
+
551
+ if npm install -g @mariozechner/claude-trace 2>/dev/null; then
552
+ install_success=true
553
+ break
554
+ else
555
+ local exit_code=$?
556
+ echo "⚠️ Installation failed with exit code $exit_code (attempt $attempt/$attempts)"
557
+ if [ $attempt -lt $attempts ]; then
558
+ echo "🔄 Retrying installation..."
559
+ sleep 2
560
+ fi
561
+ fi
562
+ done
563
+
564
+ if [ "$install_success" = "true" ]; then
565
+ echo "✅ claude-trace installed successfully"
189
566
 
190
567
  # Verify installation
191
- if [ -f "/home/node/.local/bin/ccusage" ] || command -v ccusage &> /dev/null; then
192
- local version=$(/home/node/.local/bin/ccusage --version 2>/dev/null || echo "installed")
193
- echo "📌 ccusage version: $version"
568
+ echo "🔍 Verifying claude-trace installation..."
569
+
570
+ # Wait for filesystem consistency
571
+ sleep 1
572
+
573
+ # Check installation indicators
574
+ local verification_passed=false
575
+ local claude_trace_bin="/home/node/.local/bin/claude-trace"
576
+ local claude_trace_module="/home/node/.local/lib/node_modules/@mariozechner/claude-trace"
577
+
578
+ if [ -f "$claude_trace_bin" ] && [ -d "$claude_trace_module" ]; then
579
+ echo "✓ Binary and module directory both exist"
580
+
581
+ # Test if the command actually works
582
+ if "$claude_trace_bin" --version >/dev/null 2>&1; then
583
+ local version=$("$claude_trace_bin" --version 2>/dev/null || echo "installed")
584
+ echo "📌 claude-trace version: $version"
585
+ echo "✓ Command execution test passed"
586
+ verification_passed=true
587
+ else
588
+ echo "⚠️ Binary exists but command execution failed"
589
+ fi
590
+ elif command -v claude-trace &> /dev/null; then
591
+ local version=$(claude-trace --version 2>/dev/null || echo "installed")
592
+ echo "📌 claude-trace version: $version"
593
+ echo "✓ Command found in PATH"
594
+ verification_passed=true
595
+ else
596
+ echo "❌ Installation verification failed:"
597
+ echo " - Binary check: $([ -f "$claude_trace_bin" ] && echo "FOUND" || echo "MISSING")"
598
+ echo " - Module check: $([ -d "$claude_trace_module" ] && echo "FOUND" || echo "MISSING")"
599
+ echo " - PATH check: $(command -v claude-trace &> /dev/null && echo "FOUND" || echo "MISSING")"
600
+ fi
601
+
602
+ if [ "$verification_passed" = "true" ]; then
603
+ echo "✅ claude-trace installation verification passed"
604
+ create_state_marker "claude-trace" "npm"
194
605
  return 0
195
606
  else
196
- echo "⚠️ ccusage installed but command not found"
607
+ echo " claude-trace installation verification failed"
197
608
  return 1
198
609
  fi
199
610
  else
200
- echo "❌ Failed to install ccusage"
611
+ echo "❌ Failed to install claude-trace after $attempts attempts"
612
+ echo "💡 Manual installation command: npm install -g @mariozechner/claude-trace"
201
613
  return 1
202
614
  fi
203
615
  }
@@ -206,30 +618,52 @@ install_ccusage() {
206
618
  install_dev_tools() {
207
619
  echo "🛠️ Installing additional development tools..."
208
620
 
209
- # Install git-delta for better git diffs
210
- echo "📦 Installing git-delta..."
211
- if command -v cargo &> /dev/null; then
212
- # If cargo is available, use it
213
- cargo install git-delta
214
- else
215
- # Otherwise, download the binary
216
- local delta_version="0.18.2"
217
- local delta_url="https://github.com/dandavison/delta/releases/download/${delta_version}/delta-${delta_version}-x86_64-unknown-linux-musl.tar.gz"
218
-
219
- if retry_command 2 5 wget -q -O /tmp/delta.tar.gz "$delta_url"; then
220
- sudo tar -xzf /tmp/delta.tar.gz -C /usr/local/bin delta-${delta_version}-x86_64-unknown-linux-musl/delta --strip-components=1
221
- sudo chmod +x /usr/local/bin/delta
222
- rm -f /tmp/delta.tar.gz
223
- echo "✅ git-delta installed successfully"
224
-
225
- # Configure git to use delta
621
+ # Install git-delta for better git diffs
622
+ if command -v delta &> /dev/null; then
623
+ echo "✅ git-delta already installed"
624
+ # Still check and configure git if needed
625
+ current_pager=$(git config --global core.pager 2>/dev/null || echo "")
626
+ if [ "$current_pager" != "delta" ]; then
627
+ echo "🔧 Configuring git to use delta..."
226
628
  git config --global core.pager "delta"
227
629
  git config --global interactive.diffFilter "delta --color-only"
228
630
  git config --global delta.navigate true
229
631
  git config --global delta.light false
230
632
  git config --global delta.side-by-side true
231
633
  else
232
- echo "⚠️ Failed to install git-delta"
634
+ echo " Git already configured to use delta"
635
+ fi
636
+ else
637
+ echo "📦 Installing git-delta..."
638
+ if command -v cargo &> /dev/null; then
639
+ # If cargo is available, use it
640
+ cargo install git-delta
641
+ else
642
+ # Otherwise, download the binary
643
+ delta_version="0.18.2"
644
+ delta_url="https://github.com/dandavison/delta/releases/download/${delta_version}/delta-${delta_version}-x86_64-unknown-linux-musl.tar.gz"
645
+
646
+ if retry_command 2 5 wget -q -O /tmp/delta.tar.gz "$delta_url"; then
647
+ sudo tar -xzf /tmp/delta.tar.gz -C /usr/local/bin delta-${delta_version}-x86_64-unknown-linux-musl/delta --strip-components=1
648
+ sudo chmod +x /usr/local/bin/delta
649
+ rm -f /tmp/delta.tar.gz
650
+ echo "✅ git-delta installed successfully"
651
+
652
+ # Configure git to use delta (idempotent)
653
+ current_pager=$(git config --global core.pager 2>/dev/null || echo "")
654
+ if [ "$current_pager" != "delta" ]; then
655
+ echo "🔧 Configuring git to use delta..."
656
+ git config --global core.pager "delta"
657
+ git config --global interactive.diffFilter "delta --color-only"
658
+ git config --global delta.navigate true
659
+ git config --global delta.light false
660
+ git config --global delta.side-by-side true
661
+ else
662
+ echo "✅ Git already configured to use delta"
663
+ fi
664
+ else
665
+ echo "⚠️ Failed to install git-delta"
666
+ fi
233
667
  fi
234
668
  fi
235
669
 
@@ -237,12 +671,187 @@ install_dev_tools() {
237
671
  setup_shell_config
238
672
  }
239
673
 
674
+ # Function to setup Claude Code environment variables
675
+ setup_claude_environment() {
676
+ echo "🔧 Setting up Claude Code environment variables..."
677
+
678
+ # Claude Code Performance and Timeout Settings (configurable via .env)
679
+ export BASH_DEFAULT_TIMEOUT_MS="${BASH_DEFAULT_TIMEOUT_MS:-120000}"
680
+ export BASH_MAX_TIMEOUT_MS="${BASH_MAX_TIMEOUT_MS:-600000}"
681
+ export CLAUDE_CODE_MAX_OUTPUT_TOKENS="${CLAUDE_CODE_MAX_OUTPUT_TOKENS:-31999}"
682
+ export MAX_THINKING_TOKENS="${MAX_THINKING_TOKENS:-62000}"
683
+ export MAX_MCP_OUTPUT_TOKENS="${MAX_MCP_OUTPUT_TOKENS:-31999}"
684
+ export MCP_TIMEOUT="${MCP_TIMEOUT:-60000}"
685
+ export MCP_TOOL_TIMEOUT="${MCP_TOOL_TIMEOUT:-120000}"
686
+
687
+ # Claude Code Stability Settings
688
+ # DISABLE_AUTOUPDATER prevents Claude Code from auto-updating during work sessions
689
+ # which can cause model selections to change and potential loss of system prompts
690
+ export DISABLE_AUTOUPDATER="${DISABLE_AUTOUPDATER:-true}"
691
+
692
+ # DISABLE_BUG_COMMAND prevents accidental bug reports in container environments
693
+ export DISABLE_BUG_COMMAND="${DISABLE_BUG_COMMAND:-true}"
694
+
695
+ # ENABLE_AUTOMATIC_TERMINAL_SETUP controls whether terminal keybindings are automatically configured
696
+ # This performs the equivalent of Claude Code's /terminal-setup slash command
697
+ export ENABLE_AUTOMATIC_TERMINAL_SETUP="${ENABLE_AUTOMATIC_TERMINAL_SETUP:-false}"
698
+
699
+ echo "✅ Claude Code environment variables configured:"
700
+ echo " 📊 BASH_DEFAULT_TIMEOUT_MS: $BASH_DEFAULT_TIMEOUT_MS"
701
+ echo " 📊 BASH_MAX_TIMEOUT_MS: $BASH_MAX_TIMEOUT_MS"
702
+ echo " 📊 CLAUDE_CODE_MAX_OUTPUT_TOKENS: $CLAUDE_CODE_MAX_OUTPUT_TOKENS"
703
+ echo " 📊 MAX_THINKING_TOKENS: $MAX_THINKING_TOKENS"
704
+ echo " 📊 MAX_MCP_OUTPUT_TOKENS: $MAX_MCP_OUTPUT_TOKENS"
705
+ echo " 📊 MCP_TIMEOUT: $MCP_TIMEOUT"
706
+ echo " 📊 MCP_TOOL_TIMEOUT: $MCP_TOOL_TIMEOUT"
707
+ echo " 🔒 DISABLE_AUTOUPDATER: $DISABLE_AUTOUPDATER"
708
+ echo " 🔒 DISABLE_BUG_COMMAND: $DISABLE_BUG_COMMAND"
709
+ echo " ⌨️ ENABLE_AUTOMATIC_TERMINAL_SETUP: $ENABLE_AUTOMATIC_TERMINAL_SETUP"
710
+ }
711
+
712
+ # Function to setup terminal keybindings (equivalent to /terminal-setup)
713
+ setup_terminal_keybindings() {
714
+ echo "🔧 Setting up terminal keybindings..."
715
+
716
+ # Check if automatic terminal setup is enabled (default: false)
717
+ if [ "${ENABLE_AUTOMATIC_TERMINAL_SETUP:-false}" != "true" ]; then
718
+ echo "⏭️ Automatic terminal setup disabled (set ENABLE_AUTOMATIC_TERMINAL_SETUP=true to enable)"
719
+ return 0
720
+ fi
721
+
722
+ local keybindings_file="/home/node/.config/Code/User/keybindings.json"
723
+ local keybindings_dir="/home/node/.config/Code/User"
724
+
725
+ # Create VSCode config directory if it doesn't exist
726
+ if [ ! -d "$keybindings_dir" ]; then
727
+ mkdir -p "$keybindings_dir"
728
+ chown -R node:node "/home/node/.config/Code"
729
+ fi
730
+
731
+ # Create or update keybindings file with proper Shift+Enter setup
732
+ if [ -f "$keybindings_file" ]; then
733
+ # Check if Shift+Enter binding already exists and is correctly configured
734
+ if grep -q "shift+enter" "$keybindings_file" 2>/dev/null; then
735
+ echo "📝 Existing Shift+Enter keybinding found, validating configuration..."
736
+
737
+ # Check if it's the correct terminal setup binding
738
+ if grep -A 5 -B 5 "shift+enter" "$keybindings_file" | grep -q "workbench.action.terminal.sendSequence" && \
739
+ grep -A 5 -B 5 "shift+enter" "$keybindings_file" | grep -q "terminalFocus"; then
740
+ echo "✅ Correct terminal Shift+Enter keybinding already configured"
741
+ return 0
742
+ else
743
+ echo "⚠️ Incorrect Shift+Enter keybinding found, replacing with correct terminal setup..."
744
+ # Create backup
745
+ cp "$keybindings_file" "${keybindings_file}.backup.$(date +%Y%m%d_%H%M%S)"
746
+
747
+ # Remove existing Shift+Enter bindings
748
+ if command -v jq >/dev/null 2>&1; then
749
+ jq 'map(select(.key != "shift+enter"))' "$keybindings_file" > "${keybindings_file}.tmp" && \
750
+ mv "${keybindings_file}.tmp" "$keybindings_file"
751
+ else
752
+ sed -i '/shift+enter/,/}/d' "$keybindings_file"
753
+ sed -i 's/,\s*]/]/g' "$keybindings_file"
754
+ sed -i 's/,\s*}/}/g' "$keybindings_file"
755
+ fi
756
+ fi
757
+ else
758
+ echo "📝 No Shift+Enter keybinding found, adding terminal setup..."
759
+ fi
760
+
761
+ # Add the correct terminal Shift+Enter keybinding
762
+ if command -v jq >/dev/null 2>&1; then
763
+ # Use jq to properly add the terminal keybinding
764
+ jq '. += [{
765
+ "key": "shift+enter",
766
+ "command": "workbench.action.terminal.sendSequence",
767
+ "args": {
768
+ "text": "\\r\\n"
769
+ },
770
+ "when": "terminalFocus"
771
+ }]' "$keybindings_file" > "${keybindings_file}.tmp" && \
772
+ mv "${keybindings_file}.tmp" "$keybindings_file"
773
+ else
774
+ # Fallback: manually construct the JSON
775
+ if [ "$(cat "$keybindings_file")" = "[]" ]; then
776
+ # Empty array, replace entirely
777
+ cat > "$keybindings_file" << 'EOF'
778
+ [
779
+ {
780
+ "key": "shift+enter",
781
+ "command": "workbench.action.terminal.sendSequence",
782
+ "args": {
783
+ "text": "\\r\\n"
784
+ },
785
+ "when": "terminalFocus"
786
+ }
787
+ ]
788
+ EOF
789
+ else
790
+ # Existing content, need to insert
791
+ # Remove the closing ] and add the new binding
792
+ sed -i '$s/]//' "$keybindings_file"
793
+ cat >> "$keybindings_file" << 'EOF'
794
+ ,{
795
+ "key": "shift+enter",
796
+ "command": "workbench.action.terminal.sendSequence",
797
+ "args": {
798
+ "text": "\\r\\n"
799
+ },
800
+ "when": "terminalFocus"
801
+ }
802
+ ]
803
+ EOF
804
+ fi
805
+ fi
806
+
807
+ # Validate JSON
808
+ if ! python3 -m json.tool "$keybindings_file" >/dev/null 2>&1; then
809
+ echo "⚠️ JSON validation failed, creating clean terminal setup..."
810
+ cat > "$keybindings_file" << 'EOF'
811
+ [
812
+ {
813
+ "key": "shift+enter",
814
+ "command": "workbench.action.terminal.sendSequence",
815
+ "args": {
816
+ "text": "\\r\\n"
817
+ },
818
+ "when": "terminalFocus"
819
+ }
820
+ ]
821
+ EOF
822
+ fi
823
+
824
+ else
825
+ # Create new keybindings file with terminal setup
826
+ echo "📝 Creating new keybindings.json with terminal setup..."
827
+ cat > "$keybindings_file" << 'EOF'
828
+ [
829
+ {
830
+ "key": "shift+enter",
831
+ "command": "workbench.action.terminal.sendSequence",
832
+ "args": {
833
+ "text": "\\r\\n"
834
+ },
835
+ "when": "terminalFocus"
836
+ }
837
+ ]
838
+ EOF
839
+ fi
840
+
841
+ # Set proper ownership and permissions
842
+ chown node:node "$keybindings_file"
843
+ chmod 644 "$keybindings_file"
844
+
845
+ echo "✅ Terminal Shift+Enter keybinding configured successfully"
846
+ echo " 💡 Shift+Enter will now send newlines in VSCode terminal (equivalent to /terminal-setup)"
847
+ }
848
+
240
849
  # Function to setup enhanced ZSH configuration
241
850
  setup_shell_config() {
242
851
  echo "🐚 Setting up enhanced shell configuration..."
243
852
 
244
853
  # Add PATH configuration to shell files
245
- local shell_files=(
854
+ shell_files=(
246
855
  "/home/node/.bashrc"
247
856
  "/home/node/.zshrc"
248
857
  "/home/node/.profile"
@@ -257,7 +866,33 @@ setup_shell_config() {
257
866
  cat >> "$shell_file" << 'EOF'
258
867
 
259
868
  # ClaudePod custom configuration
260
- export PATH="$HOME/.local/bin:$PATH"
869
+ # Function to add directory to PATH without duplication
870
+ add_to_path() {
871
+ local dir="$1"
872
+ case ":$PATH:" in
873
+ *":$dir:"*) ;;
874
+ *) export PATH="$dir:$PATH" ;;
875
+ esac
876
+ }
877
+
878
+ # Add local bin to PATH (avoiding duplicates)
879
+ add_to_path "$HOME/.local/bin"
880
+
881
+ # Source NVM (Node Version Manager)
882
+ export NVM_DIR="/usr/local/share/nvm"
883
+ [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
884
+
885
+ # Claude Code Environment Variables (configurable via .devcontainer/.env)
886
+ export BASH_DEFAULT_TIMEOUT_MS="${BASH_DEFAULT_TIMEOUT_MS:-120000}"
887
+ export BASH_MAX_TIMEOUT_MS="${BASH_MAX_TIMEOUT_MS:-600000}"
888
+ export CLAUDE_CODE_MAX_OUTPUT_TOKENS="${CLAUDE_CODE_MAX_OUTPUT_TOKENS:-31999}"
889
+ export MAX_THINKING_TOKENS="${MAX_THINKING_TOKENS:-62000}"
890
+ export MAX_MCP_OUTPUT_TOKENS="${MAX_MCP_OUTPUT_TOKENS:-31999}"
891
+ export MCP_TIMEOUT="${MCP_TIMEOUT:-60000}"
892
+ export MCP_TOOL_TIMEOUT="${MCP_TOOL_TIMEOUT:-120000}"
893
+ export DISABLE_AUTOUPDATER="${DISABLE_AUTOUPDATER:-true}"
894
+ export DISABLE_BUG_COMMAND="${DISABLE_BUG_COMMAND:-true}"
895
+ export ENABLE_AUTOMATIC_TERMINAL_SETUP="${ENABLE_AUTOMATIC_TERMINAL_SETUP:-false}"
261
896
 
262
897
  # Git aliases
263
898
  alias gs='git status'
@@ -266,13 +901,43 @@ alias gc='git commit'
266
901
  alias gp='git push'
267
902
  alias gl='git log --oneline --graph --decorate'
268
903
 
269
- # Claude Code alias with permissions flag
270
- alias claude='claude --model sonnet --dangerously-skip-permissions'
271
-
272
904
  # List aliases
273
905
  alias ll='ls -alF'
274
906
  alias la='ls -A'
275
907
  alias l='ls -CF'
908
+
909
+ # ClaudePod usage information function
910
+ claudepod_info() {
911
+ echo ""
912
+ echo "🐳 ClaudePod Development Container"
913
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
914
+ echo "🔧 Core Tools:"
915
+ echo " claude # Start Claude Code CLI"
916
+ echo " ccusage # View Claude Code usage analytics"
917
+ echo " cchistory # Analyze Claude Code prompt changes"
918
+ echo " claude-trace # Record Claude Code interactions"
919
+ echo ""
920
+ echo "📊 Quick Commands:"
921
+ echo " ccusage # Daily usage report"
922
+ echo " ccusage session # Usage by conversation"
923
+ echo " cchistory 1.0.50 --latest # Compare prompts since v1.0.50"
924
+ echo " cchistory --current # View current version prompts"
925
+ echo " claude-trace # Start logging Claude interactions"
926
+ echo " claude-trace --generate-html logs.jsonl report.html # Create HTML report"
927
+ echo ""
928
+ echo "💡 Tips:"
929
+ echo " • Claude statusline shows real-time usage/costs"
930
+ echo " • Use 'gs', 'gd', 'gc' for git shortcuts"
931
+ echo " • Run 'claudepod_info' anytime to see this again"
932
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
933
+ echo ""
934
+ }
935
+
936
+ # Show ClaudePod info on first terminal open (once per session)
937
+ if [ ! -f "/tmp/.claudepod_info_shown_$$" ]; then
938
+ claudepod_info
939
+ touch "/tmp/.claudepod_info_shown_$$"
940
+ fi
276
941
  EOF
277
942
  fi
278
943
 
@@ -282,10 +947,19 @@ EOF
282
947
  done
283
948
 
284
949
  # Run ZSH enhancement setup as the node user if available
285
- if [ -f ".devcontainer/setup-zsh.sh" ]; then
286
- sudo -u node -E bash .devcontainer/setup-zsh.sh 2>/dev/null || {
287
- echo "⚠️ ZSH setup encountered some non-critical errors, continuing..."
288
- }
950
+ if [ -f "/workspace/.devcontainer/setup-zsh.sh" ]; then
951
+ echo "🔧 Clearing npm prefix conflicts before ZSH setup..."
952
+ # Clear npm prefix environment variables that conflict with NVM during shell setup
953
+ unset npm_config_prefix 2>/dev/null || true
954
+ unset NPM_CONFIG_PREFIX 2>/dev/null || true
955
+
956
+ if sudo -u node -E bash -c 'unset npm_config_prefix; unset NPM_CONFIG_PREFIX; bash /workspace/.devcontainer/setup-zsh.sh' 2>&1; then
957
+ echo "✅ ZSH setup completed successfully"
958
+ else
959
+ local exit_code=$?
960
+ echo "⚠️ ZSH setup encountered some non-critical errors (exit code: $exit_code), continuing..."
961
+ echo " You can manually run: sudo -u node bash /workspace/.devcontainer/setup-zsh.sh"
962
+ fi
289
963
  echo "✅ Enhanced ZSH configuration completed"
290
964
  else
291
965
  echo "✅ Basic shell configuration completed"
@@ -305,49 +979,23 @@ display_completion_message() {
305
979
  echo " 3. Your configuration will persist in the mounted volumes"
306
980
  echo ""
307
981
  echo "🛠️ Installed tools:"
308
- echo " - Claude Code CLI"
982
+ echo " - Claude Code CLI with statusline integration"
309
983
  echo " - ccusage (Claude Code usage analytics)"
984
+ echo " - cchistory (Claude Code prompt analyzer)"
985
+ echo " - claude-trace (Claude Code interaction recorder)"
310
986
  echo " - git-delta (better git diffs)"
311
987
  echo " - Shell aliases (gs, gd, gc, gp, gl)"
312
988
  echo ""
313
- echo "💡 Tip: Claude Code is now available globally as 'claude'"
989
+ echo "💡 Tips:"
990
+ echo " • Run 'claude' to start Claude Code with statusline integration"
991
+ echo " • Use 'ccusage' for real-time usage analytics and cost tracking"
992
+ echo " • Use 'cchistory' to analyze Claude Code prompt changes"
993
+ echo " • Use 'claude-trace' to record and analyze Claude interactions"
994
+ echo " • Terminal info shown on new terminal sessions"
995
+ echo " • Run 'claudepod_info' anytime for quick command reference"
314
996
  echo "════════════════════════════════════════════════════════════════"
315
997
  }
316
998
 
317
- # Function to setup npm directories and permissions
318
- setup_npm_permissions() {
319
- echo "🔧 Setting up npm directories and permissions..."
320
-
321
- # Create npm directories with correct ownership
322
- local npm_dirs=(
323
- "/home/node/.npm"
324
- "/home/node/.npm/_cacache"
325
- "/home/node/.npm/_logs"
326
- "/home/node/.config"
327
- "/home/node/.local"
328
- "/home/node/.local/bin"
329
- )
330
-
331
- for dir in "${npm_dirs[@]}"; do
332
- mkdir -p "$dir"
333
- chown -R node:node "$dir"
334
- chmod -R 755 "$dir"
335
- done
336
-
337
- # Remove any existing .npmrc directory/file and create .npmrc file
338
- rm -rf /home/node/.npmrc
339
- cat > /home/node/.npmrc << 'EOF'
340
- cache=/home/node/.npm/_cacache
341
- prefix=/home/node/.local
342
- update-notifier=false
343
- EOF
344
-
345
- # Set proper ownership for .npmrc
346
- chown node:node /home/node/.npmrc
347
- chmod 644 /home/node/.npmrc
348
-
349
- echo "✅ npm directories and permissions configured"
350
- }
351
999
 
352
1000
  # Main execution
353
1001
  main() {
@@ -355,37 +1003,66 @@ main() {
355
1003
  echo "🐳 ClaudePod Post-Create Setup - Phases 2 & 4"
356
1004
  echo "════════════════════════════════════════════════════════════════"
357
1005
 
358
- # Source NVM and ensure PATH is set correctly for the entire script
359
- export NVM_DIR="/usr/local/share/nvm"
360
- [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
361
- export PATH="/home/node/.local/bin:$PATH"
362
-
363
1006
  # Fix workspace permissions
364
1007
  echo "🔧 Setting workspace permissions..."
365
- sudo chown -R node:node /workspace
366
- sudo chmod -R u+rwX,g+rwX /workspace
1008
+ if [ -d "/workspace" ]; then
1009
+ sudo chown -R node:node /workspace
1010
+ sudo chmod -R u+rwX,g+rwX /workspace
1011
+ else
1012
+ echo "⚠️ /workspace directory not found - this is unexpected"
1013
+ exit 1
1014
+ fi
367
1015
 
368
1016
  # Setup workspace directories for bind mounts (Claude and Serena)
369
1017
  setup_workspace_directories
370
1018
 
371
- # Setup npm permissions and directories
372
- setup_npm_permissions
373
-
374
1019
  # Add node user to docker group for Docker socket access
375
1020
  echo "🐳 Adding node user to docker group..."
376
- sudo usermod -aG docker node
1021
+ sudo usermod -aG docker node 2>/dev/null || echo " Docker group already configured"
377
1022
  echo "✅ Node user added to docker group"
378
1023
 
1024
+ # Setup Claude Code environment variables
1025
+ setup_claude_environment
1026
+
379
1027
  # Install Claude Code
380
1028
  if install_claude_code; then
381
- # Setup configuration directory
382
- setup_claude_config
1029
+ # Setup configuration directories using focused modules
1030
+ setup_claude_core_config
1031
+ echo "✓ Claude core config completed successfully"
1032
+
1033
+ setup_serena_config
1034
+ echo "✓ Serena config completed successfully"
1035
+
1036
+ setup_taskmaster_config
1037
+ echo "✓ TaskMaster config completed successfully"
1038
+
1039
+ setup_searxng
1040
+ echo "✓ SearXNG setup completed successfully"
383
1041
 
384
1042
  # Install ccusage CLI tool
1043
+ echo "📊 Starting ccusage installation..."
385
1044
  install_ccusage || echo "⚠️ Continuing without ccusage..."
1045
+ echo "✓ ccusage installation phase completed"
1046
+
1047
+ # Install cchistory CLI tool
1048
+ echo "📊 Starting cchistory installation..."
1049
+ install_cchistory || echo "⚠️ Continuing without cchistory..."
1050
+ echo "✓ cchistory installation phase completed"
1051
+
1052
+ # Install claude-trace CLI tool
1053
+ echo "📊 Starting claude-trace installation..."
1054
+ install_claude_trace || echo "⚠️ Continuing without claude-trace..."
1055
+ echo "✓ claude-trace installation phase completed"
386
1056
 
387
1057
  # Install development tools
388
- install_dev_tools
1058
+ echo "🛠️ Starting development tools installation..."
1059
+ install_dev_tools || echo "⚠️ Continuing without some dev tools..."
1060
+ echo "✓ Development tools installation phase completed"
1061
+
1062
+ # Setup terminal keybindings (equivalent to /terminal-setup)
1063
+ echo "⌨️ Starting terminal keybindings setup..."
1064
+ setup_terminal_keybindings || echo "⚠️ Continuing without terminal keybindings..."
1065
+ echo "✓ Terminal keybindings setup completed"
389
1066
 
390
1067
  # Display completion message
391
1068
  display_completion_message
@@ -397,4 +1074,4 @@ main() {
397
1074
  }
398
1075
 
399
1076
  # Execute main function
400
- main
1077
+ main