devflow-kit 1.7.0 → 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (197) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +31 -1
  3. package/dist/cli.js +3 -1
  4. package/dist/commands/hud.d.ts +22 -0
  5. package/dist/commands/hud.js +180 -0
  6. package/dist/commands/init.d.ts +2 -12
  7. package/dist/commands/init.js +362 -181
  8. package/dist/commands/list.js +1 -0
  9. package/dist/commands/uninstall.js +9 -16
  10. package/dist/hud/cache.d.ts +14 -0
  11. package/dist/hud/cache.js +54 -0
  12. package/dist/hud/colors.d.ts +23 -0
  13. package/dist/hud/colors.js +62 -0
  14. package/dist/hud/components/config-counts.d.ts +8 -0
  15. package/dist/hud/components/config-counts.js +91 -0
  16. package/dist/hud/components/context-usage.d.ts +8 -0
  17. package/dist/hud/components/context-usage.js +49 -0
  18. package/dist/hud/components/diff-stats.d.ts +3 -0
  19. package/dist/hud/components/diff-stats.js +36 -0
  20. package/dist/hud/components/directory.d.ts +3 -0
  21. package/dist/hud/components/directory.js +10 -0
  22. package/dist/hud/components/git-ahead-behind.d.ts +3 -0
  23. package/dist/hud/components/git-ahead-behind.js +16 -0
  24. package/dist/hud/components/git-branch.d.ts +3 -0
  25. package/dist/hud/components/git-branch.js +14 -0
  26. package/dist/hud/components/model.d.ts +3 -0
  27. package/dist/hud/components/model.js +21 -0
  28. package/dist/hud/components/release-info.d.ts +3 -0
  29. package/dist/hud/components/release-info.js +9 -0
  30. package/dist/hud/components/session-cost.d.ts +3 -0
  31. package/dist/hud/components/session-cost.js +9 -0
  32. package/dist/hud/components/session-duration.d.ts +3 -0
  33. package/dist/hud/components/session-duration.js +18 -0
  34. package/dist/hud/components/todo-progress.d.ts +3 -0
  35. package/dist/hud/components/todo-progress.js +11 -0
  36. package/dist/hud/components/usage-quota.d.ts +3 -0
  37. package/dist/hud/components/usage-quota.js +45 -0
  38. package/dist/hud/components/version-badge.d.ts +3 -0
  39. package/dist/hud/components/version-badge.js +80 -0
  40. package/dist/hud/components/worktree-count.d.ts +3 -0
  41. package/dist/hud/components/worktree-count.js +8 -0
  42. package/dist/hud/config.d.ts +10 -0
  43. package/dist/hud/config.js +55 -0
  44. package/dist/hud/credentials.d.ts +17 -0
  45. package/dist/hud/credentials.js +99 -0
  46. package/dist/hud/git.d.ts +7 -0
  47. package/dist/hud/git.js +153 -0
  48. package/dist/hud/index.d.ts +2 -0
  49. package/dist/hud/index.js +81 -0
  50. package/dist/hud/render.d.ts +7 -0
  51. package/dist/hud/render.js +111 -0
  52. package/dist/hud/stdin.d.ts +6 -0
  53. package/dist/hud/stdin.js +25 -0
  54. package/dist/hud/transcript.d.ts +7 -0
  55. package/dist/hud/transcript.js +130 -0
  56. package/dist/hud/types.d.ts +116 -0
  57. package/dist/hud/types.js +2 -0
  58. package/dist/hud/usage-api.d.ts +7 -0
  59. package/dist/hud/usage-api.js +84 -0
  60. package/dist/utils/manifest.d.ts +1 -0
  61. package/dist/utils/post-install.d.ts +8 -1
  62. package/dist/utils/post-install.js +41 -0
  63. package/package.json +5 -2
  64. package/plugins/devflow-accessibility/.claude-plugin/plugin.json +1 -1
  65. package/plugins/devflow-ambient/.claude-plugin/plugin.json +1 -1
  66. package/plugins/devflow-ambient/agents/scrutinizer.md +6 -4
  67. package/plugins/devflow-ambient/agents/shepherd.md +26 -12
  68. package/plugins/devflow-ambient/agents/simplifier.md +24 -15
  69. package/plugins/devflow-audit-claude/.claude-plugin/plugin.json +1 -1
  70. package/plugins/devflow-code-review/.claude-plugin/plugin.json +1 -1
  71. package/plugins/devflow-core-skills/.claude-plugin/plugin.json +1 -1
  72. package/plugins/devflow-debug/.claude-plugin/plugin.json +1 -1
  73. package/plugins/devflow-frontend-design/.claude-plugin/plugin.json +1 -1
  74. package/plugins/devflow-go/.claude-plugin/plugin.json +1 -1
  75. package/plugins/devflow-implement/.claude-plugin/plugin.json +1 -1
  76. package/plugins/devflow-implement/agents/scrutinizer.md +6 -4
  77. package/plugins/devflow-implement/agents/shepherd.md +26 -12
  78. package/plugins/devflow-implement/agents/simplifier.md +24 -15
  79. package/plugins/devflow-implement/skills/self-review/references/stub-detection.md +135 -0
  80. package/plugins/devflow-java/.claude-plugin/plugin.json +1 -1
  81. package/plugins/devflow-python/.claude-plugin/plugin.json +1 -1
  82. package/plugins/devflow-react/.claude-plugin/plugin.json +1 -1
  83. package/plugins/devflow-resolve/.claude-plugin/plugin.json +1 -1
  84. package/plugins/devflow-resolve/agents/simplifier.md +24 -15
  85. package/plugins/devflow-rust/.claude-plugin/plugin.json +1 -1
  86. package/plugins/devflow-self-review/.claude-plugin/plugin.json +1 -1
  87. package/plugins/devflow-self-review/agents/scrutinizer.md +6 -4
  88. package/plugins/devflow-self-review/agents/simplifier.md +24 -15
  89. package/plugins/devflow-self-review/skills/self-review/references/stub-detection.md +135 -0
  90. package/plugins/devflow-specify/.claude-plugin/plugin.json +1 -1
  91. package/plugins/devflow-typescript/.claude-plugin/plugin.json +1 -1
  92. package/scripts/hud/cache.d.ts +14 -0
  93. package/scripts/hud/cache.d.ts.map +1 -0
  94. package/scripts/hud/cache.js +54 -0
  95. package/scripts/hud/cache.js.map +1 -0
  96. package/scripts/hud/colors.d.ts +23 -0
  97. package/scripts/hud/colors.d.ts.map +1 -0
  98. package/scripts/hud/colors.js +62 -0
  99. package/scripts/hud/colors.js.map +1 -0
  100. package/scripts/hud/components/config-counts.d.ts +8 -0
  101. package/scripts/hud/components/config-counts.d.ts.map +1 -0
  102. package/scripts/hud/components/config-counts.js +91 -0
  103. package/scripts/hud/components/config-counts.js.map +1 -0
  104. package/scripts/hud/components/context-usage.d.ts +8 -0
  105. package/scripts/hud/components/context-usage.d.ts.map +1 -0
  106. package/scripts/hud/components/context-usage.js +49 -0
  107. package/scripts/hud/components/context-usage.js.map +1 -0
  108. package/scripts/hud/components/diff-stats.d.ts +3 -0
  109. package/scripts/hud/components/diff-stats.d.ts.map +1 -0
  110. package/scripts/hud/components/diff-stats.js +36 -0
  111. package/scripts/hud/components/diff-stats.js.map +1 -0
  112. package/scripts/hud/components/directory.d.ts +3 -0
  113. package/scripts/hud/components/directory.d.ts.map +1 -0
  114. package/scripts/hud/components/directory.js +10 -0
  115. package/scripts/hud/components/directory.js.map +1 -0
  116. package/scripts/hud/components/git-ahead-behind.d.ts +3 -0
  117. package/scripts/hud/components/git-ahead-behind.d.ts.map +1 -0
  118. package/scripts/hud/components/git-ahead-behind.js +16 -0
  119. package/scripts/hud/components/git-ahead-behind.js.map +1 -0
  120. package/scripts/hud/components/git-branch.d.ts +3 -0
  121. package/scripts/hud/components/git-branch.d.ts.map +1 -0
  122. package/scripts/hud/components/git-branch.js +14 -0
  123. package/scripts/hud/components/git-branch.js.map +1 -0
  124. package/scripts/hud/components/model.d.ts +3 -0
  125. package/scripts/hud/components/model.d.ts.map +1 -0
  126. package/scripts/hud/components/model.js +21 -0
  127. package/scripts/hud/components/model.js.map +1 -0
  128. package/scripts/hud/components/release-info.d.ts +3 -0
  129. package/scripts/hud/components/release-info.d.ts.map +1 -0
  130. package/scripts/hud/components/release-info.js +9 -0
  131. package/scripts/hud/components/release-info.js.map +1 -0
  132. package/scripts/hud/components/session-cost.d.ts +3 -0
  133. package/scripts/hud/components/session-cost.d.ts.map +1 -0
  134. package/scripts/hud/components/session-cost.js +9 -0
  135. package/scripts/hud/components/session-cost.js.map +1 -0
  136. package/scripts/hud/components/session-duration.d.ts +3 -0
  137. package/scripts/hud/components/session-duration.d.ts.map +1 -0
  138. package/scripts/hud/components/session-duration.js +18 -0
  139. package/scripts/hud/components/session-duration.js.map +1 -0
  140. package/scripts/hud/components/todo-progress.d.ts +3 -0
  141. package/scripts/hud/components/todo-progress.d.ts.map +1 -0
  142. package/scripts/hud/components/todo-progress.js +11 -0
  143. package/scripts/hud/components/todo-progress.js.map +1 -0
  144. package/scripts/hud/components/usage-quota.d.ts +3 -0
  145. package/scripts/hud/components/usage-quota.d.ts.map +1 -0
  146. package/scripts/hud/components/usage-quota.js +45 -0
  147. package/scripts/hud/components/usage-quota.js.map +1 -0
  148. package/scripts/hud/components/version-badge.d.ts +3 -0
  149. package/scripts/hud/components/version-badge.d.ts.map +1 -0
  150. package/scripts/hud/components/version-badge.js +80 -0
  151. package/scripts/hud/components/version-badge.js.map +1 -0
  152. package/scripts/hud/components/worktree-count.d.ts +3 -0
  153. package/scripts/hud/components/worktree-count.d.ts.map +1 -0
  154. package/scripts/hud/components/worktree-count.js +8 -0
  155. package/scripts/hud/components/worktree-count.js.map +1 -0
  156. package/scripts/hud/config.d.ts +10 -0
  157. package/scripts/hud/config.d.ts.map +1 -0
  158. package/scripts/hud/config.js +55 -0
  159. package/scripts/hud/config.js.map +1 -0
  160. package/scripts/hud/credentials.d.ts +17 -0
  161. package/scripts/hud/credentials.d.ts.map +1 -0
  162. package/scripts/hud/credentials.js +99 -0
  163. package/scripts/hud/credentials.js.map +1 -0
  164. package/scripts/hud/git.d.ts +7 -0
  165. package/scripts/hud/git.d.ts.map +1 -0
  166. package/scripts/hud/git.js +153 -0
  167. package/scripts/hud/git.js.map +1 -0
  168. package/scripts/hud/index.d.ts +2 -0
  169. package/scripts/hud/index.d.ts.map +1 -0
  170. package/scripts/hud/index.js +81 -0
  171. package/scripts/hud/index.js.map +1 -0
  172. package/scripts/hud/render.d.ts +7 -0
  173. package/scripts/hud/render.d.ts.map +1 -0
  174. package/scripts/hud/render.js +111 -0
  175. package/scripts/hud/render.js.map +1 -0
  176. package/scripts/hud/stdin.d.ts +6 -0
  177. package/scripts/hud/stdin.d.ts.map +1 -0
  178. package/scripts/hud/stdin.js +25 -0
  179. package/scripts/hud/stdin.js.map +1 -0
  180. package/scripts/hud/transcript.d.ts +7 -0
  181. package/scripts/hud/transcript.d.ts.map +1 -0
  182. package/scripts/hud/transcript.js +130 -0
  183. package/scripts/hud/transcript.js.map +1 -0
  184. package/scripts/hud/types.d.ts +116 -0
  185. package/scripts/hud/types.d.ts.map +1 -0
  186. package/scripts/hud/types.js +2 -0
  187. package/scripts/hud/types.js.map +1 -0
  188. package/scripts/hud/usage-api.d.ts +7 -0
  189. package/scripts/hud/usage-api.d.ts.map +1 -0
  190. package/scripts/hud/usage-api.js +84 -0
  191. package/scripts/hud/usage-api.js.map +1 -0
  192. package/scripts/hud.sh +5 -0
  193. package/shared/agents/scrutinizer.md +6 -4
  194. package/shared/agents/shepherd.md +26 -12
  195. package/shared/agents/simplifier.md +24 -15
  196. package/shared/skills/self-review/references/stub-detection.md +135 -0
  197. package/src/templates/settings.json +1 -1
@@ -0,0 +1,7 @@
1
+ import type { TranscriptData } from './types.js';
2
+ /**
3
+ * Parse a Claude Code session transcript (JSONL) to extract tool/agent activity and todo progress.
4
+ * Returns null if the file doesn't exist or can't be parsed.
5
+ */
6
+ export declare function parseTranscript(transcriptPath: string): Promise<TranscriptData | null>;
7
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1,130 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as readline from 'node:readline';
4
+ // Precompiled patterns
5
+ const TODO_WRITE_NAME = /^TodoWrite$/i;
6
+ /**
7
+ * Parse a Claude Code session transcript (JSONL) to extract tool/agent activity and todo progress.
8
+ * Returns null if the file doesn't exist or can't be parsed.
9
+ */
10
+ export async function parseTranscript(transcriptPath) {
11
+ try {
12
+ if (!fs.existsSync(transcriptPath))
13
+ return null;
14
+ const tools = new Map();
15
+ const agents = new Map();
16
+ const skills = new Set();
17
+ let todosCompleted = 0;
18
+ let todosTotal = 0;
19
+ const stream = fs.createReadStream(transcriptPath, { encoding: 'utf-8' });
20
+ const rl = readline.createInterface({
21
+ input: stream,
22
+ crlfDelay: Infinity,
23
+ });
24
+ for await (const line of rl) {
25
+ if (!line.trim())
26
+ continue;
27
+ try {
28
+ const entry = JSON.parse(line);
29
+ // Turn boundary: clear tools and agents on each human message
30
+ // so only the current turn's activity shows in the HUD
31
+ if (entry.type === 'human') {
32
+ tools.clear();
33
+ agents.clear();
34
+ continue;
35
+ }
36
+ const todoResult = processEntry(entry, tools, agents, skills);
37
+ if (todoResult) {
38
+ todosCompleted = todoResult.completed;
39
+ todosTotal = todoResult.total;
40
+ }
41
+ }
42
+ catch {
43
+ // Skip malformed lines
44
+ }
45
+ }
46
+ return {
47
+ tools: Array.from(tools.values()),
48
+ agents: Array.from(agents.values()),
49
+ todos: { completed: todosCompleted, total: todosTotal },
50
+ skills: Array.from(skills),
51
+ };
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ function processEntry(entry, tools, agents, skills) {
58
+ if (entry.type !== 'assistant' || !entry.message)
59
+ return null;
60
+ const message = entry.message;
61
+ if (!Array.isArray(message.content))
62
+ return null;
63
+ let todoResult = null;
64
+ for (const block of message.content) {
65
+ const blockType = block.type;
66
+ if (blockType === 'tool_use') {
67
+ const name = block.name;
68
+ const id = block.id;
69
+ if (name === 'Agent' || name === 'Task') {
70
+ // Agent spawn
71
+ const input = block.input;
72
+ const agentType = input?.subagent_type || 'Agent';
73
+ const agentDesc = typeof input?.description === 'string' ? input.description : undefined;
74
+ agents.set(id, {
75
+ name: agentType,
76
+ model: input?.model,
77
+ status: 'running',
78
+ description: agentDesc,
79
+ });
80
+ }
81
+ else if (name === 'Skill') {
82
+ // Track loaded skills
83
+ const input = block.input;
84
+ if (input?.skill && typeof input.skill === 'string') {
85
+ skills.add(input.skill);
86
+ }
87
+ }
88
+ else if (TODO_WRITE_NAME.test(name)) {
89
+ // Track todos
90
+ const input = block.input;
91
+ const todos = input?.todos;
92
+ if (Array.isArray(todos)) {
93
+ const total = todos.length;
94
+ const completed = todos.filter((t) => t.status === 'completed').length;
95
+ todoResult = { completed, total };
96
+ }
97
+ }
98
+ else {
99
+ // Regular tool — extract file target for Read/Edit/Write
100
+ const input = block.input;
101
+ let target;
102
+ if (input?.file_path && typeof input.file_path === 'string') {
103
+ target = path.basename(input.file_path);
104
+ }
105
+ // Extract description: prefer input.description, fallback to first 4 words of command (Bash)
106
+ let description;
107
+ if (typeof input?.description === 'string') {
108
+ description = input.description;
109
+ }
110
+ else if (name === 'Bash' && typeof input?.command === 'string') {
111
+ description = input.command.split(/\s+/).slice(0, 4).join(' ');
112
+ }
113
+ tools.set(id, { name, status: 'running', target, description });
114
+ }
115
+ }
116
+ else if (blockType === 'tool_result') {
117
+ const toolUseId = block.tool_use_id;
118
+ const toolEntry = tools.get(toolUseId);
119
+ if (toolEntry) {
120
+ toolEntry.status = 'completed';
121
+ }
122
+ const agentEntry = agents.get(toolUseId);
123
+ if (agentEntry) {
124
+ agentEntry.status = 'completed';
125
+ }
126
+ }
127
+ }
128
+ return todoResult;
129
+ }
130
+ //# sourceMappingURL=transcript.js.map
@@ -0,0 +1,116 @@
1
+ /**
2
+ * StdinData — the JSON that Claude Code pipes to statusLine commands.
3
+ */
4
+ export interface StdinData {
5
+ model?: {
6
+ display_name?: string;
7
+ id?: string;
8
+ };
9
+ cwd?: string;
10
+ context_window?: {
11
+ context_window_size?: number;
12
+ current_usage?: {
13
+ input_tokens?: number;
14
+ output_tokens?: number;
15
+ };
16
+ used_percentage?: number;
17
+ };
18
+ cost?: {
19
+ total_cost_usd?: number;
20
+ };
21
+ session_id?: string;
22
+ transcript_path?: string;
23
+ }
24
+ /**
25
+ * Component IDs — the 14 HUD components.
26
+ */
27
+ export type ComponentId = 'directory' | 'gitBranch' | 'gitAheadBehind' | 'diffStats' | 'model' | 'contextUsage' | 'versionBadge' | 'sessionDuration' | 'usageQuota' | 'todoProgress' | 'configCounts' | 'sessionCost' | 'releaseInfo' | 'worktreeCount';
28
+ /**
29
+ * HUD config persisted to ~/.devflow/hud.json.
30
+ */
31
+ export interface HudConfig {
32
+ enabled: boolean;
33
+ detail: boolean;
34
+ }
35
+ /**
36
+ * Component render result.
37
+ */
38
+ export interface ComponentResult {
39
+ text: string;
40
+ raw: string;
41
+ }
42
+ /**
43
+ * Component function signature.
44
+ */
45
+ export type ComponentFn = (ctx: GatherContext) => Promise<ComponentResult | null>;
46
+ /**
47
+ * Git status data gathered from the working directory.
48
+ */
49
+ export interface GitStatus {
50
+ branch: string;
51
+ dirty: boolean;
52
+ staged: boolean;
53
+ ahead: number;
54
+ behind: number;
55
+ filesChanged: number;
56
+ additions: number;
57
+ deletions: number;
58
+ lastTag: string | null;
59
+ commitsSinceTag: number;
60
+ worktreeCount: number;
61
+ }
62
+ /**
63
+ * Transcript data parsed from session JSONL.
64
+ */
65
+ export interface TranscriptData {
66
+ tools: Array<{
67
+ name: string;
68
+ status: 'running' | 'completed';
69
+ target?: string;
70
+ description?: string;
71
+ }>;
72
+ agents: Array<{
73
+ name: string;
74
+ model?: string;
75
+ status: 'running' | 'completed';
76
+ description?: string;
77
+ }>;
78
+ todos: {
79
+ completed: number;
80
+ total: number;
81
+ };
82
+ skills: string[];
83
+ }
84
+ /**
85
+ * Usage API data.
86
+ */
87
+ export interface UsageData {
88
+ fiveHourPercent: number | null;
89
+ sevenDayPercent: number | null;
90
+ }
91
+ /**
92
+ * Config counts data for the configCounts component.
93
+ */
94
+ export interface ConfigCountsData {
95
+ claudeMdFiles: number;
96
+ rules: number;
97
+ mcpServers: number;
98
+ hooks: number;
99
+ }
100
+ /**
101
+ * Gather context passed to all component render functions.
102
+ */
103
+ export interface GatherContext {
104
+ stdin: StdinData;
105
+ git: GitStatus | null;
106
+ transcript: TranscriptData | null;
107
+ usage: UsageData | null;
108
+ configCounts: ConfigCountsData | null;
109
+ config: HudConfig & {
110
+ components: ComponentId[];
111
+ };
112
+ devflowDir: string;
113
+ sessionStartTime: number | null;
114
+ terminalWidth: number;
115
+ }
116
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,7 @@
1
+ import type { UsageData } from './types.js';
2
+ /**
3
+ * Fetch usage quota data from the Anthropic API.
4
+ * Uses caching with backoff for rate limiting. Returns null on failure.
5
+ */
6
+ export declare function fetchUsageData(): Promise<UsageData | null>;
7
+ //# sourceMappingURL=usage-api.d.ts.map
@@ -0,0 +1,84 @@
1
+ import * as fs from 'node:fs';
2
+ import { readCache, writeCache, readCacheStale } from './cache.js';
3
+ import { getCredentials } from './credentials.js';
4
+ const USAGE_CACHE_KEY = 'usage';
5
+ const USAGE_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
6
+ const USAGE_FAIL_TTL = 15 * 1000; // 15 seconds
7
+ const API_TIMEOUT = 1_500; // Must fit within 2s overall HUD timeout
8
+ const BACKOFF_CACHE_KEY = 'usage-backoff';
9
+ const DEBUG = !!process.env.DEVFLOW_HUD_DEBUG;
10
+ function debugLog(msg, data) {
11
+ if (!DEBUG)
12
+ return;
13
+ const entry = { ts: new Date().toISOString(), source: 'usage-api', msg, ...data };
14
+ fs.appendFileSync('/tmp/hud-debug.log', JSON.stringify(entry) + '\n');
15
+ }
16
+ /**
17
+ * Fetch usage quota data from the Anthropic API.
18
+ * Uses caching with backoff for rate limiting. Returns null on failure.
19
+ */
20
+ export async function fetchUsageData() {
21
+ // Check backoff
22
+ const backoff = readCache(BACKOFF_CACHE_KEY);
23
+ if (backoff && Date.now() < backoff.retryAfter) {
24
+ debugLog('skipped: backoff active', { retryAfter: backoff.retryAfter });
25
+ return readCacheStale(USAGE_CACHE_KEY);
26
+ }
27
+ // Check cache
28
+ const cached = readCache(USAGE_CACHE_KEY);
29
+ if (cached)
30
+ return cached;
31
+ const creds = await getCredentials();
32
+ if (!creds) {
33
+ debugLog('no OAuth credentials found');
34
+ return null;
35
+ }
36
+ const token = creds.accessToken;
37
+ try {
38
+ const controller = new AbortController();
39
+ const timeout = setTimeout(() => controller.abort(), API_TIMEOUT);
40
+ debugLog('fetching usage', { timeout: API_TIMEOUT });
41
+ const response = await fetch('https://api.anthropic.com/api/oauth/usage', {
42
+ headers: {
43
+ Authorization: `Bearer ${token}`,
44
+ 'Content-Type': 'application/json',
45
+ 'anthropic-beta': 'oauth-2025-04-20',
46
+ },
47
+ signal: controller.signal,
48
+ });
49
+ clearTimeout(timeout);
50
+ if (response.status === 429) {
51
+ const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);
52
+ const delay = Math.min(retryAfter * 1000, 5 * 60 * 1000);
53
+ writeCache(BACKOFF_CACHE_KEY, { retryAfter: Date.now() + delay, delay }, delay);
54
+ debugLog('rate limited (429)', { retryAfter, delay });
55
+ return readCacheStale(USAGE_CACHE_KEY);
56
+ }
57
+ if (!response.ok) {
58
+ debugLog('non-200 response', { status: response.status, statusText: response.statusText });
59
+ writeCache(USAGE_CACHE_KEY, null, USAGE_FAIL_TTL);
60
+ return readCacheStale(USAGE_CACHE_KEY);
61
+ }
62
+ const body = (await response.json());
63
+ const fiveHour = body.five_hour;
64
+ const sevenDay = body.seven_day;
65
+ const data = {
66
+ fiveHourPercent: typeof fiveHour?.utilization === 'number'
67
+ ? Math.round(Math.max(0, Math.min(100, fiveHour.utilization)))
68
+ : null,
69
+ sevenDayPercent: typeof sevenDay?.utilization === 'number'
70
+ ? Math.round(Math.max(0, Math.min(100, sevenDay.utilization)))
71
+ : null,
72
+ };
73
+ debugLog('usage fetched', { fiveHour: data.fiveHourPercent, sevenDay: data.sevenDayPercent });
74
+ writeCache(USAGE_CACHE_KEY, data, USAGE_CACHE_TTL);
75
+ return data;
76
+ }
77
+ catch (err) {
78
+ const message = err instanceof Error ? err.message : String(err);
79
+ debugLog('fetch failed', { error: message });
80
+ writeCache(USAGE_CACHE_KEY, null, USAGE_FAIL_TTL);
81
+ return readCacheStale(USAGE_CACHE_KEY);
82
+ }
83
+ }
84
+ //# sourceMappingURL=usage-api.js.map
@@ -9,6 +9,7 @@ export interface ManifestData {
9
9
  teams: boolean;
10
10
  ambient: boolean;
11
11
  memory: boolean;
12
+ hud?: boolean;
12
13
  };
13
14
  installedAt: string;
14
15
  updatedAt: string;
@@ -55,8 +55,15 @@ export type SecurityMode = 'managed' | 'user';
55
55
  export declare function installSettings(claudeDir: string, rootDir: string, devflowDir: string, verbose: boolean, teamsEnabled?: boolean, securityMode?: SecurityMode): Promise<void>;
56
56
  /**
57
57
  * Create .claudeignore in git repository root (skip if already exists).
58
+ * Returns true if a new file was created, false if it already existed or on error.
58
59
  */
59
- export declare function installClaudeignore(gitRoot: string, rootDir: string, verbose: boolean): Promise<void>;
60
+ export declare function installClaudeignore(gitRoot: string, rootDir: string, verbose: boolean): Promise<boolean>;
61
+ /**
62
+ * Discover git repository roots from Claude's project history.
63
+ * Parses ~/.claude/history.jsonl for unique project paths that are valid git repos.
64
+ * @param homeDir - Override home directory (dependency injection for tests)
65
+ */
66
+ export declare function discoverProjectGitRoots(homeDir?: string): Promise<string[]>;
60
67
  /**
61
68
  * Update .gitignore with DevFlow entries (for local scope installs).
62
69
  */
@@ -1,6 +1,7 @@
1
1
  import { promises as fs, writeFileSync, unlinkSync } from 'fs';
2
2
  import { execSync } from 'child_process';
3
3
  import * as path from 'path';
4
+ import * as os from 'os';
4
5
  import * as p from '@clack/prompts';
5
6
  import { getManagedSettingsPath } from './paths.js';
6
7
  function isNodeSystemError(error) {
@@ -353,6 +354,7 @@ export async function installSettings(claudeDir, rootDir, devflowDir, verbose, t
353
354
  }
354
355
  /**
355
356
  * Create .claudeignore in git repository root (skip if already exists).
357
+ * Returns true if a new file was created, false if it already existed or on error.
356
358
  */
357
359
  export async function installClaudeignore(gitRoot, rootDir, verbose) {
358
360
  const claudeignorePath = path.join(gitRoot, '.claudeignore');
@@ -363,6 +365,7 @@ export async function installClaudeignore(gitRoot, rootDir, verbose) {
363
365
  if (verbose) {
364
366
  p.log.success('.claudeignore created');
365
367
  }
368
+ return true;
366
369
  }
367
370
  catch (error) {
368
371
  if (isNodeSystemError(error) && error.code === 'EEXIST') {
@@ -371,7 +374,45 @@ export async function installClaudeignore(gitRoot, rootDir, verbose) {
371
374
  else if (verbose) {
372
375
  p.log.warn(`Could not create .claudeignore: ${error}`);
373
376
  }
377
+ return false;
378
+ }
379
+ }
380
+ /**
381
+ * Discover git repository roots from Claude's project history.
382
+ * Parses ~/.claude/history.jsonl for unique project paths that are valid git repos.
383
+ * @param homeDir - Override home directory (dependency injection for tests)
384
+ */
385
+ export async function discoverProjectGitRoots(homeDir) {
386
+ const historyPath = path.join(homeDir ?? os.homedir(), '.claude', 'history.jsonl');
387
+ let content;
388
+ try {
389
+ content = await fs.readFile(historyPath, 'utf-8');
390
+ }
391
+ catch {
392
+ return [];
393
+ }
394
+ const projects = new Set();
395
+ for (const line of content.split('\n')) {
396
+ if (!line.trim())
397
+ continue;
398
+ try {
399
+ const entry = JSON.parse(line);
400
+ if (typeof entry?.project === 'string') {
401
+ projects.add(path.resolve(entry.project));
402
+ }
403
+ }
404
+ catch {
405
+ // Malformed line — skip
406
+ }
374
407
  }
408
+ const results = await Promise.allSettled([...projects].map(async (project) => {
409
+ await fs.access(path.join(project, '.git'));
410
+ return project;
411
+ }));
412
+ const gitRoots = results
413
+ .filter((r) => r.status === 'fulfilled')
414
+ .map((r) => r.value);
415
+ return gitRoots.sort();
375
416
  }
376
417
  /**
377
418
  * Update .gitignore with DevFlow entries (for local scope installs).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devflow-kit",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "Agentic Development Toolkit for Claude Code - Enhance AI-assisted development with intelligent commands and workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -12,15 +12,18 @@
12
12
  "plugins/",
13
13
  "shared/",
14
14
  "scripts/hooks/",
15
+ "scripts/hud.sh",
16
+ "scripts/hud/",
15
17
  "src/templates/",
16
18
  "README.md",
17
19
  "LICENSE",
18
20
  "CHANGELOG.md"
19
21
  ],
20
22
  "scripts": {
21
- "build": "npm run build:cli && npm run build:plugins",
23
+ "build": "npm run build:cli && npm run build:plugins && npm run build:hud",
22
24
  "build:cli": "tsc",
23
25
  "build:plugins": "npx tsx scripts/build-plugins.ts",
26
+ "build:hud": "node scripts/build-hud.js",
24
27
  "dev": "tsc --watch",
25
28
  "cli": "node dist/cli.js",
26
29
  "prepublishOnly": "npm run build",
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.7.0",
7
+ "version": "1.8.1",
8
8
  "homepage": "https://github.com/dean0x/devflow",
9
9
  "repository": "https://github.com/dean0x/devflow",
10
10
  "license": "MIT",
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.7.0",
7
+ "version": "1.8.1",
8
8
  "homepage": "https://github.com/dean0x/devflow",
9
9
  "repository": "https://github.com/dean0x/devflow",
10
10
  "license": "MIT",
@@ -21,13 +21,15 @@ You receive from orchestrator:
21
21
 
22
22
  2. **Evaluate P0 pillars** (Design, Functionality, Security): These MUST pass. Fix all issues found.
23
23
 
24
- 3. **Evaluate P1 pillars** (Complexity, Error Handling, Tests): These SHOULD pass. Fix all issues found.
24
+ 3. **Detect stubs and wiring gaps**: Check for placeholder implementations that compile but don't deliver real functionality. See `references/stub-detection.md` for patterns. Flag as P0-Functionality issues.
25
25
 
26
- 4. **Evaluate P2 pillars** (Naming, Consistency, Documentation): Report as suggestions. Fix if straightforward.
26
+ 4. **Evaluate P1 pillars** (Complexity, Error Handling, Tests): These SHOULD pass. Fix all issues found.
27
27
 
28
- 5. **Commit fixes**: If any changes were made, create a commit with message "fix: address self-review issues".
28
+ 5. **Evaluate P2 pillars** (Naming, Consistency, Documentation): Report as suggestions. Fix if straightforward.
29
29
 
30
- 6. **Report status**: Return structured report with pillar evaluations and changes made.
30
+ 6. **Commit fixes**: If any changes were made, create a commit with message "fix: address self-review issues".
31
+
32
+ 7. **Report status**: Return structured report with pillar evaluations and changes made.
31
33
 
32
34
  ## Principles
33
35
 
@@ -21,9 +21,19 @@ You receive from orchestrator:
21
21
 
22
22
  1. **Understand intent**: Read ORIGINAL_REQUEST and EXECUTION_PLAN to understand what was requested
23
23
  2. **Review implementation**: Read FILES_CHANGED to understand what was built
24
- 3. **Check completeness**: Verify all plan steps implemented, all acceptance criteria met
25
- 4. **Check scope**: Identify out-of-scope additions not justified by design improvements
26
- 5. **Report misalignments**: Document issues with sufficient detail for Coder to fix
24
+ 3. **Goal-backward verification**: Start from the user's observable goals. For each goal: trace backward through the implementation — is it wired into the running app → does it contain substantive logic → does the file/function exist? Report any goal failing at any depth.
25
+ 4. **Check artifact depth**: Classify each deliverable using this scale:
26
+
27
+ | Depth | Meaning | Example |
28
+ |-------|---------|---------|
29
+ | Exists | File/function created | Route file exists |
30
+ | Substantive | Contains real logic | Route has validation + DB call |
31
+ | Wired | Connected to running app | Route registered, imported, reachable |
32
+
33
+ Flag anything at "Exists" without reaching "Wired" as `incomplete`.
34
+ 5. **Check completeness**: Verify all plan steps implemented, all acceptance criteria met
35
+ 6. **Check scope**: Identify out-of-scope additions not justified by design improvements
36
+ 7. **Report misalignments**: Document issues with sufficient detail for Coder to fix
27
37
 
28
38
  ## Principles
29
39
 
@@ -51,6 +61,11 @@ Return structured alignment status:
51
61
  - Implementation solves: {1-sentence summary}
52
62
  - Alignment: aligned | drifted
53
63
 
64
+ ### Artifact Depth
65
+ | Deliverable | Exists | Substantive | Wired | Status |
66
+ |-------------|--------|-------------|-------|--------|
67
+ | {feature} | Y/N | Y/N | Y/N | complete/incomplete/stub |
68
+
54
69
  ### Misalignments Found (if MISALIGNED)
55
70
 
56
71
  | Type | Description | Files | Suggested Fix |
@@ -59,20 +74,17 @@ Return structured alignment status:
59
74
  | scope_creep | {what's out of scope} | {file paths} | {remove or justify} |
60
75
  | incomplete | {what's partially done} | {file paths} | {what remains} |
61
76
  | intent_drift | {how intent drifted} | {file paths} | {how to realign} |
77
+ | stub | {placeholder, not real logic} | {file paths} | {what real implementation needs} |
62
78
 
63
79
  ### Scope Check
64
80
  - Out-of-scope additions: {list or "None"}
65
81
  - Justification: {if additions found, are they justified design improvements?}
66
- ```
67
-
68
- ## Misalignment Types
69
82
 
70
- | Type | Description | Example |
71
- |------|-------------|---------|
72
- | `missing` | Functionality in plan not implemented | "Login validation not implemented" |
73
- | `scope_creep` | Added functionality not in plan | "Analytics tracking added but not requested" |
74
- | `incomplete` | Partially implemented functionality | "Error handling added but no user-facing messages" |
75
- | `intent_drift` | Implementation solves different problem | "Built password reset instead of login flow" |
83
+ ### Re-verification (if applicable)
84
+ | Previously Failed | Status | Notes |
85
+ |-------------------|--------|-------|
86
+ | {item} | RESOLVED/STILL_FAILING | {details} |
87
+ ```
76
88
 
77
89
  ## Boundaries
78
90
 
@@ -81,12 +93,14 @@ Return structured alignment status:
81
93
  - Out-of-scope additions not justified by design
82
94
  - Partial implementations
83
95
  - Intent drift
96
+ - Stubs or placeholders passing as real implementations
84
97
 
85
98
  **Report as ALIGNED:**
86
99
  - All plan steps implemented
87
100
  - All acceptance criteria met
88
101
  - No unjustified scope additions
89
102
  - Implementation matches original intent
103
+ - All deliverables reach "Wired" depth
90
104
 
91
105
  **Never:**
92
106
  - Modify code or create commits
@@ -30,31 +30,39 @@ Analyze recently modified code and apply refinements that:
30
30
  - Use proper error handling patterns (avoid try/catch when possible)
31
31
  - Maintain consistent naming conventions
32
32
 
33
- 3. **Enhance Clarity**: Simplify code structure by:
34
-
35
- - Reducing unnecessary complexity and nesting
36
- - Eliminating redundant code and abstractions
37
- - Improving readability through clear variable and function names
33
+ 3. **Remove Slop**: Detect and remove these categories:
34
+
35
+ | Category | Pattern |
36
+ |----------|---------|
37
+ | Language-behavior tests | Tests verifying built-in language features work as documented |
38
+ | Redundant type checks | Runtime checks for types TypeScript already enforces |
39
+ | Over-defensive handling | try/catch around code that cannot throw |
40
+ | Debug remnants | console.log, debugger, alert() left behind |
41
+ | Commented-out code | Dead code preserved in comments |
42
+ | Unused imports | Imports not referenced anywhere in file |
43
+ | Verbose names | Unnecessarily long names (`currentUserDataObject` → `user`) |
44
+ | Unnecessary intermediates | Variables used once, immediately after assignment |
45
+
46
+ 4. **Enhance Clarity**: Simplify code structure by:
47
+
48
+ - Reducing unnecessary nesting (early returns, guard clauses)
38
49
  - Consolidating related logic
39
- - Removing unnecessary comments that describe obvious code
40
- - IMPORTANT: Avoid nested ternary operators - prefer switch statements or if/else chains for multiple conditions
41
- - Choose clarity over brevity - explicit code is often better than overly compact code
50
+ - Avoiding nested ternary operators — prefer switch or if/else
51
+ - Choosing clarity over brevity — explicit code beats compact code
42
52
 
43
- 4. **Maintain Balance**: Avoid over-simplification that could:
53
+ 5. **Maintain Balance**: Avoid over-simplification that could:
44
54
 
45
- - Reduce code clarity or maintainability
46
55
  - Create overly clever solutions that are hard to understand
47
56
  - Combine too many concerns into single functions or components
48
57
  - Remove helpful abstractions that improve code organization
49
- - Prioritize "fewer lines" over readability (e.g., nested ternaries, dense one-liners)
50
58
  - Make the code harder to debug or extend
51
59
 
52
- 5. **Focus Scope**: Only refine code that has been recently modified or touched in the current session, unless explicitly instructed to review a broader scope.
60
+ 6. **Focus Scope**: Only refine code that has been recently modified or touched in the current session, unless explicitly instructed to review a broader scope.
53
61
 
54
62
  Your refinement process:
55
63
 
56
64
  1. Identify the recently modified code sections
57
- 2. Analyze for opportunities to improve elegance and consistency
65
+ 2. Analyze for slop categories and clarity improvements
58
66
  3. Apply project-specific best practices and coding standards
59
67
  4. Ensure all functionality remains unchanged
60
68
  5. Verify the refined code is simpler and more maintainable
@@ -87,7 +95,8 @@ Return structured completion status:
87
95
  - Files outside the recently modified scope (unless instructed)
88
96
 
89
97
  **Handle autonomously:**
90
- - Naming improvements, dead code removal, nesting reduction
98
+ - Slop removal (all 8 categories)
99
+ - Naming improvements, nesting reduction
91
100
  - Import sorting and organization
92
101
  - Redundant abstraction elimination
93
- - Comment cleanup (remove obvious, keep non-obvious)
102
+ - Comment cleanup (remove obvious, keep non-obvious)
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "Dean0x"
6
6
  },
7
- "version": "1.7.0",
7
+ "version": "1.8.1",
8
8
  "homepage": "https://github.com/dean0x/devflow",
9
9
  "repository": "https://github.com/dean0x/devflow",
10
10
  "license": "MIT",