codeforge-dev 1.4.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.
Files changed (131) hide show
  1. package/.devcontainer/.env +22 -0
  2. package/.devcontainer/CHANGELOG.md +197 -0
  3. package/.devcontainer/CLAUDE.md +117 -0
  4. package/.devcontainer/README.md +222 -0
  5. package/.devcontainer/config/main-system-prompt.md +502 -0
  6. package/.devcontainer/config/settings.json +47 -0
  7. package/.devcontainer/devcontainer.json +94 -0
  8. package/.devcontainer/features/README.md +113 -0
  9. package/.devcontainer/features/agent-browser/README.md +65 -0
  10. package/.devcontainer/features/agent-browser/devcontainer-feature.json +23 -0
  11. package/.devcontainer/features/agent-browser/install.sh +79 -0
  12. package/.devcontainer/features/ast-grep/README.md +24 -0
  13. package/.devcontainer/features/ast-grep/devcontainer-feature.json +24 -0
  14. package/.devcontainer/features/ast-grep/install.sh +51 -0
  15. package/.devcontainer/features/ccstatusline/README.md +296 -0
  16. package/.devcontainer/features/ccstatusline/devcontainer-feature.json +19 -0
  17. package/.devcontainer/features/ccstatusline/install.sh +290 -0
  18. package/.devcontainer/features/ccusage/README.md +205 -0
  19. package/.devcontainer/features/ccusage/devcontainer-feature.json +38 -0
  20. package/.devcontainer/features/ccusage/install.sh +132 -0
  21. package/.devcontainer/features/claude-code/README.md +498 -0
  22. package/.devcontainer/features/claude-code/config/settings.json +36 -0
  23. package/.devcontainer/features/claude-code/config/system-prompt.md +118 -0
  24. package/.devcontainer/features/claude-code/config/world-building-sp.md +1432 -0
  25. package/.devcontainer/features/claude-code/devcontainer-feature.json +42 -0
  26. package/.devcontainer/features/claude-code/install.sh +466 -0
  27. package/.devcontainer/features/claude-monitor/README.md +74 -0
  28. package/.devcontainer/features/claude-monitor/devcontainer-feature.json +38 -0
  29. package/.devcontainer/features/claude-monitor/install.sh +99 -0
  30. package/.devcontainer/features/lsp-servers/README.md +85 -0
  31. package/.devcontainer/features/lsp-servers/devcontainer-feature.json +40 -0
  32. package/.devcontainer/features/lsp-servers/install.sh +116 -0
  33. package/.devcontainer/features/mcp-qdrant/CHANGES.md +399 -0
  34. package/.devcontainer/features/mcp-qdrant/README.md +474 -0
  35. package/.devcontainer/features/mcp-qdrant/devcontainer-feature.json +57 -0
  36. package/.devcontainer/features/mcp-qdrant/install.sh +295 -0
  37. package/.devcontainer/features/mcp-qdrant/poststart-hook.sh +129 -0
  38. package/.devcontainer/features/mcp-reasoner/README.md +177 -0
  39. package/.devcontainer/features/mcp-reasoner/devcontainer-feature.json +20 -0
  40. package/.devcontainer/features/mcp-reasoner/install.sh +177 -0
  41. package/.devcontainer/features/mcp-reasoner/poststart-hook.sh +67 -0
  42. package/.devcontainer/features/notify-hook/README.md +86 -0
  43. package/.devcontainer/features/notify-hook/devcontainer-feature.json +23 -0
  44. package/.devcontainer/features/notify-hook/install.sh +38 -0
  45. package/.devcontainer/features/splitrail/README.md +140 -0
  46. package/.devcontainer/features/splitrail/devcontainer-feature.json +34 -0
  47. package/.devcontainer/features/splitrail/install.sh +129 -0
  48. package/.devcontainer/features/tree-sitter/README.md +138 -0
  49. package/.devcontainer/features/tree-sitter/devcontainer-feature.json +52 -0
  50. package/.devcontainer/features/tree-sitter/install.sh +173 -0
  51. package/.devcontainer/plugins/devs-marketplace/.claude-plugin/marketplace.json +106 -0
  52. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/.claude-plugin/plugin.json +7 -0
  53. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/hooks/hooks.json +17 -0
  54. package/.devcontainer/plugins/devs-marketplace/plugins/auto-formatter/scripts/format-file.py +101 -0
  55. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/.claude-plugin/plugin.json +7 -0
  56. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/hooks/hooks.json +17 -0
  57. package/.devcontainer/plugins/devs-marketplace/plugins/auto-linter/scripts/lint-file.py +137 -0
  58. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/.claude-plugin/plugin.json +8 -0
  59. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/SKILL.md +387 -0
  60. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/cli-flags-and-output.md +312 -0
  61. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/claude-code-headless/references/sdk-and-mcp.md +569 -0
  62. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/SKILL.md +309 -0
  63. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/compose-services.md +438 -0
  64. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker/references/dockerfile-patterns.md +340 -0
  65. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/SKILL.md +412 -0
  66. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/container-lifecycle.md +388 -0
  67. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/docker-py/references/resources-and-security.md +444 -0
  68. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/SKILL.md +344 -0
  69. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/middleware-and-lifespan.md +254 -0
  70. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/pydantic-models.md +245 -0
  71. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/routing-and-dependencies.md +255 -0
  72. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/fastapi/references/sse-and-streaming.md +318 -0
  73. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/SKILL.md +345 -0
  74. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/agents-and-tools.md +271 -0
  75. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/pydantic-ai/references/models-and-streaming.md +422 -0
  76. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/SKILL.md +220 -0
  77. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/cross-vendor-principles.md +139 -0
  78. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/patterns-and-antipatterns.md +376 -0
  79. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/skill-building/references/skill-authoring-patterns.md +356 -0
  80. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/SKILL.md +329 -0
  81. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/advanced-queries.md +314 -0
  82. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/javascript-patterns.md +323 -0
  83. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/python-patterns.md +354 -0
  84. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/sqlite/references/schema-and-pragmas.md +326 -0
  85. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/SKILL.md +356 -0
  86. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/ai-sdk-svelte.md +128 -0
  87. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/component-patterns.md +332 -0
  88. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/layercake.md +203 -0
  89. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/migration-guide.md +350 -0
  90. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/runes-and-reactivity.md +328 -0
  91. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/spa-and-routing.md +262 -0
  92. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/svelte5/references/svelte-dnd-action.md +181 -0
  93. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/SKILL.md +414 -0
  94. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/fastapi-testing.md +411 -0
  95. package/.devcontainer/plugins/devs-marketplace/plugins/codedirective-skills/skills/testing/references/svelte-testing.md +538 -0
  96. package/.devcontainer/plugins/devs-marketplace/plugins/codeforge-lsp/.claude-plugin/plugin.json +7 -0
  97. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/.claude-plugin/plugin.json +7 -0
  98. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/hooks/hooks.json +17 -0
  99. package/.devcontainer/plugins/devs-marketplace/plugins/dangerous-command-blocker/scripts/block-dangerous.py +110 -0
  100. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/.claude-plugin/plugin.json +7 -0
  101. package/.devcontainer/plugins/devs-marketplace/plugins/notify-hook/hooks/hooks.json +17 -0
  102. package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/.claude-plugin/plugin.json +7 -0
  103. package/.devcontainer/plugins/devs-marketplace/plugins/planning-reminder/hooks/hooks.json +17 -0
  104. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/.claude-plugin/plugin.json +7 -0
  105. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/hooks/hooks.json +17 -0
  106. package/.devcontainer/plugins/devs-marketplace/plugins/protected-files-guard/scripts/guard-protected.py +108 -0
  107. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272create-pr.md +337 -0
  108. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272new.md +166 -0
  109. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272review-commit.md +290 -0
  110. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/commands/ticket/357/200/272work.md +257 -0
  111. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/plugin.json +8 -0
  112. package/.devcontainer/plugins/devs-marketplace/plugins/ticket-workflow/.claude-plugin/system-prompt.md +184 -0
  113. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/.claude-plugin/plugin.json +6 -0
  114. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/config/planning-instructions.md +14 -0
  115. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/functional-conjuring-map.md +989 -0
  116. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/hooks/hooks.json +33 -0
  117. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/__pycache__/post-enhance-task.cpython-314.pyc +0 -0
  118. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhance-planning.py +71 -0
  119. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-plan.sh +68 -0
  120. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/enhancers/enhance-task.sh +120 -0
  121. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-plan.py +133 -0
  122. package/.devcontainer/plugins/devs-marketplace/plugins/workflow-enhancer/scripts/post-enhance-task.py +253 -0
  123. package/.devcontainer/scripts/setup-aliases.sh +80 -0
  124. package/.devcontainer/scripts/setup-config.sh +28 -0
  125. package/.devcontainer/scripts/setup-irie-claude.sh +32 -0
  126. package/.devcontainer/scripts/setup-plugins.sh +80 -0
  127. package/.devcontainer/scripts/setup.sh +58 -0
  128. package/LICENSE.txt +674 -0
  129. package/README.md +267 -0
  130. package/package.json +44 -0
  131. package/setup.js +83 -0
@@ -0,0 +1,290 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # Cleanup on exit
5
+ cleanup() {
6
+ rm -f /tmp/ccstatusline-*.json 2>/dev/null || true
7
+ }
8
+ trap cleanup EXIT
9
+
10
+ # Import options from devcontainer-feature.json
11
+ # NOTE: DevContainer converts camelCase options to UPPERCASE without underscores
12
+ USERNAME="${USERNAME:-automatic}"
13
+
14
+ echo "[ccstatusline] Starting installation..."
15
+
16
+ # Source NVM (Node is installed via NVM by the node feature)
17
+ if [ -f /usr/local/share/nvm/nvm.sh ]; then
18
+ source /usr/local/share/nvm/nvm.sh
19
+ fi
20
+
21
+ # Validate jq is available (required for JSON generation)
22
+ if ! command -v jq &>/dev/null; then
23
+ echo "[ccstatusline] ERROR: jq is not available"
24
+ echo " Install common-utils feature first"
25
+ exit 1
26
+ fi
27
+
28
+ # Validate npm/npx is available
29
+ if ! command -v npm &>/dev/null && ! command -v npx &>/dev/null; then
30
+ echo "[ccstatusline] ERROR: npm/npx is not available"
31
+ echo " Install node feature first"
32
+ echo " NVM path: /usr/local/share/nvm/nvm.sh"
33
+ exit 1
34
+ fi
35
+
36
+ # Determine the user
37
+ if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
38
+ USERNAME=""
39
+ for CURRENT_USER in vscode node codespace; do
40
+ if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
41
+ USERNAME=${CURRENT_USER}
42
+ break
43
+ fi
44
+ done
45
+ [ -z "${USERNAME}" ] && USERNAME=root
46
+ elif [ "${USERNAME}" = "none" ] || ! id -u "${USERNAME}" >/dev/null 2>&1; then
47
+ USERNAME=root
48
+ fi
49
+
50
+ echo "[ccstatusline] Installing for user: ${USERNAME}"
51
+
52
+ # Get user's home directory
53
+ USER_HOME=$(eval echo ~${USERNAME})
54
+
55
+ # Check if ccstatusline is available
56
+ if sudo -u "${USERNAME}" bash -c 'npx -y ccstatusline@latest --version' &>/dev/null 2>&1; then
57
+ echo "[ccstatusline] ccstatusline already available via npx"
58
+ else
59
+ echo "[ccstatusline] ccstatusline will be cached on first use via npx"
60
+ fi
61
+
62
+ echo "[ccstatusline] Generating powerline configuration..."
63
+
64
+ # Generate powerline configuration using jq (ANSI colors - same as module)
65
+ CONFIG_JSON=$(jq -n '{
66
+ version: 3,
67
+ lines: [
68
+ [
69
+ {id: "1", type: "context-length", color: "cyan"},
70
+ {id: "3", type: "git-branch", color: "brightBlack"},
71
+ {id: "5", type: "tokens-input", color: "magenta"},
72
+ {id: "7", type: "session-clock", color: "yellow"},
73
+ {id: "1eafc42e-f222-4090-a463-46de6ba81849", type: "output-style", backgroundColor: "bgBrightBlack"}
74
+ ],
75
+ [
76
+ {id: "db519d5a-80a7-4b44-8a9c-2c7d8c0a7176", type: "context-percentage-usable", backgroundColor: "bgRed"},
77
+ {id: "a529e50e-b9f3-4150-a812-937ab81545e8", type: "git-changes", backgroundColor: "bgBrightBlue"},
78
+ {id: "ac094d46-3673-4d41-84e3-dc8c5bcf639f", type: "tokens-output", backgroundColor: "bgMagenta"},
79
+ {id: "90aae111-3d3f-4bb0-8336-230f322cc2e8", type: "block-timer", backgroundColor: "bgYellow"},
80
+ {id: "d904cca6-ade8-41c1-a4f5-ddea30607a5e", type: "model", backgroundColor: "bgMagenta"}
81
+ ],
82
+ [
83
+ {id: "9bacbdb4-2e01-45de-a0c0-ee6ec30fa3c2", type: "tokens-total", backgroundColor: "bgGreen"},
84
+ {id: "a9eaae3f-7f91-459c-833a-fbc9f01a09ae", type: "git-worktree", backgroundColor: "bgBrightBlue"},
85
+ {id: "2ad12147-05fd-45fb-8336-53ba2e7df56c", type: "tokens-cached", backgroundColor: "bgBrightRed"},
86
+ {id: "a4fe7f75-2f6c-49c7-88f6-ac7381142c2c", type: "session-cost", backgroundColor: "bgBrightWhite"},
87
+ {id: "2cdff909-8297-44a1-83f9-ad4bf024391e", type: "version", backgroundColor: "bgRed"}
88
+ ]
89
+ ],
90
+ flexMode: "full-minus-40",
91
+ compactThreshold: 60,
92
+ colorLevel: 2,
93
+ inheritSeparatorColors: false,
94
+ globalBold: false,
95
+ powerline: {
96
+ enabled: true,
97
+ separators: [""],
98
+ separatorInvertBackground: [true],
99
+ startCaps: [""],
100
+ endCaps: [""],
101
+ autoAlign: false,
102
+ theme: "monokai"
103
+ },
104
+ defaultPadding: " "
105
+ }')
106
+
107
+ # Validate generated config
108
+ if ! echo "${CONFIG_JSON}" | jq empty 2>/dev/null; then
109
+ echo "[ccstatusline] ERROR: Generated configuration is invalid JSON"
110
+ exit 1
111
+ fi
112
+
113
+ echo "[ccstatusline] Writing configuration..."
114
+
115
+ CONFIG_DIR="${USER_HOME}/.config/ccstatusline"
116
+ CONFIG_FILE="${CONFIG_DIR}/settings.json"
117
+
118
+ # Create directory
119
+ mkdir -p "${CONFIG_DIR}"
120
+
121
+ # Write config using secure temp file
122
+ TEMP_CONFIG=$(mktemp)
123
+ chmod 644 "${TEMP_CONFIG}"
124
+ echo "${CONFIG_JSON}" | jq . > "${TEMP_CONFIG}"
125
+
126
+ # Move to final location
127
+ mv "${TEMP_CONFIG}" "${CONFIG_FILE}"
128
+
129
+ # Set ownership
130
+ if ! chown "${USERNAME}:${USERNAME}" "${CONFIG_FILE}" 2>/dev/null; then
131
+ echo "[ccstatusline] WARNING: Could not set ownership on ${CONFIG_FILE}"
132
+ echo " Fix: sudo chown ${USERNAME}:${USERNAME} ${CONFIG_FILE}"
133
+ fi
134
+
135
+ if ! chown "${USERNAME}:${USERNAME}" "${CONFIG_DIR}" 2>/dev/null; then
136
+ echo "[ccstatusline] WARNING: Could not set ownership on ${CONFIG_DIR}"
137
+ fi
138
+
139
+ echo "[ccstatusline] ✓ Configuration written to ${CONFIG_FILE}"
140
+
141
+ # Create template directory and save config template
142
+ echo "[ccstatusline] Creating configuration template..."
143
+ mkdir -p /usr/local/share/ccstatusline
144
+ TEMPLATE_FILE=/usr/local/share/ccstatusline/settings.template.json
145
+ echo "${CONFIG_JSON}" | jq . > "${TEMPLATE_FILE}"
146
+ chmod 644 "${TEMPLATE_FILE}"
147
+ echo "[ccstatusline] ✓ Template saved to ${TEMPLATE_FILE}"
148
+
149
+ # Create wrapper script to protect configuration
150
+ echo "[ccstatusline] Creating wrapper script..."
151
+ cat > /usr/local/bin/ccstatusline-wrapper <<'WRAPPER_EOF'
152
+ #!/bin/bash
153
+ # ccstatusline wrapper script
154
+ # Ensures custom powerline configuration is valid before running ccstatusline
155
+
156
+ set -euo pipefail
157
+
158
+ CONFIG_FILE="$HOME/.config/ccstatusline/settings.json"
159
+ TEMPLATE_FILE="/usr/local/share/ccstatusline/settings.template.json"
160
+
161
+ # Ensure config directory exists
162
+ mkdir -p "$HOME/.config/ccstatusline"
163
+
164
+ # Function to check if config is valid
165
+ is_config_valid() {
166
+ if [[ ! -f "$CONFIG_FILE" ]]; then
167
+ return 1
168
+ fi
169
+
170
+ # Check if powerline is enabled (key indicator of custom config)
171
+ if ! grep -q '"enabled"[[:space:]]*:[[:space:]]*true' "$CONFIG_FILE" 2>/dev/null; then
172
+ return 1
173
+ fi
174
+
175
+ # Check if ANSI colors are present (backgroundColor with bg prefix)
176
+ if ! grep -q 'bgRed\|bgMagenta\|bgGreen\|bgBrightBlue' "$CONFIG_FILE" 2>/dev/null; then
177
+ return 1
178
+ fi
179
+
180
+ # Validate JSON syntax
181
+ if ! jq empty "$CONFIG_FILE" 2>/dev/null; then
182
+ return 1
183
+ fi
184
+
185
+ return 0
186
+ }
187
+
188
+ # Restore config from template if missing or invalid
189
+ if ! is_config_valid; then
190
+ if [[ -f "$TEMPLATE_FILE" ]]; then
191
+ cp "$TEMPLATE_FILE" "$CONFIG_FILE"
192
+ chmod 644 "$CONFIG_FILE"
193
+ else
194
+ echo "[ccstatusline-wrapper] ERROR: Template file not found at $TEMPLATE_FILE" >&2
195
+ exit 1
196
+ fi
197
+ fi
198
+
199
+ # Run ccstatusline with all passed arguments
200
+ exec npx -y ccstatusline@latest "$@"
201
+ WRAPPER_EOF
202
+
203
+ chmod +x /usr/local/bin/ccstatusline-wrapper
204
+ echo "[ccstatusline] ✓ Wrapper installed at /usr/local/bin/ccstatusline-wrapper"
205
+
206
+ # Create post-start hook directory (standard pattern for DevContainer features)
207
+ mkdir -p /usr/local/devcontainer-poststart.d
208
+
209
+ # Create post-start hook script for Claude Code integration
210
+ # Runs on EVERY container start to ensure statusLine is always configured
211
+ # This handles cached images, config deletion, and corruption scenarios
212
+ # Note: Uses prefix 40 to run before MCP servers (50-51) to ensure settings.json exists first
213
+ cat > /usr/local/devcontainer-poststart.d/40-ccstatusline.sh <<'AUTOEOF'
214
+ #!/bin/bash
215
+ set -euo pipefail
216
+
217
+ echo "[ccstatusline] Auto-configuring Claude Code integration..."
218
+
219
+ # Validate prerequisites
220
+ if ! command -v jq &>/dev/null; then
221
+ echo "[ccstatusline] ERROR: jq is not available"
222
+ echo " Ensure common-utils feature is installed"
223
+ exit 1
224
+ fi
225
+
226
+ SETTINGS_FILE="${WORKSPACE_ROOT:-/workspaces}/.claude/settings.json"
227
+ # Use SUDO_USER since _REMOTE_USER isn't set in post-start hooks
228
+ USERNAME="${SUDO_USER:-vscode}"
229
+
230
+ # Ensure directory exists
231
+ mkdir -p "$(dirname "${SETTINGS_FILE}")"
232
+
233
+ # Initialize settings.json if missing
234
+ if [ ! -f "${SETTINGS_FILE}" ]; then
235
+ echo '{}' > "${SETTINGS_FILE}"
236
+ fi
237
+
238
+ # Add statusLine configuration (atomic) - use wrapper to protect config
239
+ jq '.statusLine //= {}' "${SETTINGS_FILE}" | \
240
+ jq '.statusLine = {
241
+ type: "command",
242
+ command: "/usr/local/bin/ccstatusline-wrapper"
243
+ }' > "${SETTINGS_FILE}.tmp"
244
+
245
+ # Atomic move (only if jq succeeded)
246
+ if [ $? -eq 0 ]; then
247
+ mv "${SETTINGS_FILE}.tmp" "${SETTINGS_FILE}"
248
+ if ! chown "${USERNAME}:${USERNAME}" "${SETTINGS_FILE}" 2>/dev/null; then
249
+ echo "[ccstatusline] WARNING: Could not set ownership on ${SETTINGS_FILE}"
250
+ fi
251
+ echo "[ccstatusline] ✓ Configured in ${SETTINGS_FILE}"
252
+ echo "[ccstatusline] Verify: cat ${SETTINGS_FILE} | jq '.statusLine'"
253
+ else
254
+ rm -f "${SETTINGS_FILE}.tmp"
255
+ echo "[ccstatusline] ERROR: Configuration failed"
256
+ exit 1
257
+ fi
258
+ AUTOEOF
259
+
260
+ chmod +x /usr/local/devcontainer-poststart.d/40-ccstatusline.sh
261
+ echo "[ccstatusline] ✓ Post-start hook created at /usr/local/devcontainer-poststart.d/40-ccstatusline.sh"
262
+ echo ""
263
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
264
+ echo " ccstatusline Installation Complete"
265
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
266
+ echo ""
267
+ echo "Configuration:"
268
+ echo " • Config file: ${CONFIG_FILE}"
269
+ echo " • User: ${USERNAME}"
270
+ echo " • Theme: Powerline (3 lines, 13 widgets, ANSI colors)"
271
+ echo " • Protected by: /usr/local/bin/ccstatusline-wrapper"
272
+ echo ""
273
+ echo "Display:"
274
+ echo " Line 1: Context | Git Branch | Tokens In | Clock | Output Style"
275
+ echo " Line 2: Context % | Git Changes | Tokens Out | Block Timer | Model"
276
+ echo " Line 3: Tokens Total | Git Worktree | Cached | Cost | Version"
277
+ echo ""
278
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
279
+ echo " Next Steps"
280
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
281
+ echo ""
282
+ echo "1. Configuration will be applied automatically on container creation"
283
+ echo ""
284
+ echo "2. Test manually:"
285
+ echo " echo '{\"model\":{\"display_name\":\"Test\"}}' | npx -y ccstatusline@latest"
286
+ echo ""
287
+ echo "3. View configuration:"
288
+ echo " cat ${CONFIG_FILE} | jq ."
289
+ echo ""
290
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
@@ -0,0 +1,205 @@
1
+ # ccusage - Claude Code Usage Analyzer
2
+
3
+ A DevContainer feature that installs the ccusage CLI tool for analyzing Claude Code and Codex token usage from local JSONL files.
4
+
5
+ ## Overview
6
+
7
+ ccusage tracks token usage and costs across daily, monthly, and session-based reports with live monitoring capabilities. This feature configures shell aliases for easy access to the tool via `npx`.
8
+
9
+ ## Installation
10
+
11
+ Add this feature to your `.devcontainer/devcontainer.json`:
12
+
13
+ ```json
14
+ {
15
+ "features": {
16
+ "ghcr.io/devcontainers/features/node:1": {},
17
+ "./features/ccusage": {}
18
+ }
19
+ }
20
+ ```
21
+
22
+ ### With Custom Options
23
+
24
+ ```json
25
+ {
26
+ "features": {
27
+ "ghcr.io/devcontainers/features/node:1": {},
28
+ "./features/ccusage": {
29
+ "version": "latest",
30
+ "shells": "both",
31
+ "username": "automatic"
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ ## Options
38
+
39
+ | Option | Type | Default | Description |
40
+ |--------|------|---------|-------------|
41
+ | `version` | string | `latest` | ccusage version to use (e.g., 'latest', '1.0.0') |
42
+ | `shells` | string | `both` | Which shells to configure: `bash`, `zsh`, or `both` |
43
+ | `username` | string | `automatic` | Container user to install for (auto-detects vscode/node/codespace) |
44
+
45
+ ## Usage
46
+
47
+ Once installed, use the `ccusage` command from any shell:
48
+
49
+ ### Daily Usage Report
50
+ ```bash
51
+ ccusage --daily
52
+ ```
53
+ Shows token usage and costs for today.
54
+
55
+ ### Monthly Report
56
+ ```bash
57
+ ccusage --monthly
58
+ ```
59
+ Displays monthly token consumption and costs.
60
+
61
+ ### Live Monitoring
62
+ ```bash
63
+ ccusage --live
64
+ ```
65
+ Real-time monitoring of your Claude Code usage.
66
+
67
+ ### JSON Output
68
+ ```bash
69
+ ccusage --json
70
+ ```
71
+ Output data in JSON format for scripting/integration.
72
+
73
+ ### Compact Display
74
+ ```bash
75
+ ccusage --compact
76
+ ```
77
+ Minimal output for quick checks.
78
+
79
+ ## Features
80
+
81
+ - **Beautiful Tables**: Formatted output with clear cost breakdown
82
+ - **Multiple Models**: Supports Claude Opus, Sonnet, and other models
83
+ - **Timezone Support**: Customize timezone and locale settings
84
+ - **Session Tracking**: View usage by individual sessions
85
+ - **Cost Tracking**: Accurate pricing for different models
86
+
87
+ ## How It Works
88
+
89
+ This feature creates a shell alias that points to `npx -y ccusage@<version>`, which automatically downloads and runs the latest version of ccusage without requiring a global installation.
90
+
91
+ ccusage automatically reads from Claude Code's JSONL usage logs located in:
92
+ - `~/.claude/` (default)
93
+ - `$CLAUDE_CONFIG_DIR` (if customized)
94
+
95
+ ## Advanced Options
96
+
97
+ For full list of ccusage command options:
98
+ ```bash
99
+ ccusage --help
100
+ ```
101
+
102
+ ## Example Configurations
103
+
104
+ ### Install for Specific User (zsh only)
105
+ ```json
106
+ {
107
+ "features": {
108
+ "./features/ccusage": {
109
+ "username": "vscode",
110
+ "shells": "zsh"
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ ### Pin to Specific Version
117
+ ```json
118
+ {
119
+ "features": {
120
+ "./features/ccusage": {
121
+ "version": "1.0.0"
122
+ }
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### Bash Only Installation
128
+ ```json
129
+ {
130
+ "features": {
131
+ "./features/ccusage": {
132
+ "shells": "bash"
133
+ }
134
+ }
135
+ }
136
+ ```
137
+
138
+ ## Troubleshooting
139
+
140
+ ### Command Not Found
141
+
142
+ If `ccusage` is not found after installation:
143
+
144
+ 1. **Reload your shell**:
145
+ ```bash
146
+ source ~/.bashrc # for bash
147
+ source ~/.zshrc # for zsh
148
+ ```
149
+
150
+ 2. **Check if alias is configured**:
151
+ ```bash
152
+ grep ccusage ~/.bashrc # for bash
153
+ grep ccusage ~/.zshrc # for zsh
154
+ ```
155
+
156
+ 3. **Verify npx is available**:
157
+ ```bash
158
+ npx --version
159
+ ```
160
+
161
+ ### Permission Errors
162
+
163
+ If you see permission errors:
164
+ ```bash
165
+ sudo chown -R $(whoami):$(whoami) ~/.bashrc
166
+ sudo chown -R $(whoami):$(whoami) ~/.zshrc
167
+ ```
168
+
169
+ ### Network Issues
170
+
171
+ If ccusage fails to download:
172
+ - Check your internet connection
173
+ - The tool will be cached after first successful download
174
+ - Try running manually: `npx -y ccusage@latest --version`
175
+
176
+ ## Dependencies
177
+
178
+ This feature requires:
179
+ - **Node.js**: Install the `node` feature first
180
+ - The feature automatically declares this dependency via `installsAfter`
181
+
182
+ ## Integration with Other Tools
183
+
184
+ This tool complements:
185
+ - **splitrail**: Real-time monitoring during active sessions
186
+ - **ccstatusline**: Visual status display in terminal
187
+
188
+ ## Links
189
+
190
+ - **GitHub**: https://github.com/ryoppippi/ccusage
191
+ - **NPM**: https://www.npmjs.com/package/ccusage
192
+ - **DevContainer Features**: https://containers.dev/features
193
+
194
+ ## Version History
195
+
196
+ ### 1.0.0
197
+ - Initial release as DevContainer feature
198
+ - Automatic user detection
199
+ - Configurable shell support (bash/zsh/both)
200
+ - Version pinning support
201
+ - Idempotent installation
202
+
203
+ ## License
204
+
205
+ This feature wrapper follows the same license as the underlying ccusage tool.
@@ -0,0 +1,38 @@
1
+ {
2
+ "id": "ccusage",
3
+ "version": "1.0.0",
4
+ "name": "ccusage - Claude Code Usage Analyzer",
5
+ "description": "Installs ccusage CLI tool for analyzing Claude Code token usage",
6
+ "maintainer": "AnExiledDev",
7
+ "documentationURL": "https://github.com/ryoppippi/ccusage",
8
+ "options": {
9
+ "version": {
10
+ "type": "string",
11
+ "description": "ccusage version to use (e.g., 'latest', '1.0.0')",
12
+ "default": "latest"
13
+ },
14
+ "shells": {
15
+ "type": "string",
16
+ "description": "Which shells to configure (bash, zsh, or both)",
17
+ "default": "both",
18
+ "enum": [
19
+ "bash",
20
+ "zsh",
21
+ "both"
22
+ ],
23
+ "proposals": [
24
+ "bash",
25
+ "zsh",
26
+ "both"
27
+ ]
28
+ },
29
+ "username": {
30
+ "type": "string",
31
+ "description": "Container user to install for",
32
+ "default": "automatic"
33
+ }
34
+ },
35
+ "installsAfter": [
36
+ "ghcr.io/devcontainers/features/node:1"
37
+ ]
38
+ }
@@ -0,0 +1,132 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+
4
+ # === SETUP ===
5
+ cleanup() {
6
+ # No temp files needed for this simple feature
7
+ :
8
+ }
9
+ trap cleanup EXIT
10
+
11
+ # === IMPORT OPTIONS ===
12
+ # NOTE: DevContainer converts camelCase options to UPPERCASE without underscores
13
+ # "version" → VERSION, "shells" → SHELLS, "username" → USERNAME
14
+ CCUSAGE_VERSION="${VERSION:-latest}"
15
+ SHELLS="${SHELLS:-both}"
16
+ USERNAME="${USERNAME:-automatic}"
17
+
18
+ echo "[ccusage] Starting ccusage installation..."
19
+
20
+ # === SOURCE NVM ===
21
+ # Node is installed via NVM by the node feature
22
+ if [ -f /usr/local/share/nvm/nvm.sh ]; then
23
+ source /usr/local/share/nvm/nvm.sh
24
+ fi
25
+
26
+ # === VALIDATE DEPENDENCIES ===
27
+ if ! command -v npx &>/dev/null; then
28
+ echo "[ccusage] ERROR: npx is not available"
29
+ echo " Ensure node feature is installed first"
30
+ echo " NVM path: /usr/local/share/nvm/nvm.sh"
31
+ exit 1
32
+ fi
33
+
34
+ # === VALIDATE INPUT ===
35
+ # Validate shells parameter
36
+ if [[ ! "${SHELLS}" =~ ^(bash|zsh|both)$ ]]; then
37
+ echo "[ccusage] ERROR: shells must be 'bash', 'zsh', or 'both'"
38
+ echo " Provided: ${SHELLS}"
39
+ exit 1
40
+ fi
41
+
42
+ # Validate version format (basic check)
43
+ if [[ ! "${CCUSAGE_VERSION}" =~ ^[a-zA-Z0-9.-]+$ ]]; then
44
+ echo "[ccusage] ERROR: version contains invalid characters"
45
+ echo " Provided: ${CCUSAGE_VERSION}"
46
+ exit 1
47
+ fi
48
+
49
+ # === DETECT USER ===
50
+ if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
51
+ USERNAME=""
52
+ for CURRENT_USER in vscode node codespace; do
53
+ if id -u "${CURRENT_USER}" >/dev/null 2>&1; then
54
+ USERNAME=${CURRENT_USER}
55
+ break
56
+ fi
57
+ done
58
+ [ -z "${USERNAME}" ] && USERNAME=root
59
+ elif [ "${USERNAME}" = "none" ] || ! id -u "${USERNAME}" >/dev/null 2>&1; then
60
+ USERNAME=root
61
+ fi
62
+
63
+ echo "[ccusage] Installing for user: ${USERNAME}"
64
+
65
+ # === GET USER HOME ===
66
+ USER_HOME=$(eval echo "~${USERNAME}")
67
+ if [ ! -d "${USER_HOME}" ]; then
68
+ echo "[ccusage] ERROR: Home directory not found for user ${USERNAME}"
69
+ exit 1
70
+ fi
71
+
72
+ # === INSTALL (CREATE ALIASES) ===
73
+ ALIAS_CMD="alias ccusage=\"npx -y ccusage@${CCUSAGE_VERSION}\""
74
+
75
+ configure_shell() {
76
+ local shell_rc="$1"
77
+ local shell_name="$2"
78
+
79
+ if [ ! -f "${shell_rc}" ]; then
80
+ echo "[ccusage] Creating ${shell_name} config file: ${shell_rc}"
81
+ sudo -u "${USERNAME}" touch "${shell_rc}"
82
+ fi
83
+
84
+ if grep -q "alias ccusage=" "${shell_rc}"; then
85
+ echo "[ccusage] ${shell_name} alias already configured. Skipping..."
86
+ else
87
+ echo "[ccusage] Adding ccusage alias to ${shell_name}"
88
+ echo "${ALIAS_CMD}" >> "${shell_rc}"
89
+ if ! chown "${USERNAME}:${USERNAME}" "${shell_rc}" 2>/dev/null; then
90
+ echo "[ccusage] WARNING: Could not set ownership on ${shell_rc}"
91
+ echo " Fix: sudo chown ${USERNAME}:${USERNAME} ${shell_rc}"
92
+ fi
93
+ fi
94
+ }
95
+
96
+ # Configure requested shells
97
+ if [ "${SHELLS}" = "bash" ] || [ "${SHELLS}" = "both" ]; then
98
+ configure_shell "${USER_HOME}/.bashrc" "bash"
99
+ fi
100
+
101
+ if [ "${SHELLS}" = "zsh" ] || [ "${SHELLS}" = "both" ]; then
102
+ configure_shell "${USER_HOME}/.zshrc" "zsh"
103
+ fi
104
+
105
+ # === VERIFICATION ===
106
+ echo "[ccusage] Verifying npx can access ccusage..."
107
+ if sudo -u "${USERNAME}" bash -c "npx -y ccusage@${CCUSAGE_VERSION} --version" &>/dev/null; then
108
+ echo "[ccusage] ✓ ccusage is accessible"
109
+ else
110
+ echo "[ccusage] WARNING: Could not verify ccusage installation"
111
+ echo " This may be due to network connectivity"
112
+ echo " The alias will still work once ccusage is available"
113
+ fi
114
+
115
+ # === SUMMARY ===
116
+ echo ""
117
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
118
+ echo " ccusage Installation Complete"
119
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
120
+ echo ""
121
+ echo "Configuration:"
122
+ echo " • User: ${USERNAME}"
123
+ echo " • Version: ${CCUSAGE_VERSION}"
124
+ echo " • Shells: ${SHELLS}"
125
+ echo ""
126
+ echo "Usage:"
127
+ echo " ccusage --daily # Daily usage report"
128
+ echo " ccusage --monthly # Monthly report"
129
+ echo " ccusage --live # Live monitoring"
130
+ echo " ccusage --help # Full options"
131
+ echo ""
132
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"