claudepod 1.0.0

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.
@@ -0,0 +1,179 @@
1
+ {
2
+ "includeCoAuthoredBy": false,
3
+ "model": "claude-sonnet-4-0",
4
+ "forceLoginMethod": "claudeai",
5
+ "permissions": {
6
+ "allow": [
7
+ "Bash",
8
+ "Write",
9
+ "TodoWrite",
10
+ "mcp__serena__find_file",
11
+ "mcp__serena__list_dir",
12
+ "mcp__serena__search_for_pattern",
13
+ "mcp__serena__replace_regex",
14
+ "mcp__serena__get_symbols_overview",
15
+ "mcp__serena__find_symbol",
16
+ "mcp__serena__find_referencing_symbols",
17
+ "mcp__serena__replace_symbol_body",
18
+ "mcp__serena__insert_after_symbol",
19
+ "mcp__serena__insert_before_symbol",
20
+ "mcp__serena__read_memory",
21
+ "mcp__serena__write_memory",
22
+ "mcp__serena__list_memories",
23
+ "mcp__serena__delete_memory",
24
+ "mcp__serena__restart_language_server",
25
+ "mcp__serena__onboarding",
26
+ "mcp__serena__check_onboarding_performed",
27
+ "mcp__serena__think_about_collected_information",
28
+ "mcp__serena__think_about_task_adherence",
29
+ "mcp__serena__think_about_whether_you_are_done",
30
+ "mcp__tavily-search__tavily_search",
31
+ "mcp__tavily-search__tavily_extract",
32
+ "mcp__tavily-search__tavily_crawl",
33
+ "mcp__tavily-search__tavily_map",
34
+ "mcp__ide__getDiagnostics",
35
+ "mcp__ide__executeCode",
36
+ "ListMcpResourcesTool",
37
+ "ReadMcpResourceTool",
38
+ "mcp__ref-tools__search",
39
+ "mcp__ref-tools__get_document",
40
+ "mcp__ref-tools__get_page_content",
41
+ "mcp__ref-tools__search_docs",
42
+ "mcp__ref-tools__get_api_reference",
43
+ "mcp__taskmaster-ai__get_tasks",
44
+ "mcp__taskmaster-ai__next_task",
45
+ "mcp__taskmaster-ai__get_task",
46
+ "mcp__taskmaster-ai__set_task_status",
47
+ "mcp__taskmaster-ai__add_task",
48
+ "mcp__taskmaster-ai__update_task",
49
+ "mcp__taskmaster-ai__expand_task",
50
+ "mcp__taskmaster-ai__parse_prd",
51
+ "mcp__taskmaster-ai__initialize_project",
52
+ "mcp__taskmaster-ai__expand_all",
53
+ "mcp__taskmaster-ai__update_subtask",
54
+ "mcp__taskmaster-ai__models",
55
+ "mcp__taskmaster-ai__analyze_project_complexity",
56
+ "mcp__taskmaster-ai__research",
57
+ "mcp__github__get_me",
58
+ "mcp__github__get_file_contents",
59
+ "mcp__github__create_or_update_file",
60
+ "mcp__github__delete_file",
61
+ "mcp__github__list_branches",
62
+ "mcp__github__create_branch",
63
+ "mcp__github__get_pull_request",
64
+ "mcp__github__create_pull_request",
65
+ "mcp__github__list_pull_requests",
66
+ "mcp__github__get_pull_request_diff",
67
+ "mcp__github__get_issue",
68
+ "mcp__github__create_issue",
69
+ "mcp__github__list_issues",
70
+ "mcp__github__add_issue_comment",
71
+ "mcp__github__push_files",
72
+ "mcp__github__get_pull_request_files",
73
+ "mcp__github__get_pull_request_comments",
74
+ "mcp__github__merge_pull_request",
75
+ "mcp__github__list_commits",
76
+ "mcp__github__get_commit",
77
+ "mcp__github__update_pull_request",
78
+ "mcp__github__get_issue_comments",
79
+ "mcp__github__search_repositories",
80
+ "mcp__github__search_code",
81
+ "mcp__github__fork_repository",
82
+ "mcp__github__create_repository",
83
+ "mcp__github__list_tags",
84
+ "mcp__ccusage__daily",
85
+ "mcp__ccusage__session"
86
+ ],
87
+ "deny": [
88
+ "Read",
89
+ "Edit",
90
+ "MultiEdit",
91
+ "Glob",
92
+ "Grep",
93
+ "LS",
94
+ "Task",
95
+ "ExitPlanMode",
96
+ "NotebookEdit",
97
+ "WebFetch",
98
+ "WebSearch",
99
+ "mcp__deepwiki__read_wiki_structure",
100
+ "mcp__deepwiki__read_wiki_contents",
101
+ "mcp__deepwiki__ask_question",
102
+ "mcp__taskmaster-ai__rules",
103
+ "mcp__taskmaster-ai__scope_up_task",
104
+ "mcp__taskmaster-ai__scope_down_task",
105
+ "mcp__taskmaster-ai__complexity_report",
106
+ "mcp__taskmaster-ai__generate",
107
+ "mcp__taskmaster-ai__add_subtask",
108
+ "mcp__taskmaster-ai__update",
109
+ "mcp__taskmaster-ai__remove_task",
110
+ "mcp__taskmaster-ai__remove_subtask",
111
+ "mcp__taskmaster-ai__clear_subtasks",
112
+ "mcp__taskmaster-ai__move_task",
113
+ "mcp__taskmaster-ai__add_dependency",
114
+ "mcp__taskmaster-ai__remove_dependency",
115
+ "mcp__taskmaster-ai__validate_dependencies",
116
+ "mcp__taskmaster-ai__fix_dependencies",
117
+ "mcp__taskmaster-ai__response-language",
118
+ "mcp__taskmaster-ai__list_tags",
119
+ "mcp__taskmaster-ai__add_tag",
120
+ "mcp__taskmaster-ai__delete_tag",
121
+ "mcp__taskmaster-ai__use_tag",
122
+ "mcp__taskmaster-ai__rename_tag",
123
+ "mcp__taskmaster-ai__copy_tag",
124
+ "mcp__github__add_comment_to_pending_review",
125
+ "mcp__github__add_sub_issue",
126
+ "mcp__github__assign_copilot_to_issue",
127
+ "mcp__github__cancel_workflow_run",
128
+ "mcp__github__create_and_submit_pull_request_review",
129
+ "mcp__github__create_gist",
130
+ "mcp__github__create_pending_pull_request_review",
131
+ "mcp__github__delete_pending_pull_request_review",
132
+ "mcp__github__delete_workflow_run_logs",
133
+ "mcp__github__dismiss_notification",
134
+ "mcp__github__download_workflow_run_artifact",
135
+ "mcp__github__get_code_scanning_alert",
136
+ "mcp__github__get_dependabot_alert",
137
+ "mcp__github__get_discussion",
138
+ "mcp__github__get_discussion_comments",
139
+ "mcp__github__get_job_logs",
140
+ "mcp__github__get_notification_details",
141
+ "mcp__github__get_pull_request_reviews",
142
+ "mcp__github__get_pull_request_status",
143
+ "mcp__github__get_secret_scanning_alert",
144
+ "mcp__github__get_tag",
145
+ "mcp__github__get_workflow_run",
146
+ "mcp__github__get_workflow_run_logs",
147
+ "mcp__github__get_workflow_run_usage",
148
+ "mcp__github__list_code_scanning_alerts",
149
+ "mcp__github__list_dependabot_alerts",
150
+ "mcp__github__list_discussion_categories",
151
+ "mcp__github__list_discussions",
152
+ "mcp__github__list_gists",
153
+ "mcp__github__list_notifications",
154
+ "mcp__github__list_secret_scanning_alerts",
155
+ "mcp__github__list_sub_issues",
156
+ "mcp__github__list_workflow_jobs",
157
+ "mcp__github__list_workflow_run_artifacts",
158
+ "mcp__github__list_workflow_runs",
159
+ "mcp__github__list_workflows",
160
+ "mcp__github__manage_notification_subscription",
161
+ "mcp__github__manage_repository_notification_subscription",
162
+ "mcp__github__mark_all_notifications_read",
163
+ "mcp__github__remove_sub_issue",
164
+ "mcp__github__reprioritize_sub_issue",
165
+ "mcp__github__request_copilot_review",
166
+ "mcp__github__rerun_failed_jobs",
167
+ "mcp__github__rerun_workflow_run",
168
+ "mcp__github__run_workflow",
169
+ "mcp__github__search_issues",
170
+ "mcp__github__search_orgs",
171
+ "mcp__github__search_pull_requests",
172
+ "mcp__github__search_users",
173
+ "mcp__github__submit_pending_pull_request_review",
174
+ "mcp__github__update_gist",
175
+ "mcp__github__update_issue",
176
+ "mcp__github__update_pull_request_branch"
177
+ ]
178
+ }
179
+ }
@@ -0,0 +1,110 @@
1
+ {
2
+ "name": "ClaudePod Development Environment",
3
+ "image": "mcr.microsoft.com/vscode/devcontainers/base:ubuntu-22.04",
4
+
5
+ "features": {
6
+ "ghcr.io/devcontainers/features/common-utils:2": {
7
+ "installZsh": true,
8
+ "installOhMyZsh": true,
9
+ "username": "node",
10
+ "uid": 1000,
11
+ "gid": 1000,
12
+ "upgradePackages": true
13
+ },
14
+ "ghcr.io/devcontainers/features/node:1": {
15
+ "nodeGypDependencies": true,
16
+ "version": "20"
17
+ },
18
+ "ghcr.io/devcontainers/features/python:1": {
19
+ "version": "3.13",
20
+ "installTools": true,
21
+ "toolsToInstall": "flake8,autopep8,black,yapf,mypy,pydocstyle,pycodestyle,bandit,pipenv,virtualenv,pytest,pylint"
22
+ },
23
+ "ghcr.io/devcontainers/features/git:1": {
24
+ "version": "latest",
25
+ "ppa": false
26
+ },
27
+ "ghcr.io/devcontainers/features/github-cli:1": {
28
+ "version": "latest"
29
+ },
30
+ "ghcr.io/devcontainers/features/docker-in-docker:2": {
31
+ "version": "latest",
32
+ "dockerDashComposeVersion": "v2"
33
+ }
34
+ },
35
+
36
+ "containerEnv": {
37
+ "CLAUDE_CONFIG_DIR": "/home/node/.claude",
38
+ "DEVCONTAINER": "true",
39
+ "TAVILY_API_KEY": "${localEnv:TAVILY_API_KEY}",
40
+ "REF_TOOLS_API_KEY": "${localEnv:REF_TOOLS_API_KEY}",
41
+ "GITHUB_PERSONAL_ACCESS_TOKEN": "${localEnv:GITHUB_PERSONAL_ACCESS_TOKEN}",
42
+ "GITHUB_API_URL": "${localEnv:GITHUB_API_URL}",
43
+ "GITHUB_TOOLSET": "${localEnv:GITHUB_TOOLSET}"
44
+ },
45
+
46
+ "mounts": [
47
+ "source=${localWorkspaceFolder}/.claude,target=/home/node/.claude,type=bind,consistency=cached",
48
+ "source=${localWorkspaceFolder}/.serena,target=/home/node/.serena,type=bind,consistency=cached",
49
+ "source=claudepod-bash-history,target=/home/node/.bash_history,type=volume",
50
+ "source=claudepod-zsh-history,target=/home/node/.zsh_history,type=volume",
51
+ "source=claudepod-npm-cache,target=/home/node/.npm,type=volume",
52
+ "source=claudepod-npm-config,target=/home/node/.config,type=volume",
53
+ "source=claudepod-npm-global,target=/home/node/.local,type=volume"
54
+ ],
55
+
56
+ "postCreateCommand": "sudo -E /bin/bash .devcontainer/post-create.sh",
57
+ "postStartCommand": "/bin/bash .devcontainer/post-start.sh",
58
+
59
+ "forwardPorts": [],
60
+ "portsAttributes": {
61
+ "*": {
62
+ "onAutoForward": "openBrowserOnce"
63
+ }
64
+ },
65
+ "otherPortsAttributes": {
66
+ "onAutoForward": "openBrowser"
67
+ },
68
+
69
+ "customizations": {
70
+ "vscode": {
71
+ "extensions": [
72
+ "ms-vscode-remote.remote-containers",
73
+ "ms-vscode-remote.remote-ssh",
74
+ "ms-vscode-remote.remote-ssh-edit",
75
+ "ms-vscode.remote-explorer",
76
+ "ms-vscode-remote.vscode-remote-extensionpack",
77
+ "ms-python.python",
78
+ "ms-python.vscode-pylance",
79
+ "dbaeumer.vscode-eslint",
80
+ "esbenp.prettier-vscode",
81
+ "GitHub.vscode-pull-request-github",
82
+ "eamodio.gitlens"
83
+ ],
84
+ "settings": {
85
+ "remote.SSH.defaultExtensions": [
86
+ "ms-vscode-remote.remote-ssh-edit"
87
+ ],
88
+ "terminal.integrated.defaultProfile.linux": "zsh",
89
+ "terminal.integrated.profiles.linux": {
90
+ "zsh": {
91
+ "path": "/usr/bin/zsh",
92
+ "args": ["-l"]
93
+ }
94
+ },
95
+ "terminal.integrated.shell.linux": "/usr/bin/zsh",
96
+ "terminal.integrated.shellArgs.linux": ["-l"],
97
+ "terminal.integrated.fontFamily": "MesloLGS NF, 'Courier New', monospace",
98
+ "terminal.integrated.fontSize": 14
99
+ }
100
+ }
101
+ },
102
+
103
+ "remoteUser": "node",
104
+ "containerUser": "node",
105
+
106
+ "workspaceFolder": "/workspace",
107
+ "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
108
+
109
+ "postAttachCommand": "sudo chown -R node:node /workspace"
110
+ }
@@ -0,0 +1,400 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # ClaudePod Post-Create Script - Phases 2 & 4
5
+ # This script handles Claude Code installation, configuration, and development tools
6
+
7
+ echo "🚀 Starting ClaudePod post-create setup..."
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"
13
+
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
20
+
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
33
+ }
34
+
35
+ # Function to install Claude Code
36
+ install_claude_code() {
37
+ echo "📦 Installing Claude Code..."
38
+
39
+ # Ensure PATH includes npm global bin directory
40
+ export PATH="/home/node/.local/bin:$PATH"
41
+
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"
45
+
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
56
+ fi
57
+ else
58
+ echo "❌ Failed to install Claude Code after multiple attempts"
59
+ return 1
60
+ fi
61
+ }
62
+
63
+ # Function to setup workspace directories for bind mounts
64
+ setup_workspace_directories() {
65
+ echo "🔧 Setting up workspace configuration directories..."
66
+
67
+ # Create workspace directories for bind mounts
68
+ local workspace_dirs=(
69
+ "/workspace/.claude"
70
+ "/workspace/.serena"
71
+ )
72
+
73
+ for dir in "${workspace_dirs[@]}"; do
74
+ if [ ! -d "$dir" ]; then
75
+ mkdir -p "$dir"
76
+ echo "📁 Created workspace directory: $dir"
77
+ fi
78
+ # Set proper permissions
79
+ chown -R node:node "$dir"
80
+ chmod -R 755 "$dir"
81
+ done
82
+
83
+ # Setup Serena configuration if it doesn't exist
84
+ setup_serena_config
85
+
86
+ echo "✅ Workspace configuration directories ready"
87
+ }
88
+
89
+ # Function to setup Serena configuration
90
+ setup_serena_config() {
91
+ local serena_config="/workspace/.serena/serena_config.yml"
92
+
93
+ if [ ! -f "$serena_config" ]; then
94
+ echo "📝 Creating Serena configuration..."
95
+
96
+ cat > "$serena_config" << 'EOF'
97
+ gui_log_window: False
98
+ # whether to open a graphical window with Serena's logs.
99
+
100
+ web_dashboard: True
101
+ # whether to open the Serena web dashboard (accessible through your web browser)
102
+
103
+ web_dashboard_open_on_launch: False
104
+ # whether to open a browser window with the web dashboard when Serena starts
105
+ # If set to False, you can still open the dashboard manually by navigating to
106
+ # http://localhost:24282/dashboard/ in your web browser
107
+
108
+ log_level: 20
109
+ # the minimum log level for the GUI log window and the dashboard (10 = debug, 20 = info, 30 = warning, 40 = error)
110
+
111
+ trace_lsp_communication: False
112
+ # whether to trace the communication between Serena and the language servers.
113
+
114
+ tool_timeout: 240
115
+ # timeout, in seconds, after which tool executions are terminated
116
+
117
+ excluded_tools: []
118
+ # list of tools to be globally excluded
119
+
120
+ included_optional_tools: []
121
+ # list of optional tools (which are disabled by default) to be included
122
+
123
+ jetbrains: False
124
+ # whether to enable JetBrains mode
125
+
126
+ record_tool_usage_stats: False
127
+ # whether to record tool usage statistics
128
+
129
+ token_count_estimator: TIKTOKEN_GPT4O
130
+ # token count estimator to use for tool usage statistics
131
+
132
+ # MANAGED BY SERENA, KEEP AT THE BOTTOM OF THE YAML AND DON'T EDIT WITHOUT NEED
133
+ # The list of registered projects.
134
+ projects: []
135
+ EOF
136
+
137
+ # Set proper ownership
138
+ chown node:node "$serena_config"
139
+ chmod 644 "$serena_config"
140
+
141
+ echo "✅ Serena configuration created with dashboard auto-open disabled"
142
+ else
143
+ echo "📁 Serena configuration already exists"
144
+ fi
145
+ }
146
+
147
+ # Function to setup Claude configuration directory
148
+ setup_claude_config() {
149
+ echo "🔧 Setting up Claude configuration..."
150
+
151
+ # Claude Code uses multiple possible config locations
152
+ local claude_dirs=(
153
+ "/home/node/.claude"
154
+ "/home/node/.config/claude"
155
+ )
156
+
157
+ for dir in "${claude_dirs[@]}"; do
158
+ if [ ! -d "$dir" ]; then
159
+ mkdir -p "$dir"
160
+ echo "📁 Created configuration directory: $dir"
161
+ fi
162
+ # Set proper permissions
163
+ chown -R node:node "$dir"
164
+ chmod -R 700 "$dir"
165
+ done
166
+
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"
170
+
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)"
176
+ else
177
+ echo "⚠️ Claude settings template not found, using defaults"
178
+ fi
179
+
180
+ echo "✅ Claude configuration directories ready"
181
+ }
182
+
183
+ # Function to install ccusage CLI tool
184
+ install_ccusage() {
185
+ echo "📊 Installing ccusage..."
186
+
187
+ if retry_command 3 5 npm install -g ccusage; then
188
+ echo "✅ ccusage installed successfully"
189
+
190
+ # 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"
194
+ return 0
195
+ else
196
+ echo "⚠️ ccusage installed but command not found"
197
+ return 1
198
+ fi
199
+ else
200
+ echo "❌ Failed to install ccusage"
201
+ return 1
202
+ fi
203
+ }
204
+
205
+ # Function to install development tools
206
+ install_dev_tools() {
207
+ echo "🛠️ Installing additional development tools..."
208
+
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
226
+ git config --global core.pager "delta"
227
+ git config --global interactive.diffFilter "delta --color-only"
228
+ git config --global delta.navigate true
229
+ git config --global delta.light false
230
+ git config --global delta.side-by-side true
231
+ else
232
+ echo "⚠️ Failed to install git-delta"
233
+ fi
234
+ fi
235
+
236
+ # Setup basic shell enhancements
237
+ setup_shell_config
238
+ }
239
+
240
+ # Function to setup enhanced ZSH configuration
241
+ setup_shell_config() {
242
+ echo "🐚 Setting up enhanced shell configuration..."
243
+
244
+ # Add PATH configuration to shell files
245
+ local shell_files=(
246
+ "/home/node/.bashrc"
247
+ "/home/node/.zshrc"
248
+ "/home/node/.profile"
249
+ )
250
+
251
+ for shell_file in "${shell_files[@]}"; do
252
+ # Ensure the shell file exists
253
+ touch "$shell_file"
254
+
255
+ # Add PATH and aliases if not already present
256
+ if ! grep -q "# ClaudePod custom configuration" "$shell_file" 2>/dev/null; then
257
+ cat >> "$shell_file" << 'EOF'
258
+
259
+ # ClaudePod custom configuration
260
+ export PATH="$HOME/.local/bin:$PATH"
261
+
262
+ # Git aliases
263
+ alias gs='git status'
264
+ alias gd='git diff'
265
+ alias gc='git commit'
266
+ alias gp='git push'
267
+ alias gl='git log --oneline --graph --decorate'
268
+
269
+ # Claude Code alias with permissions flag
270
+ alias claude='claude --model sonnet --dangerously-skip-permissions'
271
+
272
+ # List aliases
273
+ alias ll='ls -alF'
274
+ alias la='ls -A'
275
+ alias l='ls -CF'
276
+ EOF
277
+ fi
278
+
279
+ # Set proper ownership
280
+ chown node:node "$shell_file"
281
+ chmod 644 "$shell_file"
282
+ done
283
+
284
+ # 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
+ }
289
+ echo "✅ Enhanced ZSH configuration completed"
290
+ else
291
+ echo "✅ Basic shell configuration completed"
292
+ fi
293
+ }
294
+
295
+ # Function to display setup completion message
296
+ display_completion_message() {
297
+ echo ""
298
+ echo "════════════════════════════════════════════════════════════════"
299
+ echo "✅ ClaudePod setup complete!"
300
+ echo "════════════════════════════════════════════════════════════════"
301
+ echo ""
302
+ echo "🔑 Next steps:"
303
+ echo " 1. Run 'claude' to start using Claude Code"
304
+ echo " 2. Authentication will be handled on first use"
305
+ echo " 3. Your configuration will persist in the mounted volumes"
306
+ echo ""
307
+ echo "🛠️ Installed tools:"
308
+ echo " - Claude Code CLI"
309
+ echo " - ccusage (Claude Code usage analytics)"
310
+ echo " - git-delta (better git diffs)"
311
+ echo " - Shell aliases (gs, gd, gc, gp, gl)"
312
+ echo ""
313
+ echo "💡 Tip: Claude Code is now available globally as 'claude'"
314
+ echo "════════════════════════════════════════════════════════════════"
315
+ }
316
+
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
+
352
+ # Main execution
353
+ main() {
354
+ echo "════════════════════════════════════════════════════════════════"
355
+ echo "🐳 ClaudePod Post-Create Setup - Phases 2 & 4"
356
+ echo "════════════════════════════════════════════════════════════════"
357
+
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
+ # Fix workspace permissions
364
+ echo "🔧 Setting workspace permissions..."
365
+ sudo chown -R node:node /workspace
366
+ sudo chmod -R u+rwX,g+rwX /workspace
367
+
368
+ # Setup workspace directories for bind mounts (Claude and Serena)
369
+ setup_workspace_directories
370
+
371
+ # Setup npm permissions and directories
372
+ setup_npm_permissions
373
+
374
+ # Add node user to docker group for Docker socket access
375
+ echo "🐳 Adding node user to docker group..."
376
+ sudo usermod -aG docker node
377
+ echo "✅ Node user added to docker group"
378
+
379
+ # Install Claude Code
380
+ if install_claude_code; then
381
+ # Setup configuration directory
382
+ setup_claude_config
383
+
384
+ # Install ccusage CLI tool
385
+ install_ccusage || echo "⚠️ Continuing without ccusage..."
386
+
387
+ # Install development tools
388
+ install_dev_tools
389
+
390
+ # Display completion message
391
+ display_completion_message
392
+ else
393
+ echo "⚠️ Setup completed with errors. Claude Code installation failed."
394
+ echo " You can try installing manually with: npm install -g @anthropic-ai/claude-code"
395
+ exit 1
396
+ fi
397
+ }
398
+
399
+ # Execute main function
400
+ main