codeforge-dev 1.14.2 → 2.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.
- package/{.devcontainer/config/defaults → .codeforge/config}/ccstatusline-settings.json +44 -6
- package/{.devcontainer/config/defaults → .codeforge/config}/main-system-prompt.md +14 -6
- package/.codeforge/config/orchestrator-system-prompt.md +333 -0
- package/{.devcontainer/config/defaults → .codeforge/config}/settings.json +3 -1
- package/{.devcontainer/config → .codeforge}/file-manifest.json +15 -9
- package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.sh +3 -1
- package/.devcontainer/.env.example +5 -5
- package/.devcontainer/.secrets.example +3 -0
- package/.devcontainer/CHANGELOG.md +242 -0
- package/.devcontainer/CLAUDE.md +129 -22
- package/.devcontainer/README.md +34 -19
- package/.devcontainer/devcontainer.json +28 -10
- package/.devcontainer/features/agent-browser/install.sh +2 -0
- package/.devcontainer/features/ast-grep/install.sh +2 -0
- package/.devcontainer/features/biome/install.sh +2 -0
- package/.devcontainer/features/ccburn/install.sh +2 -0
- package/.devcontainer/features/ccms/install.sh +2 -0
- package/.devcontainer/features/ccstatusline/README.md +7 -6
- package/.devcontainer/features/ccstatusline/install.sh +9 -4
- package/.devcontainer/features/ccusage/install.sh +2 -0
- package/.devcontainer/features/chromaterm/chromaterm.yml +2 -2
- package/.devcontainer/features/chromaterm/install.sh +2 -0
- package/.devcontainer/features/claude-code-native/README.md +47 -0
- package/.devcontainer/features/claude-code-native/devcontainer-feature.json +29 -0
- package/.devcontainer/features/claude-code-native/install.sh +131 -0
- package/.devcontainer/features/claude-monitor/install.sh +2 -0
- package/.devcontainer/features/claude-session-dashboard/README.md +2 -2
- package/.devcontainer/features/claude-session-dashboard/install.sh +2 -0
- package/.devcontainer/features/dprint/install.sh +2 -0
- package/.devcontainer/features/hadolint/install.sh +2 -0
- package/.devcontainer/features/kitty-terminfo/README.md +3 -1
- package/.devcontainer/features/kitty-terminfo/install.sh +2 -0
- package/.devcontainer/features/lsp-servers/install.sh +2 -0
- package/.devcontainer/features/mcp-qdrant/CHANGES.md +3 -3
- package/.devcontainer/features/mcp-qdrant/README.md +1 -0
- package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +1 -1
- package/.devcontainer/features/mcp-qdrant/install.sh +9 -2
- package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +9 -2
- package/.devcontainer/features/notify-hook/devcontainer-feature.json +1 -1
- package/.devcontainer/features/notify-hook/install.sh +2 -0
- package/.devcontainer/features/ruff/install.sh +2 -0
- package/.devcontainer/features/shellcheck/install.sh +2 -0
- package/.devcontainer/features/shfmt/install.sh +2 -0
- package/.devcontainer/features/tmux/README.md +3 -3
- package/.devcontainer/features/tmux/install.sh +3 -1
- package/.devcontainer/features/tree-sitter/install.sh +2 -0
- package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +27 -11
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/README.md +23 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/claude-guide.md +4 -4
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/documenter.md +254 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/implementer.md +260 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/investigator.md +255 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/agent-system/agents/tester.md +304 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/README.md +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/auto-code-quality/scripts/advisory-test-runner.py +4 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +2 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/.claude-plugin/plugin.json +7 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/README.md +125 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/pr-review/SKILL.md +325 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/git-workflow/skills/ship/SKILL.md +314 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/.claude-plugin/plugin.json +5 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/README.md +52 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/prompt-snippets/skills/ps/SKILL.md +37 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected-bash.py +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/README.md +30 -14
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/hooks/hooks.json +13 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/collect-session-edits.py +44 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/session-context/scripts/commit-reminder.py +89 -10
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/.claude-plugin/plugin.json +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/README.md +19 -11
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/scripts/skill-suggester.py +476 -282
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/SKILL.md +227 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/manual-worktree-commands.md +238 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/skill-engine/skills/worktree/references/parallel-workflow-patterns.md +228 -0
- package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/scripts/ticket-linker.py +2 -2
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/README.md +1 -1
- package/.devcontainer/plugins/devs-marketplace/plugins/workspace-scope-guard/scripts/guard-workspace-scope.py +3 -2
- package/.devcontainer/scripts/check-setup.sh +5 -3
- package/.devcontainer/scripts/preflight.sh +113 -0
- package/.devcontainer/scripts/setup-aliases.sh +13 -8
- package/.devcontainer/scripts/setup-auth.sh +46 -0
- package/.devcontainer/scripts/setup-config.sh +29 -10
- package/.devcontainer/scripts/setup-migrate-claude.sh +80 -0
- package/.devcontainer/scripts/setup-migrate-codeforge.sh +60 -0
- package/.devcontainer/scripts/setup-plugins.sh +3 -1
- package/.devcontainer/scripts/setup-projects.sh +3 -1
- package/.devcontainer/scripts/setup-terminal.sh +3 -1
- package/.devcontainer/scripts/setup-update-claude.sh +22 -27
- package/.devcontainer/scripts/setup.sh +57 -5
- package/LICENSE.txt +14 -0
- package/README.md +79 -5
- package/package.json +2 -1
- package/setup.js +392 -21
- package/.devcontainer/docs/configuration-reference.md +0 -93
- package/.devcontainer/docs/keybindings.md +0 -100
- package/.devcontainer/docs/optional-features.md +0 -64
- package/.devcontainer/docs/plugins.md +0 -176
- package/.devcontainer/docs/troubleshooting.md +0 -128
- package/.devcontainer/scripts/setup-symlink-claude.sh +0 -36
- /package/{.devcontainer/config/defaults → .codeforge/config}/keybindings.json +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/rules/session-search.md +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/rules/spec-workflow.md +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/rules/workspace-scope.md +0 -0
- /package/{.devcontainer/config/defaults → .codeforge/config}/writing-system-prompt.md +0 -0
- /package/{.devcontainer → .codeforge/scripts}/connect-external-terminal.ps1 +0 -0
|
@@ -5,11 +5,23 @@
|
|
|
5
5
|
"workspaceFolder": "/workspaces",
|
|
6
6
|
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces,type=bind",
|
|
7
7
|
|
|
8
|
+
"initializeCommand": "bash .devcontainer/scripts/preflight.sh",
|
|
9
|
+
|
|
10
|
+
"mounts": [
|
|
11
|
+
{
|
|
12
|
+
"source": "codeforge-claude-config-${devcontainerId}",
|
|
13
|
+
"target": "/home/vscode/.claude",
|
|
14
|
+
"type": "volume"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
|
|
8
18
|
"remoteEnv": {
|
|
9
19
|
"WORKSPACE_ROOT": "/workspaces",
|
|
10
|
-
"CLAUDE_CONFIG_DIR": "/
|
|
20
|
+
"CLAUDE_CONFIG_DIR": "/home/vscode/.claude",
|
|
11
21
|
"GH_CONFIG_DIR": "/workspaces/.gh",
|
|
12
22
|
"TMPDIR": "/workspaces/.tmp",
|
|
23
|
+
"TERM": "${localEnv:TERM:xterm-256color}",
|
|
24
|
+
"COLORTERM": "truecolor",
|
|
13
25
|
"CLAUDECODE": null
|
|
14
26
|
},
|
|
15
27
|
|
|
@@ -27,15 +39,20 @@
|
|
|
27
39
|
},
|
|
28
40
|
"GH_EMAIL": {
|
|
29
41
|
"description": "GitHub email for git config (optional)"
|
|
42
|
+
},
|
|
43
|
+
"CLAUDE_AUTH_TOKEN": {
|
|
44
|
+
"description": "Claude long-lived auth token from 'claude setup-token' (optional - sk-ant-oat01-*)",
|
|
45
|
+
"documentationUrl": "https://docs.anthropic.com/en/docs/claude-code/cli-reference#claude-setup-token"
|
|
30
46
|
}
|
|
31
47
|
},
|
|
32
48
|
|
|
33
49
|
// Feature install order: external runtimes first (Node, uv, Rust, Bun),
|
|
34
|
-
// then Claude Code (
|
|
50
|
+
// then Claude Code native binary (no Node dependency), then custom features.
|
|
35
51
|
// npm-dependent features (agent-browser, ccusage, ccburn, claude-session-dashboard,
|
|
36
52
|
// biome, lsp-servers) must come after Node. uv-dependent features (ruff, claude-monitor) must
|
|
37
53
|
// come after uv. cargo-dependent features (ccms) must come after Rust.
|
|
38
|
-
// notify-hook is last (lightweight, no dependencies).
|
|
54
|
+
// notify-hook is second-to-last (lightweight, no dependencies).
|
|
55
|
+
// dbr (devcontainer-bridge) is last — standalone binary, no dependencies.
|
|
39
56
|
"overrideFeatureInstallOrder": [
|
|
40
57
|
"ghcr.io/devcontainers/features/node",
|
|
41
58
|
"ghcr.io/devcontainers/features/github-cli",
|
|
@@ -43,7 +60,7 @@
|
|
|
43
60
|
"ghcr.io/devcontainers-extra/features/uv",
|
|
44
61
|
"ghcr.io/rails/devcontainer/features/bun",
|
|
45
62
|
"ghcr.io/devcontainers/features/rust",
|
|
46
|
-
"
|
|
63
|
+
"./features/claude-code-native",
|
|
47
64
|
"./features/tmux",
|
|
48
65
|
"./features/agent-browser",
|
|
49
66
|
"./features/claude-monitor",
|
|
@@ -63,7 +80,8 @@
|
|
|
63
80
|
"./features/shellcheck",
|
|
64
81
|
"./features/hadolint",
|
|
65
82
|
"./features/biome",
|
|
66
|
-
"./features/notify-hook"
|
|
83
|
+
"./features/notify-hook",
|
|
84
|
+
"ghcr.io/bradleybeddoes/devcontainer-bridge/dbr"
|
|
67
85
|
],
|
|
68
86
|
|
|
69
87
|
"features": {
|
|
@@ -82,7 +100,7 @@
|
|
|
82
100
|
},
|
|
83
101
|
// Uncomment to add Go runtime (not installed by default):
|
|
84
102
|
// "ghcr.io/devcontainers/features/go:1": {},
|
|
85
|
-
"
|
|
103
|
+
"./features/claude-code-native": {},
|
|
86
104
|
"./features/tmux": {},
|
|
87
105
|
"./features/ccusage": {
|
|
88
106
|
"version": "latest",
|
|
@@ -133,17 +151,18 @@
|
|
|
133
151
|
"./features/notify-hook": {
|
|
134
152
|
"enableBell": true,
|
|
135
153
|
"enableOsc": true
|
|
136
|
-
}
|
|
154
|
+
},
|
|
155
|
+
"ghcr.io/bradleybeddoes/devcontainer-bridge/dbr:0.2.0": {}
|
|
137
156
|
},
|
|
138
157
|
|
|
139
|
-
"forwardPorts": [
|
|
158
|
+
"forwardPorts": [],
|
|
140
159
|
"portsAttributes": {
|
|
141
160
|
"7847": {
|
|
142
161
|
"label": "Claude Dashboard",
|
|
143
162
|
"onAutoForward": "notify"
|
|
144
163
|
},
|
|
145
164
|
"*": {
|
|
146
|
-
"onAutoForward": "
|
|
165
|
+
"onAutoForward": "notify"
|
|
147
166
|
}
|
|
148
167
|
},
|
|
149
168
|
|
|
@@ -188,7 +207,6 @@
|
|
|
188
207
|
"extensions": [
|
|
189
208
|
"wenbopan.vscode-terminal-osc-notifier",
|
|
190
209
|
"GitHub.vscode-github-actions",
|
|
191
|
-
"fabiospampinato.vscode-todo-plus",
|
|
192
210
|
"alefragnani.project-manager"
|
|
193
211
|
]
|
|
194
212
|
}
|
|
@@ -45,7 +45,7 @@ All widgets connected with powerline arrows (monokai theme).
|
|
|
45
45
|
|
|
46
46
|
- **ccstatusline npm package**: Installed on-demand via `npx` (not globally)
|
|
47
47
|
- **Configuration file**: `~/.config/ccstatusline/settings.json` with powerline theme
|
|
48
|
-
- **Claude Code integration**: Automatically updates
|
|
48
|
+
- **Claude Code integration**: Automatically updates `~/.claude/settings.json`
|
|
49
49
|
- **Disk Usage**: Minimal (~2MB when cached by npx)
|
|
50
50
|
|
|
51
51
|
## Requirements
|
|
@@ -75,9 +75,10 @@ The feature will validate these are present and exit with an error if missing.
|
|
|
75
75
|
- ✅ **Session Resume**: Copyable `cc --resume {sessionId}` command via custom-command widget
|
|
76
76
|
- ✅ **Burn Rate Tracking**: Live ccburn compact output showing pace indicators (🧊/🔥/🚨)
|
|
77
77
|
- ✅ **ANSI Colors**: High-contrast colors optimized for dark terminals
|
|
78
|
-
- ✅ **Automatic Integration**: Auto-configures
|
|
78
|
+
- ✅ **Automatic Integration**: Auto-configures `~/.claude/settings.json`
|
|
79
79
|
- ✅ **Idempotent**: Safe to run multiple times
|
|
80
80
|
- ✅ **Multi-user**: Automatically detects container user
|
|
81
|
+
- ✅ **Config-aware**: Respects `CLAUDE_CONFIG_DIR` environment variable (defaults to `~/.claude`)
|
|
81
82
|
|
|
82
83
|
## Post-Installation Steps
|
|
83
84
|
|
|
@@ -85,7 +86,7 @@ The feature will validate these are present and exit with an error if missing.
|
|
|
85
86
|
|
|
86
87
|
This feature automatically:
|
|
87
88
|
1. Creates `~/.config/ccstatusline/settings.json` with powerline configuration
|
|
88
|
-
2. Configures
|
|
89
|
+
2. Configures `~/.claude/settings.json` to use ccstatusline
|
|
89
90
|
|
|
90
91
|
**No manual steps required!**
|
|
91
92
|
|
|
@@ -105,7 +106,7 @@ You should see formatted output with powerline styling.
|
|
|
105
106
|
|
|
106
107
|
**3. Check Claude Code integration:**
|
|
107
108
|
```bash
|
|
108
|
-
cat
|
|
109
|
+
cat "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json" | jq '.statusLine'
|
|
109
110
|
```
|
|
110
111
|
|
|
111
112
|
Should show:
|
|
@@ -204,7 +205,7 @@ cat ~/.config/ccstatusline/settings.json | jq .
|
|
|
204
205
|
echo '{"model":{"display_name":"Test"}}' | npx -y ccstatusline@latest
|
|
205
206
|
|
|
206
207
|
# 3. Check Claude Code settings
|
|
207
|
-
cat
|
|
208
|
+
cat "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/settings.json" | jq '.statusLine'
|
|
208
209
|
|
|
209
210
|
# 4. Manually run auto-config if needed
|
|
210
211
|
configure-ccstatusline-auto
|
|
@@ -258,7 +259,7 @@ configure-ccstatusline-auto
|
|
|
258
259
|
npm install -g ccstatusline@latest
|
|
259
260
|
```
|
|
260
261
|
|
|
261
|
-
Then update
|
|
262
|
+
Then update `${CLAUDE_CONFIG_DIR:-~/.claude}/settings.json`:
|
|
262
263
|
```json
|
|
263
264
|
{
|
|
264
265
|
"statusLine": {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
3
|
+
# Copyright (c) 2026 Marcus Krueger
|
|
2
4
|
set -euo pipefail
|
|
3
5
|
|
|
4
6
|
# Cleanup on exit
|
|
@@ -67,7 +69,7 @@ else
|
|
|
67
69
|
fi
|
|
68
70
|
|
|
69
71
|
# Widget config is managed by file-manifest.json (deployed by setup-config.sh)
|
|
70
|
-
# Source: .
|
|
72
|
+
# Source: .codeforge/config/ccstatusline-settings.json
|
|
71
73
|
# Deployed to: ~/.config/ccstatusline/settings.json (if-changed)
|
|
72
74
|
# Template: /usr/local/share/ccstatusline/settings.template.json (always)
|
|
73
75
|
echo "[ccstatusline] Widget config managed by file-manifest.json"
|
|
@@ -75,6 +77,7 @@ echo "[ccstatusline] Widget config managed by file-manifest.json"
|
|
|
75
77
|
# Create directories so wrapper doesn't fail before first post-start
|
|
76
78
|
mkdir -p "${USER_HOME}/.config/ccstatusline"
|
|
77
79
|
mkdir -p /usr/local/share/ccstatusline
|
|
80
|
+
chown "${USERNAME}:${USERNAME}" /usr/local/share/ccstatusline
|
|
78
81
|
chown "${USERNAME}:${USERNAME}" "${USER_HOME}/.config/ccstatusline" 2>/dev/null || true
|
|
79
82
|
|
|
80
83
|
# Create session resume helper script for custom-command widget
|
|
@@ -190,9 +193,11 @@ if ! command -v jq &>/dev/null; then
|
|
|
190
193
|
exit 1
|
|
191
194
|
fi
|
|
192
195
|
|
|
193
|
-
SETTINGS_FILE="${WORKSPACE_ROOT:-/workspaces}/.claude/settings.json"
|
|
194
196
|
# Use SUDO_USER since _REMOTE_USER isn't set in post-start hooks
|
|
195
197
|
USERNAME="${SUDO_USER:-vscode}"
|
|
198
|
+
_USER_HOME=$(getent passwd "$USERNAME" 2>/dev/null | cut -d: -f6)
|
|
199
|
+
_USER_HOME="${_USER_HOME:-/home/$USERNAME}"
|
|
200
|
+
SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-${_USER_HOME}/.claude}/settings.json"
|
|
196
201
|
|
|
197
202
|
# Ensure directory exists
|
|
198
203
|
mkdir -p "$(dirname "${SETTINGS_FILE}")"
|
|
@@ -232,7 +237,7 @@ echo " ccstatusline Installation Complete"
|
|
|
232
237
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
233
238
|
echo ""
|
|
234
239
|
echo "Configuration:"
|
|
235
|
-
echo " • Source: .
|
|
240
|
+
echo " • Source: .codeforge/config/ccstatusline-settings.json"
|
|
236
241
|
echo " • Deployed to: ~/.config/ccstatusline/settings.json (by file-manifest)"
|
|
237
242
|
echo " • Template: /usr/local/share/ccstatusline/settings.template.json"
|
|
238
243
|
echo " • User: ${USERNAME}"
|
|
@@ -244,7 +249,7 @@ echo "━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
244
249
|
echo ""
|
|
245
250
|
echo "1. Widget config is deployed automatically on container start"
|
|
246
251
|
echo ""
|
|
247
|
-
echo "2. To customize: edit .
|
|
252
|
+
echo "2. To customize: edit .codeforge/config/ccstatusline-settings.json"
|
|
248
253
|
echo " Changes deploy on next container start (if-changed)"
|
|
249
254
|
echo ""
|
|
250
255
|
echo "3. Test manually:"
|
|
@@ -18,7 +18,7 @@ rules:
|
|
|
18
18
|
# File paths with optional line numbers (e.g., src/main.py:42)
|
|
19
19
|
# Covers common extensions for languages used in development
|
|
20
20
|
- description: File paths with line numbers
|
|
21
|
-
regex: '(?<=[\s(]|^)([a-zA-Z0-9_./-]+\.(py|ts|tsx|js|jsx|md|json|yml|yaml|toml|sh|rs|go|sql|css|html|svelte))(:(\d+))?'
|
|
21
|
+
regex: '(?:(?<=[\s(])|^)([a-zA-Z0-9_./-]+\.(py|ts|tsx|js|jsx|md|json|yml|yaml|toml|sh|rs|go|sql|css|html|svelte))(:(\d+))?'
|
|
22
22
|
color:
|
|
23
23
|
1: f.file_purple underline
|
|
24
24
|
4: f.line_gray
|
|
@@ -31,5 +31,5 @@ rules:
|
|
|
31
31
|
|
|
32
32
|
# Git short commit hashes (7-12 hex chars)
|
|
33
33
|
- description: Git commit hashes
|
|
34
|
-
regex: '(?<=commit |merge |pick |revert |fixup )[0-9a-f]{7,40}'
|
|
34
|
+
regex: '(?:(?<=commit )|(?<=merge )|(?<=pick )|(?<=revert )|(?<=fixup ))[0-9a-f]{7,40}'
|
|
35
35
|
color: f.hash_yellow
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Claude Code CLI (Native Binary)
|
|
2
|
+
|
|
3
|
+
Installs [Claude Code](https://docs.anthropic.com/en/docs/claude-code) as a native binary using Anthropic's official installer.
|
|
4
|
+
|
|
5
|
+
Unlike the npm-based installation (`ghcr.io/anthropics/devcontainer-features/claude-code`), this feature installs the native binary directly to `~/.local/bin/claude`. The binary is owned by the container user, so the in-session auto-updater works without permission issues.
|
|
6
|
+
|
|
7
|
+
## Options
|
|
8
|
+
|
|
9
|
+
| Option | Default | Description |
|
|
10
|
+
|--------|---------|-------------|
|
|
11
|
+
| `version` | `latest` | `latest`, `stable`, or a specific semver (e.g., `2.1.52`). Set to `none` to skip. |
|
|
12
|
+
| `username` | `automatic` | Container user to install for. `automatic` detects from `$_REMOTE_USER`. |
|
|
13
|
+
|
|
14
|
+
## How it works
|
|
15
|
+
|
|
16
|
+
1. Downloads the official installer from `https://claude.ai/install.sh`
|
|
17
|
+
2. Runs it as the target user (not root)
|
|
18
|
+
3. The installer handles platform detection, checksum verification, and binary placement
|
|
19
|
+
4. Binary is installed to `~/.local/bin/claude` with versions stored in `~/.local/share/claude/versions/`
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"features": {
|
|
26
|
+
"./features/claude-code-native": {}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
With version pinning:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"features": {
|
|
36
|
+
"./features/claude-code-native": {
|
|
37
|
+
"version": "2.1.52"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Why native over npm?
|
|
44
|
+
|
|
45
|
+
The npm installation (`npm install -g @anthropic-ai/claude-code`) runs as root during the Docker build, creating a package owned by `root`. When the container user tries to auto-update Claude Code in-session, it fails with `EACCES` because it can't write to the root-owned package directory.
|
|
46
|
+
|
|
47
|
+
The native binary installs to `~/.local/` under the container user's ownership, so `claude update` works without elevated permissions.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "claude-code-native",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"name": "Claude Code CLI (Native Binary)",
|
|
5
|
+
"description": "Installs Claude Code CLI as a native binary via the official Anthropic installer",
|
|
6
|
+
"documentationURL": "https://docs.anthropic.com/en/docs/claude-code",
|
|
7
|
+
"options": {
|
|
8
|
+
"version": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "Version to install: 'latest', 'stable', or a specific semver. Use 'none' to skip.",
|
|
11
|
+
"default": "latest"
|
|
12
|
+
},
|
|
13
|
+
"username": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Container user to install for",
|
|
16
|
+
"default": "automatic"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"customizations": {
|
|
20
|
+
"vscode": {
|
|
21
|
+
"extensions": [
|
|
22
|
+
"anthropic.claude-code"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"installsAfter": [
|
|
27
|
+
"ghcr.io/devcontainers/features/common-utils:2"
|
|
28
|
+
]
|
|
29
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
3
|
+
# Copyright (c) 2026 Marcus Krueger
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
VERSION="${VERSION:-latest}"
|
|
7
|
+
USERNAME="${USERNAME:-automatic}"
|
|
8
|
+
|
|
9
|
+
# Skip installation if version is "none"
|
|
10
|
+
if [ "${VERSION}" = "none" ]; then
|
|
11
|
+
echo "[claude-code-native] Skipping installation (version=none)"
|
|
12
|
+
exit 0
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
echo "[claude-code-native] Starting installation..."
|
|
16
|
+
echo "[claude-code-native] Version: ${VERSION}"
|
|
17
|
+
|
|
18
|
+
# === VALIDATE DEPENDENCIES ===
|
|
19
|
+
# The official installer (claude.ai/install.sh) requires curl internally
|
|
20
|
+
if ! command -v curl >/dev/null 2>&1; then
|
|
21
|
+
echo "[claude-code-native] ERROR: curl is required"
|
|
22
|
+
echo " Ensure common-utils feature is installed first"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# === DETECT USER ===
|
|
27
|
+
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
|
|
28
|
+
if [ -n "${_REMOTE_USER:-}" ]; then
|
|
29
|
+
USERNAME="${_REMOTE_USER}"
|
|
30
|
+
elif getent passwd vscode >/dev/null 2>&1; then
|
|
31
|
+
USERNAME="vscode"
|
|
32
|
+
elif getent passwd node >/dev/null 2>&1; then
|
|
33
|
+
USERNAME="node"
|
|
34
|
+
elif getent passwd codespace >/dev/null 2>&1; then
|
|
35
|
+
USERNAME="codespace"
|
|
36
|
+
else
|
|
37
|
+
USERNAME="root"
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
USER_HOME=$(getent passwd "${USERNAME}" | cut -d: -f6)
|
|
42
|
+
if [ -z "${USER_HOME}" ]; then
|
|
43
|
+
echo "[claude-code-native] ERROR: Could not determine home directory for ${USERNAME}"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
echo "[claude-code-native] Installing for user: ${USERNAME} (home: ${USER_HOME})"
|
|
48
|
+
|
|
49
|
+
# === PREPARE DIRECTORIES ===
|
|
50
|
+
mkdir -p "${USER_HOME}/.local/bin"
|
|
51
|
+
mkdir -p "${USER_HOME}/.local/share/claude"
|
|
52
|
+
mkdir -p "${USER_HOME}/.local/state"
|
|
53
|
+
mkdir -p "${USER_HOME}/.claude"
|
|
54
|
+
chown -R "${USERNAME}:" "${USER_HOME}/.local" "${USER_HOME}/.claude"
|
|
55
|
+
|
|
56
|
+
# === DETERMINE TARGET ===
|
|
57
|
+
# The official installer accepts: stable, latest, or a specific semver
|
|
58
|
+
TARGET="${VERSION}"
|
|
59
|
+
if [ "${TARGET}" != "latest" ] && [ "${TARGET}" != "stable" ]; then
|
|
60
|
+
if ! echo "${TARGET}" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
|
|
61
|
+
echo "[claude-code-native] ERROR: Invalid version '${TARGET}'"
|
|
62
|
+
echo " Use 'latest', 'stable', or a semver (e.g., 2.1.52)"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# === INSTALL ===
|
|
68
|
+
# The official Anthropic installer handles:
|
|
69
|
+
# - Platform detection (linux/darwin, x64/arm64, glibc/musl)
|
|
70
|
+
# - Manifest download and checksum verification
|
|
71
|
+
# - Binary download to ~/.local/bin/claude (symlink to ~/.local/share/claude/versions/*)
|
|
72
|
+
echo "[claude-code-native] Downloading official installer..."
|
|
73
|
+
|
|
74
|
+
if [ "${USERNAME}" = "root" ]; then
|
|
75
|
+
curl -fsSL https://claude.ai/install.sh | bash -s -- "${TARGET}"
|
|
76
|
+
else
|
|
77
|
+
su - "${USERNAME}" -c "curl -fsSL https://claude.ai/install.sh | bash -s -- \"${TARGET}\""
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# === VERIFICATION ===
|
|
81
|
+
CLAUDE_BIN="${USER_HOME}/.local/bin/claude"
|
|
82
|
+
|
|
83
|
+
if [ -x "${CLAUDE_BIN}" ]; then
|
|
84
|
+
INSTALLED_VERSION=$(su - "${USERNAME}" -c "${CLAUDE_BIN} --version 2>/dev/null" || echo "unknown")
|
|
85
|
+
echo "[claude-code-native] ✓ Claude Code installed: ${INSTALLED_VERSION}"
|
|
86
|
+
echo "[claude-code-native] Binary: ${CLAUDE_BIN}"
|
|
87
|
+
else
|
|
88
|
+
echo "[claude-code-native] ERROR: Installation failed — ${CLAUDE_BIN} not found or not executable"
|
|
89
|
+
echo "[claude-code-native] Expected binary at: ${CLAUDE_BIN}"
|
|
90
|
+
ls -la "${USER_HOME}/.local/bin/" 2>/dev/null || true
|
|
91
|
+
exit 1
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
# === POST-START HOOK ===
|
|
95
|
+
# Ensures hasCompletedOnboarding is set when token auth is configured.
|
|
96
|
+
# Runs as the LAST post-start hook (99- prefix) to catch overwrites from
|
|
97
|
+
# Claude Code CLI/extension that may race with postStartCommand.
|
|
98
|
+
HOOK_DIR="/usr/local/devcontainer-poststart.d"
|
|
99
|
+
mkdir -p "$HOOK_DIR"
|
|
100
|
+
cat > "$HOOK_DIR/99-claude-onboarding.sh" << 'HOOK_EOF'
|
|
101
|
+
#!/bin/bash
|
|
102
|
+
# Ensure hasCompletedOnboarding: true in .claude.json when token auth exists.
|
|
103
|
+
# Runs after all setup scripts to catch any overwrites by Claude Code CLI/extension.
|
|
104
|
+
_USERNAME="${SUDO_USER:-${USER:-vscode}}"
|
|
105
|
+
_USER_HOME=$(getent passwd "$_USERNAME" 2>/dev/null | cut -d: -f6)
|
|
106
|
+
_USER_HOME="${_USER_HOME:-/home/$_USERNAME}"
|
|
107
|
+
CLAUDE_DIR="${CLAUDE_CONFIG_DIR:-${_USER_HOME}/.claude}"
|
|
108
|
+
CLAUDE_JSON="$CLAUDE_DIR/.claude.json"
|
|
109
|
+
CRED_FILE="$CLAUDE_DIR/.credentials.json"
|
|
110
|
+
|
|
111
|
+
# Only act when token auth is configured
|
|
112
|
+
[ -f "$CRED_FILE" ] || exit 0
|
|
113
|
+
|
|
114
|
+
if [ -f "$CLAUDE_JSON" ]; then
|
|
115
|
+
if ! grep -q '"hasCompletedOnboarding"' "$CLAUDE_JSON" 2>/dev/null; then
|
|
116
|
+
if command -v jq >/dev/null 2>&1; then
|
|
117
|
+
jq '. + {"hasCompletedOnboarding": true}' "$CLAUDE_JSON" > "${CLAUDE_JSON}.tmp" && \
|
|
118
|
+
mv "${CLAUDE_JSON}.tmp" "$CLAUDE_JSON"
|
|
119
|
+
else
|
|
120
|
+
sed -i '$ s/}$/,\n "hasCompletedOnboarding": true\n}/' "$CLAUDE_JSON"
|
|
121
|
+
fi
|
|
122
|
+
echo "[claude-onboarding] Injected hasCompletedOnboarding into .claude.json"
|
|
123
|
+
fi
|
|
124
|
+
else
|
|
125
|
+
printf '{\n "hasCompletedOnboarding": true\n}\n' > "$CLAUDE_JSON"
|
|
126
|
+
echo "[claude-onboarding] Created .claude.json with hasCompletedOnboarding"
|
|
127
|
+
fi
|
|
128
|
+
HOOK_EOF
|
|
129
|
+
chmod +x "$HOOK_DIR/99-claude-onboarding.sh"
|
|
130
|
+
|
|
131
|
+
echo "[claude-code-native] Installation complete"
|
|
@@ -33,8 +33,8 @@ claude-dashboard -p 8080
|
|
|
33
33
|
claude-dashboard --help
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
The dashboard reads session data from `~/.claude/projects
|
|
36
|
+
The dashboard reads session data from `~/.claude/projects/`.
|
|
37
37
|
|
|
38
38
|
## How persistence works
|
|
39
39
|
|
|
40
|
-
Dashboard settings and cache are stored at `~/.claude-dashboard/`.
|
|
40
|
+
Dashboard settings and cache are stored at `~/.claude-dashboard/`. A poststart hook symlinks `~/.claude-dashboard` → `/workspaces/.claude-dashboard/`, which is bind-mounted and survives rebuilds.
|
|
@@ -14,7 +14,9 @@ Downloads and compiles the official kitty terminfo entry from the [Kitty termina
|
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The container defaults to `TERM=xterm-256color` with `COLORTERM=truecolor`, which provides full 256-color and 24-bit truecolor support for all terminals.
|
|
18
|
+
|
|
19
|
+
For Kitty users: the `devcontainer.json` `remoteEnv` uses `${localEnv:TERM:xterm-256color}`, which forwards your host `TERM` into VS Code sessions. If your host sets `TERM=xterm-kitty`, the installed terminfo ensures full Kitty-specific capability support (correct `bce` behavior, status line, etc.). For non-VS Code entry points (tmux, `docker exec`, SSH), `setup-aliases.sh` upgrades `TERM=xterm` to `xterm-256color` but preserves any other value. If no Kitty TERM is forwarded, `xterm-256color` provides equivalent color rendering.
|
|
18
20
|
|
|
19
21
|
```bash
|
|
20
22
|
# Verify installation
|
|
@@ -259,11 +259,11 @@ MCP_CONFIG_DIR="${USER_HOME}/.config/mcp"
|
|
|
259
259
|
|
|
260
260
|
**Current Behavior:**
|
|
261
261
|
- Feature creates: `~/.config/mcp/qdrant-config.json`
|
|
262
|
-
- Helper script (`configure-qdrant-mcp`) can update:
|
|
262
|
+
- Helper script (`configure-qdrant-mcp`) can update: `~/.claude/settings.json`
|
|
263
263
|
- User must manually run helper script
|
|
264
264
|
|
|
265
265
|
**Not Implemented (by request):**
|
|
266
|
-
- Automatic injection into
|
|
266
|
+
- Automatic injection into `~/.claude/settings.json` during installation
|
|
267
267
|
- This will be discussed separately
|
|
268
268
|
|
|
269
269
|
---
|
|
@@ -378,7 +378,7 @@ Based on comprehensive review, the following fixes were applied:
|
|
|
378
378
|
2. ✅ Fixed credentials leak - Added cleanup trap, secure temp file handling
|
|
379
379
|
|
|
380
380
|
### High Priority Fixes
|
|
381
|
-
3. ✅ Removed unused config directory (~/.config/mcp) - Target is
|
|
381
|
+
3. ✅ Removed unused config directory (~/.config/mcp) - Target is ~/.claude/settings.json
|
|
382
382
|
4. ✅ Consolidated helper scripts - Removed duplicate manual helper, kept auto-config only
|
|
383
383
|
5. ✅ Fixed redundant redirections - Changed `&>/dev/null 2>&1` to `&>/dev/null`
|
|
384
384
|
6. ✅ Fixed hardcoded workspace paths - Now uses `${WORKSPACE_ROOT:-/workspaces}`
|
|
@@ -154,6 +154,7 @@ The feature will validate these are present and exit with an error if missing.
|
|
|
154
154
|
- ✅ **Cloud or Local**: Supports both Qdrant Cloud and local instances
|
|
155
155
|
- ✅ **Idempotent**: Safe to run multiple times
|
|
156
156
|
- ✅ **Multi-user**: Automatically detects container user
|
|
157
|
+
- ✅ **Config-aware**: Respects `CLAUDE_CONFIG_DIR` environment variable (defaults to `~/.claude`)
|
|
157
158
|
- ✅ **Native mcpServers**: Uses VS Code's native devcontainer mcpServers support (declarative configuration)
|
|
158
159
|
- ✅ **Dynamic Configuration**: Environment variables loaded from `/workspaces/.qdrant-mcp.env` file
|
|
159
160
|
- ✅ **Secure**: API keys protected with 600 permissions on env file
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
# SPDX-License-Identifier: GPL-3.0-only
|
|
3
|
+
# Copyright (c) 2026 Marcus Krueger
|
|
2
4
|
set -euo pipefail
|
|
3
5
|
|
|
4
6
|
# Import options from devcontainer-feature.json
|
|
@@ -188,8 +190,13 @@ else
|
|
|
188
190
|
QDRANT_LOCAL_PATH="${QDRANT_LOCAL_PATH:-/workspaces/.qdrant/storage}"
|
|
189
191
|
fi
|
|
190
192
|
|
|
193
|
+
# Resolve target user's home (guards against $HOME=/root during feature install)
|
|
194
|
+
_USERNAME="${SUDO_USER:-${USER:-vscode}}"
|
|
195
|
+
_USER_HOME=$(getent passwd "$_USERNAME" 2>/dev/null | cut -d: -f6)
|
|
196
|
+
_USER_HOME="${_USER_HOME:-/home/$_USERNAME}"
|
|
197
|
+
|
|
191
198
|
# Ensure settings.json exists
|
|
192
|
-
SETTINGS_FILE="
|
|
199
|
+
SETTINGS_FILE="${CLAUDE_CONFIG_DIR:-${_USER_HOME}/.claude}/settings.json"
|
|
193
200
|
if [ ! -f "$SETTINGS_FILE" ]; then
|
|
194
201
|
echo "[mcp-qdrant] ERROR: $SETTINGS_FILE not found"
|
|
195
202
|
exit 1
|
|
@@ -257,7 +264,7 @@ fi
|
|
|
257
264
|
|
|
258
265
|
# Set proper permissions
|
|
259
266
|
chmod 644 "$SETTINGS_FILE"
|
|
260
|
-
chown "$
|
|
267
|
+
chown "${_USERNAME}:${_USERNAME}" "$SETTINGS_FILE" 2>/dev/null || true
|
|
261
268
|
|
|
262
269
|
echo "[mcp-qdrant] ✓ Configuration complete"
|
|
263
270
|
HOOK_EOF
|