@su-record/vibe 2.6.14 → 2.6.16

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 (233) hide show
  1. package/CLAUDE.md +1 -394
  2. package/LICENSE +21 -21
  3. package/README.md +203 -497
  4. package/agents/architect-low.md +41 -41
  5. package/agents/architect-medium.md +59 -59
  6. package/agents/architect.md +80 -80
  7. package/agents/build-error-resolver.md +115 -115
  8. package/agents/compounder.md +261 -261
  9. package/agents/diagrammer.md +178 -178
  10. package/agents/e2e-tester.md +266 -266
  11. package/agents/explorer-low.md +42 -42
  12. package/agents/explorer-medium.md +59 -59
  13. package/agents/explorer.md +48 -48
  14. package/agents/implementer-low.md +43 -43
  15. package/agents/implementer-medium.md +52 -52
  16. package/agents/implementer.md +54 -54
  17. package/agents/refactor-cleaner.md +143 -143
  18. package/agents/research/best-practices-agent.md +199 -199
  19. package/agents/research/codebase-patterns-agent.md +157 -157
  20. package/agents/research/framework-docs-agent.md +188 -188
  21. package/agents/research/security-advisory-agent.md +213 -213
  22. package/agents/review/architecture-reviewer.md +107 -107
  23. package/agents/review/complexity-reviewer.md +116 -116
  24. package/agents/review/data-integrity-reviewer.md +88 -88
  25. package/agents/review/git-history-reviewer.md +103 -103
  26. package/agents/review/performance-reviewer.md +86 -86
  27. package/agents/review/python-reviewer.md +150 -150
  28. package/agents/review/rails-reviewer.md +139 -139
  29. package/agents/review/react-reviewer.md +144 -144
  30. package/agents/review/security-reviewer.md +80 -80
  31. package/agents/review/simplicity-reviewer.md +140 -140
  32. package/agents/review/test-coverage-reviewer.md +116 -116
  33. package/agents/review/typescript-reviewer.md +127 -127
  34. package/agents/searcher.md +54 -54
  35. package/agents/simplifier.md +120 -120
  36. package/agents/tester.md +49 -49
  37. package/agents/ui-previewer.md +268 -268
  38. package/commands/vibe.analyze.md +356 -356
  39. package/commands/vibe.reason.md +329 -329
  40. package/commands/vibe.review.md +412 -412
  41. package/commands/vibe.run.md +1266 -1266
  42. package/commands/vibe.spec.md +1054 -1054
  43. package/commands/vibe.spec.review.md +319 -319
  44. package/commands/vibe.trace.md +161 -161
  45. package/commands/vibe.utils.md +376 -376
  46. package/commands/vibe.verify.md +375 -375
  47. package/dist/cli/collaborator.js +52 -52
  48. package/dist/cli/detect.js +32 -32
  49. package/dist/cli/hud.js +20 -20
  50. package/dist/cli/index.js +118 -118
  51. package/dist/cli/index.js.map +1 -1
  52. package/dist/cli/llm.js +144 -144
  53. package/dist/cli/mcp.d.ts +49 -0
  54. package/dist/cli/mcp.d.ts.map +1 -0
  55. package/dist/cli/mcp.js +169 -0
  56. package/dist/cli/mcp.js.map +1 -0
  57. package/dist/cli/postinstall.js +858 -858
  58. package/dist/cli/setup/ProjectSetup.d.ts +3 -3
  59. package/dist/cli/setup/ProjectSetup.d.ts.map +1 -1
  60. package/dist/cli/setup/ProjectSetup.js +76 -30
  61. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  62. package/dist/lib/DeepInit.js +24 -24
  63. package/dist/lib/IterationTracker.js +11 -11
  64. package/dist/lib/PythonParser.js +108 -108
  65. package/dist/lib/ReviewRace.js +96 -96
  66. package/dist/lib/SkillFrontmatter.js +28 -28
  67. package/dist/lib/SkillQualityGate.js +9 -9
  68. package/dist/lib/SkillRepository.js +159 -159
  69. package/dist/lib/UltraQA.js +77 -77
  70. package/dist/lib/gemini-api.js +5 -5
  71. package/dist/lib/gemini-mcp.d.ts +10 -0
  72. package/dist/lib/gemini-mcp.d.ts.map +1 -0
  73. package/dist/lib/gemini-mcp.js +353 -0
  74. package/dist/lib/gemini-mcp.js.map +1 -0
  75. package/dist/lib/gpt-api.js +4 -4
  76. package/dist/lib/gpt-mcp.d.ts +10 -0
  77. package/dist/lib/gpt-mcp.d.ts.map +1 -0
  78. package/dist/lib/gpt-mcp.js +352 -0
  79. package/dist/lib/gpt-mcp.js.map +1 -0
  80. package/dist/lib/memory/KnowledgeGraph.js +4 -4
  81. package/dist/lib/memory/MemorySearch.js +20 -20
  82. package/dist/lib/memory/MemoryStorage.js +64 -64
  83. package/dist/orchestrator/AgentManager.js +12 -12
  84. package/dist/orchestrator/MultiLlmResearch.js +8 -8
  85. package/dist/orchestrator/SmartRouter.js +11 -11
  86. package/dist/orchestrator/parallelResearch.js +24 -24
  87. package/dist/tools/analytics/getUsageAnalytics.d.ts +10 -0
  88. package/dist/tools/analytics/getUsageAnalytics.d.ts.map +1 -0
  89. package/dist/tools/analytics/getUsageAnalytics.js +246 -0
  90. package/dist/tools/analytics/getUsageAnalytics.js.map +1 -0
  91. package/dist/tools/analytics/index.d.ts +5 -0
  92. package/dist/tools/analytics/index.d.ts.map +1 -0
  93. package/dist/tools/analytics/index.js +5 -0
  94. package/dist/tools/analytics/index.js.map +1 -0
  95. package/dist/tools/convention/analyzeComplexity.test.js +115 -115
  96. package/dist/tools/convention/getCodingGuide.d.ts +7 -0
  97. package/dist/tools/convention/getCodingGuide.d.ts.map +1 -0
  98. package/dist/tools/convention/getCodingGuide.js +69 -0
  99. package/dist/tools/convention/getCodingGuide.js.map +1 -0
  100. package/dist/tools/convention/validateCodeQuality.test.js +104 -104
  101. package/dist/tools/planning/analyzeRequirements.d.ts +9 -0
  102. package/dist/tools/planning/analyzeRequirements.d.ts.map +1 -0
  103. package/dist/tools/planning/analyzeRequirements.js +171 -0
  104. package/dist/tools/planning/analyzeRequirements.js.map +1 -0
  105. package/dist/tools/planning/createUserStories.d.ts +9 -0
  106. package/dist/tools/planning/createUserStories.d.ts.map +1 -0
  107. package/dist/tools/planning/createUserStories.js +124 -0
  108. package/dist/tools/planning/createUserStories.js.map +1 -0
  109. package/dist/tools/planning/featureRoadmap.d.ts +10 -0
  110. package/dist/tools/planning/featureRoadmap.d.ts.map +1 -0
  111. package/dist/tools/planning/featureRoadmap.js +207 -0
  112. package/dist/tools/planning/featureRoadmap.js.map +1 -0
  113. package/dist/tools/planning/generatePrd.d.ts +11 -0
  114. package/dist/tools/planning/generatePrd.d.ts.map +1 -0
  115. package/dist/tools/planning/generatePrd.js +161 -0
  116. package/dist/tools/planning/generatePrd.js.map +1 -0
  117. package/dist/tools/planning/index.d.ts +8 -0
  118. package/dist/tools/planning/index.d.ts.map +1 -0
  119. package/dist/tools/planning/index.js +8 -0
  120. package/dist/tools/planning/index.js.map +1 -0
  121. package/dist/tools/prompt/analyzePrompt.d.ts +7 -0
  122. package/dist/tools/prompt/analyzePrompt.d.ts.map +1 -0
  123. package/dist/tools/prompt/analyzePrompt.js +150 -0
  124. package/dist/tools/prompt/analyzePrompt.js.map +1 -0
  125. package/dist/tools/prompt/enhancePrompt.d.ts +8 -0
  126. package/dist/tools/prompt/enhancePrompt.d.ts.map +1 -0
  127. package/dist/tools/prompt/enhancePrompt.js +110 -0
  128. package/dist/tools/prompt/enhancePrompt.js.map +1 -0
  129. package/dist/tools/prompt/enhancePromptGemini.d.ts +8 -0
  130. package/dist/tools/prompt/enhancePromptGemini.d.ts.map +1 -0
  131. package/dist/tools/prompt/enhancePromptGemini.js +332 -0
  132. package/dist/tools/prompt/enhancePromptGemini.js.map +1 -0
  133. package/dist/tools/prompt/index.d.ts +7 -0
  134. package/dist/tools/prompt/index.d.ts.map +1 -0
  135. package/dist/tools/prompt/index.js +7 -0
  136. package/dist/tools/prompt/index.js.map +1 -0
  137. package/dist/tools/reasoning/applyReasoningFramework.d.ts +8 -0
  138. package/dist/tools/reasoning/applyReasoningFramework.d.ts.map +1 -0
  139. package/dist/tools/reasoning/applyReasoningFramework.js +266 -0
  140. package/dist/tools/reasoning/applyReasoningFramework.js.map +1 -0
  141. package/dist/tools/reasoning/index.d.ts +5 -0
  142. package/dist/tools/reasoning/index.d.ts.map +1 -0
  143. package/dist/tools/reasoning/index.js +5 -0
  144. package/dist/tools/reasoning/index.js.map +1 -0
  145. package/dist/tools/spec/prdParser.test.js +171 -171
  146. package/dist/tools/spec/specGenerator.js +169 -169
  147. package/dist/tools/spec/traceabilityMatrix.js +64 -64
  148. package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
  149. package/dist/tools/thinking/analyzeProblem.d.ts +7 -0
  150. package/dist/tools/thinking/analyzeProblem.d.ts.map +1 -0
  151. package/dist/tools/thinking/analyzeProblem.js +55 -0
  152. package/dist/tools/thinking/analyzeProblem.js.map +1 -0
  153. package/dist/tools/thinking/breakDownProblem.d.ts +8 -0
  154. package/dist/tools/thinking/breakDownProblem.d.ts.map +1 -0
  155. package/dist/tools/thinking/breakDownProblem.js +145 -0
  156. package/dist/tools/thinking/breakDownProblem.js.map +1 -0
  157. package/dist/tools/thinking/createThinkingChain.d.ts +7 -0
  158. package/dist/tools/thinking/createThinkingChain.d.ts.map +1 -0
  159. package/dist/tools/thinking/createThinkingChain.js +44 -0
  160. package/dist/tools/thinking/createThinkingChain.js.map +1 -0
  161. package/dist/tools/thinking/formatAsPlan.d.ts +9 -0
  162. package/dist/tools/thinking/formatAsPlan.d.ts.map +1 -0
  163. package/dist/tools/thinking/formatAsPlan.js +78 -0
  164. package/dist/tools/thinking/formatAsPlan.js.map +1 -0
  165. package/dist/tools/thinking/index.d.ts +10 -0
  166. package/dist/tools/thinking/index.d.ts.map +1 -0
  167. package/dist/tools/thinking/index.js +10 -0
  168. package/dist/tools/thinking/index.js.map +1 -0
  169. package/dist/tools/thinking/stepByStepAnalysis.d.ts +8 -0
  170. package/dist/tools/thinking/stepByStepAnalysis.d.ts.map +1 -0
  171. package/dist/tools/thinking/stepByStepAnalysis.js +63 -0
  172. package/dist/tools/thinking/stepByStepAnalysis.js.map +1 -0
  173. package/dist/tools/thinking/thinkAloudProcess.d.ts +8 -0
  174. package/dist/tools/thinking/thinkAloudProcess.d.ts.map +1 -0
  175. package/dist/tools/thinking/thinkAloudProcess.js +80 -0
  176. package/dist/tools/thinking/thinkAloudProcess.js.map +1 -0
  177. package/hooks/hooks.json +222 -222
  178. package/hooks/scripts/code-check.js +22 -22
  179. package/hooks/scripts/code-review.js +22 -22
  180. package/hooks/scripts/complexity.js +22 -22
  181. package/hooks/scripts/compound.js +23 -23
  182. package/hooks/scripts/context-save.js +33 -33
  183. package/hooks/scripts/gemini-ui-gen.js +281 -281
  184. package/hooks/scripts/generate-brand-assets.js +474 -474
  185. package/hooks/scripts/hud-multiline.js +262 -262
  186. package/hooks/scripts/hud-status.js +291 -291
  187. package/hooks/scripts/keyword-detector.js +214 -214
  188. package/hooks/scripts/llm-orchestrate.js +171 -171
  189. package/hooks/scripts/post-edit.js +97 -97
  190. package/hooks/scripts/post-tool-verify.js +210 -210
  191. package/hooks/scripts/pre-tool-guard.js +125 -125
  192. package/hooks/scripts/recall.js +22 -22
  193. package/hooks/scripts/session-start.js +30 -30
  194. package/hooks/scripts/skill-injector.js +191 -191
  195. package/hooks/scripts/utils.js +97 -97
  196. package/languages/csharp-unity.md +515 -515
  197. package/languages/gdscript-godot.md +470 -470
  198. package/languages/ruby-rails.md +489 -489
  199. package/languages/typescript-angular.md +433 -433
  200. package/languages/typescript-astro.md +416 -416
  201. package/languages/typescript-electron.md +406 -406
  202. package/languages/typescript-nestjs.md +524 -524
  203. package/languages/typescript-svelte.md +407 -407
  204. package/languages/typescript-tauri.md +365 -365
  205. package/package.json +84 -84
  206. package/skills/brand-assets.md +141 -141
  207. package/skills/commerce-patterns.md +361 -361
  208. package/skills/context7-usage.md +102 -102
  209. package/skills/e2e-commerce.md +304 -304
  210. package/skills/frontend-design.md +92 -92
  211. package/skills/git-worktree.md +181 -181
  212. package/skills/parallel-research.md +77 -77
  213. package/skills/priority-todos.md +239 -239
  214. package/skills/seo-checklist.md +244 -244
  215. package/skills/tool-fallback.md +190 -190
  216. package/skills/vibe-capabilities.md +161 -161
  217. package/vibe/constitution.md +227 -227
  218. package/vibe/rules/core/communication-guide.md +98 -98
  219. package/vibe/rules/core/development-philosophy.md +52 -52
  220. package/vibe/rules/core/quick-start.md +102 -102
  221. package/vibe/rules/quality/bdd-contract-testing.md +393 -393
  222. package/vibe/rules/quality/checklist.md +276 -276
  223. package/vibe/rules/quality/testing-strategy.md +440 -440
  224. package/vibe/rules/standards/anti-patterns.md +541 -541
  225. package/vibe/rules/standards/code-structure.md +291 -291
  226. package/vibe/rules/standards/complexity-metrics.md +313 -313
  227. package/vibe/rules/standards/naming-conventions.md +198 -198
  228. package/vibe/setup.sh +31 -31
  229. package/vibe/templates/constitution-template.md +252 -252
  230. package/vibe/templates/contract-backend-template.md +526 -526
  231. package/vibe/templates/contract-frontend-template.md +599 -599
  232. package/vibe/templates/feature-template.md +96 -96
  233. package/vibe/templates/spec-template.md +221 -221
@@ -1,262 +1,262 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Multi-Line HUD Visualization
4
- * Tree-based status display with overflow handling
5
- */
6
-
7
- import fs from 'fs';
8
- import path from 'path';
9
- import os from 'os';
10
-
11
- // State file
12
- const STATE_DIR = path.join(os.homedir(), '.claude', '.vibe-hud');
13
- const STATE_FILE = path.join(STATE_DIR, 'state.json');
14
-
15
- // Tree characters
16
- const TREE = {
17
- branch: '├─',
18
- last: '└─',
19
- vertical: '│ ',
20
- space: ' ',
21
- };
22
-
23
- // ANSI colors
24
- const COLORS = {
25
- reset: '\x1b[0m',
26
- bold: '\x1b[1m',
27
- dim: '\x1b[2m',
28
- green: '\x1b[32m',
29
- yellow: '\x1b[33m',
30
- red: '\x1b[31m',
31
- blue: '\x1b[34m',
32
- cyan: '\x1b[36m',
33
- magenta: '\x1b[35m',
34
- };
35
-
36
- // Status icons
37
- const ICONS = {
38
- running: '🔄',
39
- success: '✅',
40
- error: '❌',
41
- warning: '⚠️',
42
- pending: '⏳',
43
- agent: '🤖',
44
- phase: '📍',
45
- context: '📊',
46
- task: '📋',
47
- };
48
-
49
- /**
50
- * Load current state
51
- */
52
- function loadState() {
53
- try {
54
- if (fs.existsSync(STATE_FILE)) {
55
- return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
56
- }
57
- } catch {
58
- // Ignore
59
- }
60
- return {
61
- mode: 'idle',
62
- feature: null,
63
- phase: { current: 0, total: 0, name: '' },
64
- agents: [],
65
- tasks: [],
66
- context: { used: 0, total: 200000 },
67
- };
68
- }
69
-
70
- /**
71
- * Create progress bar
72
- */
73
- function createProgressBar(current, total, width = 20) {
74
- const percentage = total > 0 ? current / total : 0;
75
- const filled = Math.round(percentage * width);
76
- const empty = width - filled;
77
- return `[${'█'.repeat(filled)}${'░'.repeat(empty)}]`;
78
- }
79
-
80
- /**
81
- * Format context health
82
- */
83
- function formatContextHealth(used, total) {
84
- const percentage = Math.round((used / total) * 100);
85
- let color = COLORS.green;
86
- let icon = ICONS.success;
87
-
88
- if (percentage >= 90) {
89
- color = COLORS.red;
90
- icon = ICONS.error;
91
- } else if (percentage >= 70) {
92
- color = COLORS.yellow;
93
- icon = ICONS.warning;
94
- }
95
-
96
- return `${color}${icon} ${percentage}%${COLORS.reset}`;
97
- }
98
-
99
- /**
100
- * Multi-line render with tree structure
101
- */
102
- function renderMultiLine(state, maxLines = 10) {
103
- const lines = [];
104
- const modeIcon = state.mode === 'ultrawork' ? '🚀' :
105
- state.mode === 'spec' ? '📝' :
106
- state.mode === 'review' ? '🔍' :
107
- state.mode === 'implementing' ? '🔨' : '💤';
108
-
109
- // Header line
110
- const header = `${modeIcon} ${COLORS.bold}VIBE${COLORS.reset} ${state.mode.toUpperCase()}`;
111
- lines.push(header);
112
-
113
- // Feature name
114
- if (state.feature) {
115
- lines.push(`${TREE.branch} Feature: ${COLORS.cyan}${state.feature}${COLORS.reset}`);
116
- }
117
-
118
- // Phase progress
119
- if (state.phase.total > 0) {
120
- const phaseBar = createProgressBar(state.phase.current, state.phase.total, 15);
121
- const phaseName = state.phase.name ? ` - ${state.phase.name}` : '';
122
- lines.push(`${TREE.branch} ${ICONS.phase} Phase ${state.phase.current}/${state.phase.total}${phaseName}`);
123
- lines.push(`${TREE.vertical} ${phaseBar}`);
124
- }
125
-
126
- // Active agents
127
- if (state.agents && state.agents.length > 0) {
128
- lines.push(`${TREE.branch} ${ICONS.agent} Agents (${state.agents.length})`);
129
- const displayAgents = state.agents.slice(0, 3);
130
- const remaining = state.agents.length - displayAgents.length;
131
-
132
- displayAgents.forEach((agent, i) => {
133
- const isLast = i === displayAgents.length - 1 && remaining === 0;
134
- const prefix = isLast ? TREE.last : TREE.branch;
135
- const modelColor = agent.model === 'opus' ? COLORS.magenta :
136
- agent.model === 'sonnet' ? COLORS.blue : COLORS.green;
137
- lines.push(`${TREE.vertical} ${prefix} ${agent.name} ${modelColor}(${agent.model})${COLORS.reset}`);
138
- });
139
-
140
- if (remaining > 0) {
141
- lines.push(`${TREE.vertical} ${TREE.last} +${remaining} more...`);
142
- }
143
- }
144
-
145
- // Active tasks
146
- if (state.tasks && state.tasks.length > 0) {
147
- lines.push(`${TREE.branch} ${ICONS.task} Tasks (${state.tasks.length})`);
148
- const displayTasks = state.tasks.slice(0, 3);
149
- const remaining = state.tasks.length - displayTasks.length;
150
-
151
- displayTasks.forEach((task, i) => {
152
- const isLast = i === displayTasks.length - 1 && remaining === 0;
153
- const prefix = isLast ? TREE.last : TREE.branch;
154
- const statusIcon = task.status === 'completed' ? ICONS.success :
155
- task.status === 'failed' ? ICONS.error :
156
- task.status === 'running' ? ICONS.running : ICONS.pending;
157
- lines.push(`${TREE.vertical} ${prefix} ${statusIcon} ${task.name}`);
158
- });
159
-
160
- if (remaining > 0) {
161
- lines.push(`${TREE.vertical} ${TREE.last} +${remaining} more...`);
162
- }
163
- }
164
-
165
- // Context usage
166
- const contextHealth = formatContextHealth(state.context.used, state.context.total);
167
- lines.push(`${TREE.last} ${ICONS.context} Context: ${contextHealth}`);
168
-
169
- // Truncate if too many lines
170
- if (lines.length > maxLines) {
171
- const truncated = lines.slice(0, maxLines - 1);
172
- truncated.push(`${COLORS.dim}... (${lines.length - maxLines + 1} more lines)${COLORS.reset}`);
173
- return truncated;
174
- }
175
-
176
- return lines;
177
- }
178
-
179
- /**
180
- * Render single-line summary
181
- */
182
- function renderSingleLine(state) {
183
- const modeIcon = state.mode === 'ultrawork' ? '🚀' :
184
- state.mode === 'spec' ? '📝' :
185
- state.mode === 'review' ? '🔍' :
186
- state.mode === 'implementing' ? '🔨' : '💤';
187
-
188
- const parts = [modeIcon, state.mode];
189
-
190
- if (state.feature) {
191
- parts.push(`[${state.feature}]`);
192
- }
193
-
194
- if (state.phase.total > 0) {
195
- parts.push(`P:${state.phase.current}/${state.phase.total}`);
196
- }
197
-
198
- if (state.agents && state.agents.length > 0) {
199
- parts.push(`A:${state.agents.length}`);
200
- }
201
-
202
- const contextPct = Math.round((state.context.used / state.context.total) * 100);
203
- parts.push(`C:${contextPct}%`);
204
-
205
- return parts.join(' ');
206
- }
207
-
208
- /**
209
- * Render compact view
210
- */
211
- function renderCompact(state) {
212
- const lines = [];
213
- const modeIcon = state.mode === 'ultrawork' ? '🚀' :
214
- state.mode === 'spec' ? '📝' :
215
- state.mode === 'review' ? '🔍' :
216
- state.mode === 'implementing' ? '🔨' : '💤';
217
-
218
- // Line 1: Mode + Feature
219
- let line1 = `${modeIcon} ${state.mode}`;
220
- if (state.feature) line1 += `: ${state.feature}`;
221
- lines.push(line1);
222
-
223
- // Line 2: Phase + Agents + Context
224
- const parts = [];
225
- if (state.phase.total > 0) {
226
- parts.push(`P:${state.phase.current}/${state.phase.total}`);
227
- }
228
- if (state.agents && state.agents.length > 0) {
229
- parts.push(`A:${state.agents.length}`);
230
- }
231
- const contextPct = Math.round((state.context.used / state.context.total) * 100);
232
- const contextColor = contextPct >= 90 ? COLORS.red :
233
- contextPct >= 70 ? COLORS.yellow : COLORS.green;
234
- parts.push(`${contextColor}C:${contextPct}%${COLORS.reset}`);
235
-
236
- lines.push(` ${parts.join(' | ')}`);
237
-
238
- return lines;
239
- }
240
-
241
- /**
242
- * CLI handler
243
- */
244
- const command = process.argv[2] || 'multi';
245
- const state = loadState();
246
-
247
- switch (command) {
248
- case 'single':
249
- console.log(renderSingleLine(state));
250
- break;
251
-
252
- case 'compact':
253
- console.log(renderCompact(state).join('\n'));
254
- break;
255
-
256
- case 'multi':
257
- case 'full':
258
- default:
259
- const maxLines = parseInt(process.argv[3], 10) || 10;
260
- console.log(renderMultiLine(state, maxLines).join('\n'));
261
- break;
262
- }
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Multi-Line HUD Visualization
4
+ * Tree-based status display with overflow handling
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+ import os from 'os';
10
+
11
+ // State file
12
+ const STATE_DIR = path.join(os.homedir(), '.claude', '.vibe-hud');
13
+ const STATE_FILE = path.join(STATE_DIR, 'state.json');
14
+
15
+ // Tree characters
16
+ const TREE = {
17
+ branch: '├─',
18
+ last: '└─',
19
+ vertical: '│ ',
20
+ space: ' ',
21
+ };
22
+
23
+ // ANSI colors
24
+ const COLORS = {
25
+ reset: '\x1b[0m',
26
+ bold: '\x1b[1m',
27
+ dim: '\x1b[2m',
28
+ green: '\x1b[32m',
29
+ yellow: '\x1b[33m',
30
+ red: '\x1b[31m',
31
+ blue: '\x1b[34m',
32
+ cyan: '\x1b[36m',
33
+ magenta: '\x1b[35m',
34
+ };
35
+
36
+ // Status icons
37
+ const ICONS = {
38
+ running: '🔄',
39
+ success: '✅',
40
+ error: '❌',
41
+ warning: '⚠️',
42
+ pending: '⏳',
43
+ agent: '🤖',
44
+ phase: '📍',
45
+ context: '📊',
46
+ task: '📋',
47
+ };
48
+
49
+ /**
50
+ * Load current state
51
+ */
52
+ function loadState() {
53
+ try {
54
+ if (fs.existsSync(STATE_FILE)) {
55
+ return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
56
+ }
57
+ } catch {
58
+ // Ignore
59
+ }
60
+ return {
61
+ mode: 'idle',
62
+ feature: null,
63
+ phase: { current: 0, total: 0, name: '' },
64
+ agents: [],
65
+ tasks: [],
66
+ context: { used: 0, total: 200000 },
67
+ };
68
+ }
69
+
70
+ /**
71
+ * Create progress bar
72
+ */
73
+ function createProgressBar(current, total, width = 20) {
74
+ const percentage = total > 0 ? current / total : 0;
75
+ const filled = Math.round(percentage * width);
76
+ const empty = width - filled;
77
+ return `[${'█'.repeat(filled)}${'░'.repeat(empty)}]`;
78
+ }
79
+
80
+ /**
81
+ * Format context health
82
+ */
83
+ function formatContextHealth(used, total) {
84
+ const percentage = Math.round((used / total) * 100);
85
+ let color = COLORS.green;
86
+ let icon = ICONS.success;
87
+
88
+ if (percentage >= 90) {
89
+ color = COLORS.red;
90
+ icon = ICONS.error;
91
+ } else if (percentage >= 70) {
92
+ color = COLORS.yellow;
93
+ icon = ICONS.warning;
94
+ }
95
+
96
+ return `${color}${icon} ${percentage}%${COLORS.reset}`;
97
+ }
98
+
99
+ /**
100
+ * Multi-line render with tree structure
101
+ */
102
+ function renderMultiLine(state, maxLines = 10) {
103
+ const lines = [];
104
+ const modeIcon = state.mode === 'ultrawork' ? '🚀' :
105
+ state.mode === 'spec' ? '📝' :
106
+ state.mode === 'review' ? '🔍' :
107
+ state.mode === 'implementing' ? '🔨' : '💤';
108
+
109
+ // Header line
110
+ const header = `${modeIcon} ${COLORS.bold}VIBE${COLORS.reset} ${state.mode.toUpperCase()}`;
111
+ lines.push(header);
112
+
113
+ // Feature name
114
+ if (state.feature) {
115
+ lines.push(`${TREE.branch} Feature: ${COLORS.cyan}${state.feature}${COLORS.reset}`);
116
+ }
117
+
118
+ // Phase progress
119
+ if (state.phase.total > 0) {
120
+ const phaseBar = createProgressBar(state.phase.current, state.phase.total, 15);
121
+ const phaseName = state.phase.name ? ` - ${state.phase.name}` : '';
122
+ lines.push(`${TREE.branch} ${ICONS.phase} Phase ${state.phase.current}/${state.phase.total}${phaseName}`);
123
+ lines.push(`${TREE.vertical} ${phaseBar}`);
124
+ }
125
+
126
+ // Active agents
127
+ if (state.agents && state.agents.length > 0) {
128
+ lines.push(`${TREE.branch} ${ICONS.agent} Agents (${state.agents.length})`);
129
+ const displayAgents = state.agents.slice(0, 3);
130
+ const remaining = state.agents.length - displayAgents.length;
131
+
132
+ displayAgents.forEach((agent, i) => {
133
+ const isLast = i === displayAgents.length - 1 && remaining === 0;
134
+ const prefix = isLast ? TREE.last : TREE.branch;
135
+ const modelColor = agent.model === 'opus' ? COLORS.magenta :
136
+ agent.model === 'sonnet' ? COLORS.blue : COLORS.green;
137
+ lines.push(`${TREE.vertical} ${prefix} ${agent.name} ${modelColor}(${agent.model})${COLORS.reset}`);
138
+ });
139
+
140
+ if (remaining > 0) {
141
+ lines.push(`${TREE.vertical} ${TREE.last} +${remaining} more...`);
142
+ }
143
+ }
144
+
145
+ // Active tasks
146
+ if (state.tasks && state.tasks.length > 0) {
147
+ lines.push(`${TREE.branch} ${ICONS.task} Tasks (${state.tasks.length})`);
148
+ const displayTasks = state.tasks.slice(0, 3);
149
+ const remaining = state.tasks.length - displayTasks.length;
150
+
151
+ displayTasks.forEach((task, i) => {
152
+ const isLast = i === displayTasks.length - 1 && remaining === 0;
153
+ const prefix = isLast ? TREE.last : TREE.branch;
154
+ const statusIcon = task.status === 'completed' ? ICONS.success :
155
+ task.status === 'failed' ? ICONS.error :
156
+ task.status === 'running' ? ICONS.running : ICONS.pending;
157
+ lines.push(`${TREE.vertical} ${prefix} ${statusIcon} ${task.name}`);
158
+ });
159
+
160
+ if (remaining > 0) {
161
+ lines.push(`${TREE.vertical} ${TREE.last} +${remaining} more...`);
162
+ }
163
+ }
164
+
165
+ // Context usage
166
+ const contextHealth = formatContextHealth(state.context.used, state.context.total);
167
+ lines.push(`${TREE.last} ${ICONS.context} Context: ${contextHealth}`);
168
+
169
+ // Truncate if too many lines
170
+ if (lines.length > maxLines) {
171
+ const truncated = lines.slice(0, maxLines - 1);
172
+ truncated.push(`${COLORS.dim}... (${lines.length - maxLines + 1} more lines)${COLORS.reset}`);
173
+ return truncated;
174
+ }
175
+
176
+ return lines;
177
+ }
178
+
179
+ /**
180
+ * Render single-line summary
181
+ */
182
+ function renderSingleLine(state) {
183
+ const modeIcon = state.mode === 'ultrawork' ? '🚀' :
184
+ state.mode === 'spec' ? '📝' :
185
+ state.mode === 'review' ? '🔍' :
186
+ state.mode === 'implementing' ? '🔨' : '💤';
187
+
188
+ const parts = [modeIcon, state.mode];
189
+
190
+ if (state.feature) {
191
+ parts.push(`[${state.feature}]`);
192
+ }
193
+
194
+ if (state.phase.total > 0) {
195
+ parts.push(`P:${state.phase.current}/${state.phase.total}`);
196
+ }
197
+
198
+ if (state.agents && state.agents.length > 0) {
199
+ parts.push(`A:${state.agents.length}`);
200
+ }
201
+
202
+ const contextPct = Math.round((state.context.used / state.context.total) * 100);
203
+ parts.push(`C:${contextPct}%`);
204
+
205
+ return parts.join(' ');
206
+ }
207
+
208
+ /**
209
+ * Render compact view
210
+ */
211
+ function renderCompact(state) {
212
+ const lines = [];
213
+ const modeIcon = state.mode === 'ultrawork' ? '🚀' :
214
+ state.mode === 'spec' ? '📝' :
215
+ state.mode === 'review' ? '🔍' :
216
+ state.mode === 'implementing' ? '🔨' : '💤';
217
+
218
+ // Line 1: Mode + Feature
219
+ let line1 = `${modeIcon} ${state.mode}`;
220
+ if (state.feature) line1 += `: ${state.feature}`;
221
+ lines.push(line1);
222
+
223
+ // Line 2: Phase + Agents + Context
224
+ const parts = [];
225
+ if (state.phase.total > 0) {
226
+ parts.push(`P:${state.phase.current}/${state.phase.total}`);
227
+ }
228
+ if (state.agents && state.agents.length > 0) {
229
+ parts.push(`A:${state.agents.length}`);
230
+ }
231
+ const contextPct = Math.round((state.context.used / state.context.total) * 100);
232
+ const contextColor = contextPct >= 90 ? COLORS.red :
233
+ contextPct >= 70 ? COLORS.yellow : COLORS.green;
234
+ parts.push(`${contextColor}C:${contextPct}%${COLORS.reset}`);
235
+
236
+ lines.push(` ${parts.join(' | ')}`);
237
+
238
+ return lines;
239
+ }
240
+
241
+ /**
242
+ * CLI handler
243
+ */
244
+ const command = process.argv[2] || 'multi';
245
+ const state = loadState();
246
+
247
+ switch (command) {
248
+ case 'single':
249
+ console.log(renderSingleLine(state));
250
+ break;
251
+
252
+ case 'compact':
253
+ console.log(renderCompact(state).join('\n'));
254
+ break;
255
+
256
+ case 'multi':
257
+ case 'full':
258
+ default:
259
+ const maxLines = parseInt(process.argv[3], 10) || 10;
260
+ console.log(renderMultiLine(state, maxLines).join('\n'));
261
+ break;
262
+ }