aiblueprint-cli 1.4.59 → 1.4.61

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 (184) hide show
  1. package/README.md +16 -36
  2. package/agents-config/agents/action.md +1 -1
  3. package/agents-config/agents/explore-codebase.md +53 -53
  4. package/agents-config/agents/explore-docs.md +50 -69
  5. package/agents-config/agents/websearch.md +36 -40
  6. package/agents-config/claude-config/scripts/.claude/skills/fix-on-my-computer/SKILL.md +81 -0
  7. package/agents-config/claude-config/scripts/CLAUDE.md +10 -4
  8. package/agents-config/claude-config/scripts/bun.lockb +0 -0
  9. package/agents-config/claude-config/scripts/package.json +22 -30
  10. package/agents-config/claude-config/scripts/statusline/CLAUDE.md +37 -155
  11. package/agents-config/claude-config/scripts/statusline/README.md +18 -94
  12. package/agents-config/claude-config/scripts/statusline/defaults.json +13 -10
  13. package/agents-config/claude-config/scripts/statusline/fixtures/mock-transcript.jsonl +4 -4
  14. package/agents-config/claude-config/scripts/statusline/fixtures/test-input.json +4 -4
  15. package/agents-config/claude-config/scripts/statusline/src/commands/interactive-config.ts +403 -0
  16. package/agents-config/claude-config/scripts/statusline/src/index.ts +33 -82
  17. package/agents-config/claude-config/scripts/statusline/src/lib/config-types.ts +7 -1
  18. package/agents-config/claude-config/scripts/statusline/src/lib/formatters.ts +40 -0
  19. package/agents-config/claude-config/scripts/statusline/src/lib/presets.ts +13 -13
  20. package/agents-config/claude-config/scripts/statusline/src/lib/render-pure.ts +24 -5
  21. package/agents-config/claude-config/scripts/statusline/statusline.config.free.json +79 -0
  22. package/agents-config/claude-config/scripts/statusline/statusline.config.json +77 -77
  23. package/agents-config/codex-config/config.toml +9 -0
  24. package/agents-config/codex-config/hooks/command-deny-list.ts +203 -0
  25. package/agents-config/commands/prompts/create-vitejs-app.md +272 -0
  26. package/agents-config/commands/prompts/nextjs-add-prisma-db.md +136 -0
  27. package/agents-config/commands/prompts/nextjs-setup-better-auth.md +173 -0
  28. package/agents-config/commands/prompts/nextjs-setup-project.md +200 -0
  29. package/agents-config/commands/prompts/prompt.md +55 -0
  30. package/agents-config/commands/prompts/saas-challenge-idea.md +135 -0
  31. package/agents-config/commands/prompts/saas-create-architecture.md +242 -0
  32. package/agents-config/commands/prompts/saas-create-headline.md +132 -0
  33. package/agents-config/commands/prompts/saas-create-landing-copywritting.md +267 -0
  34. package/agents-config/commands/prompts/saas-create-legals-docs.md +176 -0
  35. package/agents-config/commands/prompts/saas-create-logos.md +240 -0
  36. package/agents-config/commands/prompts/saas-create-prd.md +195 -0
  37. package/agents-config/commands/prompts/saas-create-tasks.md +240 -0
  38. package/agents-config/commands/prompts/saas-define-pricing.md +293 -0
  39. package/agents-config/commands/prompts/saas-find-domain-name.md +190 -0
  40. package/agents-config/commands/prompts/saas-implement-landing-page.md +257 -0
  41. package/agents-config/commands/prompts/setup-tmux.md +160 -0
  42. package/agents-config/commands/prompts/tools.md +148 -0
  43. package/agents-config/scripts/.claude/skills/fix-on-my-computer/SKILL.md +81 -0
  44. package/agents-config/scripts/CLAUDE.md +37 -0
  45. package/agents-config/scripts/biome.json +37 -0
  46. package/agents-config/scripts/bun.lockb +0 -0
  47. package/agents-config/scripts/package.json +24 -0
  48. package/agents-config/scripts/statusline/CLAUDE.md +87 -0
  49. package/agents-config/scripts/statusline/README.md +117 -0
  50. package/agents-config/scripts/statusline/__tests__/context.test.ts +229 -0
  51. package/agents-config/scripts/statusline/__tests__/formatters.test.ts +108 -0
  52. package/agents-config/scripts/statusline/__tests__/statusline.test.ts +309 -0
  53. package/agents-config/scripts/statusline/defaults.json +82 -0
  54. package/agents-config/scripts/statusline/fixtures/mock-transcript.jsonl +4 -0
  55. package/agents-config/scripts/statusline/fixtures/test-input.json +35 -0
  56. package/agents-config/scripts/statusline/src/commands/interactive-config.ts +403 -0
  57. package/agents-config/scripts/statusline/src/index.ts +141 -0
  58. package/agents-config/scripts/statusline/src/lib/config-types.ts +110 -0
  59. package/agents-config/scripts/statusline/src/lib/config.ts +21 -0
  60. package/agents-config/scripts/statusline/src/lib/context.ts +103 -0
  61. package/agents-config/scripts/statusline/src/lib/formatters.ts +426 -0
  62. package/agents-config/scripts/statusline/src/lib/git.ts +100 -0
  63. package/agents-config/scripts/statusline/src/lib/menu-factories.ts +224 -0
  64. package/agents-config/scripts/statusline/src/lib/presets.ts +177 -0
  65. package/agents-config/scripts/statusline/src/lib/render-pure.ts +516 -0
  66. package/agents-config/scripts/statusline/src/lib/types.ts +36 -0
  67. package/agents-config/scripts/statusline/src/lib/utils.ts +15 -0
  68. package/agents-config/scripts/statusline/statusline.config.free.json +79 -0
  69. package/agents-config/scripts/statusline/statusline.config.json +79 -0
  70. package/agents-config/scripts/statusline/test-with-fixtures.ts +37 -0
  71. package/agents-config/scripts/statusline/test.ts +20 -0
  72. package/agents-config/scripts/statusline/tsconfig.json +27 -0
  73. package/agents-config/scripts/tsconfig.json +27 -0
  74. package/agents-config/skills/{subagent-creator → agents-managers}/SKILL.md +47 -47
  75. package/agents-config/skills/{subagent-creator/references/subagents.md → agents-managers/references/agents.md} +45 -45
  76. package/agents-config/skills/{subagent-creator → agents-managers}/references/context-management.md +20 -20
  77. package/agents-config/skills/{subagent-creator → agents-managers}/references/debugging-agents.md +27 -27
  78. package/agents-config/skills/{subagent-creator → agents-managers}/references/error-handling-and-recovery.md +19 -19
  79. package/agents-config/skills/{subagent-creator → agents-managers}/references/evaluation-and-testing.md +29 -29
  80. package/agents-config/skills/{subagent-creator → agents-managers}/references/orchestration-patterns.md +5 -5
  81. package/agents-config/skills/{subagent-creator/references/writing-subagent-prompts.md → agents-managers/references/writing-agent-prompts.md} +23 -23
  82. package/agents-config/skills/codex-environment/SKILL.md +2 -0
  83. package/agents-config/skills/commit/SKILL.md +2 -0
  84. package/agents-config/skills/create-pr/SKILL.md +2 -0
  85. package/agents-config/skills/environments-manager/SKILL.md +271 -0
  86. package/agents-config/skills/environments-manager/examples/claude/.worktreeinclude +3 -0
  87. package/agents-config/skills/environments-manager/examples/claude/commands/dev.md +5 -0
  88. package/agents-config/skills/environments-manager/examples/claude/commands/lint.md +5 -0
  89. package/agents-config/skills/environments-manager/examples/claude/commands/test.md +5 -0
  90. package/agents-config/skills/environments-manager/examples/claude/commands/typecheck.md +5 -0
  91. package/agents-config/skills/environments-manager/examples/claude/settings.json +24 -0
  92. package/agents-config/skills/environments-manager/examples/codex/environments/environment.toml +29 -0
  93. package/agents-config/skills/environments-manager/examples/cursor/worktrees.json +3 -0
  94. package/agents-config/skills/environments-manager/examples/scripts/claude-worktree-create.sh +96 -0
  95. package/agents-config/skills/environments-manager/examples/scripts/claude-worktree-remove.sh +66 -0
  96. package/agents-config/skills/environments-manager/examples/scripts/dev.sh +15 -0
  97. package/agents-config/skills/environments-manager/examples/scripts/worktree-down.sh +22 -0
  98. package/agents-config/skills/environments-manager/examples/scripts/worktree-up.sh +50 -0
  99. package/agents-config/skills/environments-manager/references/claude.md +156 -0
  100. package/agents-config/skills/environments-manager/references/codex.md +97 -0
  101. package/agents-config/skills/environments-manager/references/cursor.md +88 -0
  102. package/agents-config/skills/fix-pr-comments/SKILL.md +2 -0
  103. package/agents-config/skills/grill-me/SKILL.md +10 -0
  104. package/agents-config/skills/merge/SKILL.md +2 -0
  105. package/agents-config/skills/rules-manager/SKILL.md +191 -0
  106. package/agents-config/skills/rules-manager/references/agents-vs-claude.md +66 -0
  107. package/agents-config/skills/rules-manager/references/examples.md +117 -0
  108. package/agents-config/skills/skill-manager/SKILL.md +101 -0
  109. package/agents-config/skills/skill-manager/references/claude-code.md +81 -0
  110. package/agents-config/skills/skill-manager/references/codex.md +288 -0
  111. package/agents-config/skills/skill-manager/references/cursor.md +125 -0
  112. package/agents-config/skills/skill-manager/references/description-recommandation.md +97 -0
  113. package/agents-config/skills/skill-manager/scripts/inspect-description.ts +743 -0
  114. package/agents-config/skills/ultrathink/SKILL.md +2 -0
  115. package/dist/cli.js +581 -299
  116. package/package.json +1 -1
  117. package/agents-config/claude-config/scripts/statusline/data/.gitignore +0 -8
  118. package/agents-config/claude-config/scripts/statusline/data/.gitkeep +0 -0
  119. package/agents-config/claude-config/scripts/statusline/docs/ARCHITECTURE.md +0 -166
  120. package/agents-config/claude-config/scripts/statusline/src/tests/spend-v2.test.ts +0 -306
  121. package/agents-config/skills/apex/SKILL.md +0 -261
  122. package/agents-config/skills/apex/scripts/setup-templates.sh +0 -100
  123. package/agents-config/skills/apex/scripts/update-progress.sh +0 -80
  124. package/agents-config/skills/apex/steps/step-00-init.md +0 -267
  125. package/agents-config/skills/apex/steps/step-00b-branch.md +0 -126
  126. package/agents-config/skills/apex/steps/step-00b-economy.md +0 -244
  127. package/agents-config/skills/apex/steps/step-00b-interactive.md +0 -153
  128. package/agents-config/skills/apex/steps/step-01-analyze.md +0 -361
  129. package/agents-config/skills/apex/steps/step-02-plan.md +0 -264
  130. package/agents-config/skills/apex/steps/step-03-execute.md +0 -239
  131. package/agents-config/skills/apex/steps/step-04-validate.md +0 -251
  132. package/agents-config/skills/apex/templates/00-context.md +0 -43
  133. package/agents-config/skills/apex/templates/01-analyze.md +0 -10
  134. package/agents-config/skills/apex/templates/02-plan.md +0 -10
  135. package/agents-config/skills/apex/templates/03-execute.md +0 -10
  136. package/agents-config/skills/apex/templates/04-validate.md +0 -10
  137. package/agents-config/skills/apex/templates/README.md +0 -176
  138. package/agents-config/skills/apex/templates/step-complete.md +0 -7
  139. package/agents-config/skills/claude-memory/SKILL.md +0 -293
  140. package/agents-config/skills/claude-memory/references/comprehensive-example.md +0 -175
  141. package/agents-config/skills/claude-memory/references/optimize-guide.md +0 -300
  142. package/agents-config/skills/claude-memory/references/project-patterns.md +0 -334
  143. package/agents-config/skills/claude-memory/references/prompting-techniques.md +0 -411
  144. package/agents-config/skills/claude-memory/references/rules-directory-guide.md +0 -298
  145. package/agents-config/skills/claude-memory/references/section-templates.md +0 -347
  146. package/agents-config/skills/fix-errors/SKILL.md +0 -61
  147. package/agents-config/skills/fix-grammar/SKILL.md +0 -59
  148. package/agents-config/skills/ralph-loop/SKILL.md +0 -117
  149. package/agents-config/skills/ralph-loop/scripts/setup.sh +0 -278
  150. package/agents-config/skills/ralph-loop/steps/step-00-init.md +0 -215
  151. package/agents-config/skills/ralph-loop/steps/step-01-interactive-prd.md +0 -366
  152. package/agents-config/skills/ralph-loop/steps/step-02-create-stories.md +0 -273
  153. package/agents-config/skills/ralph-loop/steps/step-03-finish.md +0 -245
  154. package/agents-config/skills/skill-creator/LICENSE.txt +0 -202
  155. package/agents-config/skills/skill-creator/SKILL.md +0 -421
  156. package/agents-config/skills/skill-creator/package.json +0 -5
  157. package/agents-config/skills/skill-creator/references/output-patterns.md +0 -82
  158. package/agents-config/skills/skill-creator/references/progressive-disclosure-patterns.md +0 -374
  159. package/agents-config/skills/skill-creator/references/prompting-integration.md +0 -363
  160. package/agents-config/skills/skill-creator/references/real-world-examples.md +0 -513
  161. package/agents-config/skills/skill-creator/references/script-patterns.md +0 -385
  162. package/agents-config/skills/skill-creator/references/workflows.md +0 -28
  163. package/agents-config/skills/skill-creator/references/xml-tag-guide.md +0 -606
  164. package/agents-config/skills/skill-creator/scripts/init-skill.ts +0 -214
  165. package/agents-config/skills/skill-creator/scripts/package-skill.ts +0 -146
  166. package/agents-config/skills/skill-creator/scripts/validate.ts +0 -138
  167. package/agents-config/skills/workflow-apex-free/SKILL.md +0 -261
  168. package/agents-config/skills/workflow-apex-free/scripts/setup-templates.sh +0 -100
  169. package/agents-config/skills/workflow-apex-free/scripts/update-progress.sh +0 -80
  170. package/agents-config/skills/workflow-apex-free/steps/step-00-init.md +0 -267
  171. package/agents-config/skills/workflow-apex-free/steps/step-00b-branch.md +0 -126
  172. package/agents-config/skills/workflow-apex-free/steps/step-00b-economy.md +0 -244
  173. package/agents-config/skills/workflow-apex-free/steps/step-00b-interactive.md +0 -153
  174. package/agents-config/skills/workflow-apex-free/steps/step-01-analyze.md +0 -361
  175. package/agents-config/skills/workflow-apex-free/steps/step-02-plan.md +0 -264
  176. package/agents-config/skills/workflow-apex-free/steps/step-03-execute.md +0 -239
  177. package/agents-config/skills/workflow-apex-free/steps/step-04-validate.md +0 -251
  178. package/agents-config/skills/workflow-apex-free/templates/00-context.md +0 -43
  179. package/agents-config/skills/workflow-apex-free/templates/01-analyze.md +0 -10
  180. package/agents-config/skills/workflow-apex-free/templates/02-plan.md +0 -10
  181. package/agents-config/skills/workflow-apex-free/templates/03-execute.md +0 -10
  182. package/agents-config/skills/workflow-apex-free/templates/04-validate.md +0 -10
  183. package/agents-config/skills/workflow-apex-free/templates/README.md +0 -176
  184. package/agents-config/skills/workflow-apex-free/templates/step-complete.md +0 -7
@@ -0,0 +1,516 @@
1
+ /**
2
+ * Pure statusline renderer - no I/O, no side effects
3
+ *
4
+ * ARCHITECTURE: Raw data in, formatted string out.
5
+ * ALL config decisions happen here, not in data preparation.
6
+ */
7
+
8
+ import type { StatuslineConfig } from "./config-types";
9
+ import {
10
+ colors,
11
+ formatCost,
12
+ formatDuration,
13
+ formatPath,
14
+ formatProgressBar,
15
+ formatResetTime,
16
+ formatTokens,
17
+ } from "./formatters";
18
+
19
+ const WEEKLY_HOURS = 168; // 7 days * 24 hours
20
+ const FIVE_HOUR_MINUTES = 300; // 5 hours * 60 minutes
21
+
22
+ // ─────────────────────────────────────────────────────────────
23
+ // RAW DATA TYPES - No pre-formatting, just raw values
24
+ // ─────────────────────────────────────────────────────────────
25
+
26
+ export interface GitChanges {
27
+ files: number;
28
+ added: number;
29
+ deleted: number;
30
+ }
31
+
32
+ export interface RawGitData {
33
+ branch: string;
34
+ dirty: boolean;
35
+ staged: GitChanges;
36
+ unstaged: GitChanges;
37
+ }
38
+
39
+ export interface UsageLimit {
40
+ utilization: number;
41
+ resets_at: string | null;
42
+ }
43
+
44
+ export interface RawStatuslineData {
45
+ git: RawGitData | null;
46
+ path: string;
47
+ modelName: string;
48
+ cost: number;
49
+ durationMs: number;
50
+ contextTokens: number | null;
51
+ contextPercentage: number | null;
52
+ usageLimits?: {
53
+ five_hour: UsageLimit | null;
54
+ seven_day: UsageLimit | null;
55
+ };
56
+ periodCost?: number;
57
+ todayCost?: number;
58
+ thinkingEnabled?: boolean;
59
+ }
60
+
61
+ // Legacy interface for backwards compatibility
62
+ export interface StatuslineData {
63
+ branch: string;
64
+ dirPath: string;
65
+ modelName: string;
66
+ sessionCost: string;
67
+ sessionDuration: string;
68
+ contextTokens: number | null;
69
+ contextPercentage: number | null;
70
+ usageLimits?: {
71
+ five_hour: UsageLimit | null;
72
+ seven_day: UsageLimit | null;
73
+ };
74
+ periodCost?: number;
75
+ todayCost?: number;
76
+ thinkingEnabled?: boolean;
77
+ }
78
+
79
+ // ─────────────────────────────────────────────────────────────
80
+ // FORMATTING - All config-aware formatting in one place
81
+ // ─────────────────────────────────────────────────────────────
82
+
83
+ function formatGitPart(
84
+ git: RawGitData | null,
85
+ config: StatuslineConfig["git"],
86
+ ): string {
87
+ if (!git || !config.enabled) return "";
88
+
89
+ const parts: string[] = [];
90
+
91
+ if (config.showBranch) {
92
+ parts.push(colors.lightGray(git.branch));
93
+ }
94
+
95
+ if (git.dirty && config.showDirtyIndicator) {
96
+ // Append to branch name without space
97
+ if (parts.length > 0) {
98
+ parts[parts.length - 1] += colors.purple("*");
99
+ } else {
100
+ parts.push(colors.purple("*"));
101
+ }
102
+ }
103
+
104
+ const changeParts: string[] = [];
105
+
106
+ if (config.showChanges) {
107
+ const totalAdded = git.staged.added + git.unstaged.added;
108
+ const totalDeleted = git.staged.deleted + git.unstaged.deleted;
109
+ if (totalAdded > 0) changeParts.push(colors.green(`+${totalAdded}`));
110
+ if (totalDeleted > 0) changeParts.push(colors.red(`-${totalDeleted}`));
111
+ }
112
+
113
+ if (config.showStaged && git.staged.files > 0) {
114
+ changeParts.push(colors.gray(`~${git.staged.files}`));
115
+ }
116
+
117
+ if (config.showUnstaged && git.unstaged.files > 0) {
118
+ changeParts.push(colors.yellow(`~${git.unstaged.files}`));
119
+ }
120
+
121
+ if (changeParts.length > 0) {
122
+ parts.push(changeParts.join(" "));
123
+ }
124
+
125
+ return parts.join(" ");
126
+ }
127
+
128
+ function formatSessionPart(
129
+ cost: number,
130
+ durationMs: number,
131
+ contextTokens: number | null,
132
+ contextPercentage: number | null,
133
+ maxTokens: number,
134
+ config: StatuslineConfig["session"],
135
+ ): string {
136
+ // No context data yet - show placeholder
137
+ if (contextTokens === null || contextPercentage === null) {
138
+ return `${colors.gray("S:")} ${colors.gray("-")}`;
139
+ }
140
+
141
+ const items: string[] = [];
142
+
143
+ if (config.cost.enabled) {
144
+ const formattedCost = formatCost(cost, config.cost.format);
145
+ items.push(`${colors.gray("$")}${colors.dimWhite(formattedCost)}`);
146
+ }
147
+
148
+ if (config.tokens.enabled) {
149
+ const formattedUsed = formatTokens(
150
+ contextTokens,
151
+ config.tokens.showDecimals,
152
+ );
153
+ if (config.tokens.showMax) {
154
+ const formattedMax = formatTokens(maxTokens, config.tokens.showDecimals);
155
+ items.push(`${formattedUsed}${colors.gray("/")}${formattedMax}`);
156
+ } else {
157
+ items.push(formattedUsed);
158
+ }
159
+ }
160
+
161
+ if (config.percentage.enabled) {
162
+ const pctParts: string[] = [];
163
+
164
+ if (config.percentage.progressBar.enabled) {
165
+ pctParts.push(
166
+ formatProgressBar({
167
+ percentage: contextPercentage,
168
+ length: config.percentage.progressBar.length,
169
+ style: config.percentage.progressBar.style,
170
+ colorMode: config.percentage.progressBar.color,
171
+ background: config.percentage.progressBar.background,
172
+ }),
173
+ );
174
+ }
175
+
176
+ if (config.percentage.showValue) {
177
+ pctParts.push(
178
+ `${colors.lightGray(contextPercentage.toString())}${colors.gray("%")}`,
179
+ );
180
+ }
181
+
182
+ if (pctParts.length > 0) {
183
+ items.push(pctParts.join(" "));
184
+ }
185
+ }
186
+
187
+ if (config.duration.enabled) {
188
+ items.push(colors.gray(`(${formatDuration(durationMs)})`));
189
+ }
190
+
191
+ if (items.length === 0) return "";
192
+
193
+ const sep = config.infoSeparator
194
+ ? ` ${colors.gray(config.infoSeparator)} `
195
+ : " ";
196
+ return `${colors.gray("S:")} ${items.join(sep)}`;
197
+ }
198
+
199
+ function formatLimitsPart(
200
+ fiveHour: UsageLimit | null,
201
+ periodCost: number,
202
+ config: StatuslineConfig["limits"],
203
+ ): string {
204
+ if (!config.enabled || !fiveHour) return "";
205
+
206
+ const parts: string[] = [];
207
+
208
+ if (config.cost.enabled && periodCost > 0) {
209
+ parts.push(
210
+ `${colors.gray("$")}${colors.dimWhite(formatCost(periodCost, config.cost.format))}`,
211
+ );
212
+ }
213
+
214
+ if (config.percentage.enabled) {
215
+ if (config.percentage.progressBar.enabled) {
216
+ parts.push(
217
+ formatProgressBar({
218
+ percentage: fiveHour.utilization,
219
+ length: config.percentage.progressBar.length,
220
+ style: config.percentage.progressBar.style,
221
+ colorMode: config.percentage.progressBar.color,
222
+ background: config.percentage.progressBar.background,
223
+ }),
224
+ );
225
+ }
226
+
227
+ if (config.percentage.showValue) {
228
+ parts.push(
229
+ `${colors.lightGray(fiveHour.utilization.toString())}${colors.gray("%")}`,
230
+ );
231
+ }
232
+ }
233
+
234
+ if (config.showPacingDelta && fiveHour.resets_at) {
235
+ const delta = calculateFiveHourDelta(
236
+ fiveHour.utilization,
237
+ fiveHour.resets_at,
238
+ );
239
+ parts.push(
240
+ `${colors.gray("(")}${formatPacingDelta(delta)}${colors.gray(")")}`,
241
+ );
242
+ }
243
+
244
+ if (config.showTimeLeft && fiveHour.resets_at) {
245
+ parts.push(colors.gray(`(${formatResetTime(fiveHour.resets_at)})`));
246
+ }
247
+
248
+ return parts.length > 0 ? `${colors.gray("L:")} ${parts.join(" ")}` : "";
249
+ }
250
+
251
+ function shouldShowWeekly(
252
+ config: StatuslineConfig["weeklyUsage"],
253
+ fiveHourUtilization: number | null,
254
+ ): boolean {
255
+ if (config.enabled === true) return true;
256
+ if (config.enabled === false) return false;
257
+ if (config.enabled === "90%" && fiveHourUtilization !== null) {
258
+ return fiveHourUtilization >= 90;
259
+ }
260
+ return false;
261
+ }
262
+
263
+ function calculateWeeklyDelta(
264
+ utilization: number,
265
+ resetsAt: string | null,
266
+ ): number {
267
+ if (!resetsAt) return 0;
268
+
269
+ const resetDate = new Date(resetsAt);
270
+ const now = new Date();
271
+ const diffMs = resetDate.getTime() - now.getTime();
272
+ const hoursRemaining = Math.max(0, diffMs / 3600000);
273
+ const timeElapsedPercent =
274
+ ((WEEKLY_HOURS - hoursRemaining) / WEEKLY_HOURS) * 100;
275
+
276
+ return utilization - timeElapsedPercent;
277
+ }
278
+
279
+ function formatPacingDelta(delta: number): string {
280
+ const inverted = -delta;
281
+ const sign = inverted >= 0 ? "+" : "";
282
+ const value = `${sign}${inverted.toFixed(1)}%`;
283
+
284
+ if (inverted > 5) return colors.green(value);
285
+ if (inverted > 0) return colors.lightGray(value);
286
+ if (inverted > -10) return colors.yellow(value);
287
+ return colors.red(value);
288
+ }
289
+
290
+ function calculateFiveHourDelta(
291
+ utilization: number,
292
+ resetsAt: string | null,
293
+ ): number {
294
+ if (!resetsAt) return 0;
295
+
296
+ const resetDate = new Date(resetsAt);
297
+ const now = new Date();
298
+ const diffMs = resetDate.getTime() - now.getTime();
299
+ const minutesRemaining = Math.max(0, diffMs / 60000);
300
+ const timeElapsedPercent =
301
+ ((FIVE_HOUR_MINUTES - minutesRemaining) / FIVE_HOUR_MINUTES) * 100;
302
+
303
+ return utilization - timeElapsedPercent;
304
+ }
305
+
306
+ function formatWeeklyPart(
307
+ sevenDay: UsageLimit | null,
308
+ fiveHourUtilization: number | null,
309
+ periodCost: number,
310
+ config: StatuslineConfig["weeklyUsage"],
311
+ ): string {
312
+ if (!shouldShowWeekly(config, fiveHourUtilization) || !sevenDay) return "";
313
+
314
+ const parts: string[] = [];
315
+
316
+ if (config.cost.enabled && periodCost > 0) {
317
+ parts.push(
318
+ `${colors.gray("$")}${colors.dimWhite(formatCost(periodCost, config.cost.format))}`,
319
+ );
320
+ }
321
+
322
+ if (config.percentage.enabled) {
323
+ if (config.percentage.progressBar.enabled) {
324
+ parts.push(
325
+ formatProgressBar({
326
+ percentage: sevenDay.utilization,
327
+ length: config.percentage.progressBar.length,
328
+ style: config.percentage.progressBar.style,
329
+ colorMode: config.percentage.progressBar.color,
330
+ background: config.percentage.progressBar.background,
331
+ }),
332
+ );
333
+ }
334
+
335
+ if (config.percentage.showValue) {
336
+ parts.push(
337
+ `${colors.lightGray(sevenDay.utilization.toString())}${colors.gray("%")}`,
338
+ );
339
+ }
340
+ }
341
+
342
+ if (config.showPacingDelta && sevenDay.resets_at) {
343
+ const delta = calculateWeeklyDelta(
344
+ sevenDay.utilization,
345
+ sevenDay.resets_at,
346
+ );
347
+ parts.push(
348
+ `${colors.gray("(")}${formatPacingDelta(delta)}${colors.gray(")")}`,
349
+ );
350
+ }
351
+
352
+ if (config.showTimeLeft && sevenDay.resets_at) {
353
+ parts.push(colors.gray(`(${formatResetTime(sevenDay.resets_at)})`));
354
+ }
355
+
356
+ return parts.length > 0 ? `${colors.gray("W:")} ${parts.join(" ")}` : "";
357
+ }
358
+
359
+ function formatDailyPart(
360
+ todayCost: number,
361
+ config: StatuslineConfig["dailySpend"],
362
+ ): string {
363
+ if (!config.cost.enabled || todayCost <= 0) return "";
364
+ return `${colors.gray("D:")} ${colors.gray("$")}${colors.dimWhite(formatCost(todayCost, config.cost.format))}`;
365
+ }
366
+
367
+ function formatThinkingPart(
368
+ thinkingEnabled: boolean,
369
+ config: StatuslineConfig["thinking"],
370
+ ): string {
371
+ if (!config.showDisabledWarning || thinkingEnabled) return "";
372
+ return colors.red("Thinking: OFF");
373
+ }
374
+
375
+ // ─────────────────────────────────────────────────────────────
376
+ // MAIN RENDER FUNCTION - Raw data + config = output
377
+ // ─────────────────────────────────────────────────────────────
378
+
379
+ export function renderStatuslineRaw(
380
+ data: RawStatuslineData,
381
+ config: StatuslineConfig,
382
+ ): string {
383
+ const sep = colors.gray(config.separator);
384
+ const sections: string[] = [];
385
+
386
+ // Line 1: Git + Path + Model
387
+ const line1Parts: string[] = [];
388
+
389
+ const gitPart = formatGitPart(data.git, config.git);
390
+ if (gitPart) line1Parts.push(gitPart);
391
+
392
+ const pathPart = formatPath(data.path, config.pathDisplayMode);
393
+ line1Parts.push(colors.gray(pathPart));
394
+
395
+ const isSonnet = data.modelName.toLowerCase().includes("sonnet");
396
+ if (!isSonnet || config.showSonnetModel) {
397
+ line1Parts.push(colors.peach(data.modelName));
398
+ }
399
+
400
+ sections.push(line1Parts.join(` ${sep} `));
401
+
402
+ // Line 2: Session info
403
+ const sessionPart = formatSessionPart(
404
+ data.cost,
405
+ data.durationMs,
406
+ data.contextTokens,
407
+ data.contextPercentage,
408
+ config.context.maxContextTokens,
409
+ config.session,
410
+ );
411
+ if (sessionPart) sections.push(sessionPart);
412
+
413
+ // Limits
414
+ const limitsPart = formatLimitsPart(
415
+ data.usageLimits?.five_hour ?? null,
416
+ data.periodCost ?? 0,
417
+ config.limits,
418
+ );
419
+ if (limitsPart) sections.push(limitsPart);
420
+
421
+ // Weekly
422
+ const weeklyPart = formatWeeklyPart(
423
+ data.usageLimits?.seven_day ?? null,
424
+ data.usageLimits?.five_hour?.utilization ?? null,
425
+ data.periodCost ?? 0,
426
+ config.weeklyUsage,
427
+ );
428
+ if (weeklyPart) sections.push(weeklyPart);
429
+
430
+ // Daily
431
+ const dailyPart = formatDailyPart(data.todayCost ?? 0, config.dailySpend);
432
+ if (dailyPart) sections.push(dailyPart);
433
+
434
+ // Thinking warning (last position)
435
+ const thinkingPart = formatThinkingPart(
436
+ data.thinkingEnabled ?? true,
437
+ config.thinking,
438
+ );
439
+ if (thinkingPart) sections.push(thinkingPart);
440
+
441
+ const output = sections.join(` ${sep} `);
442
+
443
+ if (config.oneLine) return output;
444
+
445
+ // Two-line mode: break after line1
446
+ const line1 = sections[0];
447
+ const rest = sections.slice(1).join(` ${sep} `);
448
+ return rest ? `${line1}\n${rest}` : line1;
449
+ }
450
+
451
+ // ─────────────────────────────────────────────────────────────
452
+ // LEGACY SUPPORT - For backwards compatibility with old data format
453
+ // ─────────────────────────────────────────────────────────────
454
+
455
+ export function renderStatusline(
456
+ data: StatuslineData,
457
+ config: StatuslineConfig,
458
+ ): string {
459
+ // Convert legacy format to raw format
460
+ // Parse pre-formatted values back to raw (best effort)
461
+ const rawData: RawStatuslineData = {
462
+ git: parseGitFromBranch(data.branch),
463
+ path: data.dirPath.startsWith("~") ? data.dirPath : data.dirPath,
464
+ modelName: data.modelName,
465
+ cost: parseFloat(data.sessionCost.replace(/[$,]/g, "")) || 0,
466
+ durationMs: parseDurationToMs(data.sessionDuration),
467
+ contextTokens: data.contextTokens,
468
+ contextPercentage: data.contextPercentage,
469
+ usageLimits: data.usageLimits,
470
+ periodCost: data.periodCost,
471
+ todayCost: data.todayCost,
472
+ thinkingEnabled: data.thinkingEnabled,
473
+ };
474
+
475
+ return renderStatuslineRaw(rawData, config);
476
+ }
477
+
478
+ // Helper to parse legacy branch string back to git data
479
+ function parseGitFromBranch(branch: string): RawGitData | null {
480
+ if (!branch) return null;
481
+
482
+ // Parse "main* +10 -5" format
483
+ const dirty = branch.includes("*");
484
+ const branchName =
485
+ branch.replace(/\*.*$/, "").replace(/\*/, "").trim() || "main";
486
+
487
+ const addMatch = branch.match(/\+(\d+)/);
488
+ const delMatch = branch.match(/-(\d+)/);
489
+ const added = addMatch ? parseInt(addMatch[1], 10) : 0;
490
+ const deleted = delMatch ? parseInt(delMatch[1], 10) : 0;
491
+
492
+ return {
493
+ branch: branchName,
494
+ dirty,
495
+ staged: {
496
+ files: 0,
497
+ added: Math.floor(added / 2),
498
+ deleted: Math.floor(deleted / 2),
499
+ },
500
+ unstaged: {
501
+ files: 0,
502
+ added: Math.ceil(added / 2),
503
+ deleted: Math.ceil(deleted / 2),
504
+ },
505
+ };
506
+ }
507
+
508
+ // Helper to parse "12m" or "1h 30m" back to ms
509
+ function parseDurationToMs(duration: string): number {
510
+ let ms = 0;
511
+ const hourMatch = duration.match(/(\d+)h/);
512
+ const minMatch = duration.match(/(\d+)m/);
513
+ if (hourMatch) ms += parseInt(hourMatch[1], 10) * 3600000;
514
+ if (minMatch) ms += parseInt(minMatch[1], 10) * 60000;
515
+ return ms || 720000; // Default 12 minutes
516
+ }
@@ -0,0 +1,36 @@
1
+ export interface HookInput {
2
+ session_id: string;
3
+ transcript_path: string;
4
+ cwd: string;
5
+ model: {
6
+ id: string;
7
+ display_name: string;
8
+ };
9
+ workspace: {
10
+ current_dir: string;
11
+ project_dir: string;
12
+ };
13
+ version: string;
14
+ output_style: {
15
+ name: string;
16
+ };
17
+ cost: {
18
+ total_cost_usd: number;
19
+ total_duration_ms: number;
20
+ total_api_duration_ms: number;
21
+ total_lines_added: number;
22
+ total_lines_removed: number;
23
+ };
24
+ context_window?: {
25
+ total_input_tokens: number;
26
+ total_output_tokens: number;
27
+ context_window_size: number;
28
+ current_usage?: {
29
+ input_tokens: number;
30
+ output_tokens: number;
31
+ cache_creation_input_tokens?: number;
32
+ cache_read_input_tokens?: number;
33
+ };
34
+ };
35
+ exceeds_200k_tokens?: boolean;
36
+ }
@@ -0,0 +1,15 @@
1
+ export function normalizeResetsAt(resetsAt: string): string {
2
+ try {
3
+ const date = new Date(resetsAt);
4
+ const minutes = date.getMinutes();
5
+ const roundedMinutes = Math.round(minutes / 5) * 5;
6
+
7
+ date.setMinutes(roundedMinutes);
8
+ date.setSeconds(0);
9
+ date.setMilliseconds(0);
10
+
11
+ return date.toISOString();
12
+ } catch {
13
+ return resetsAt;
14
+ }
15
+ }
@@ -0,0 +1,79 @@
1
+ {
2
+ "features": {
3
+ "usageLimits": false,
4
+ "spendTracking": false
5
+ },
6
+ "oneLine": true,
7
+ "showSonnetModel": false,
8
+ "pathDisplayMode": "truncated",
9
+ "git": {
10
+ "enabled": true,
11
+ "showBranch": true,
12
+ "showDirtyIndicator": true,
13
+ "showChanges": false,
14
+ "showStaged": true,
15
+ "showUnstaged": true
16
+ },
17
+ "separator": "•",
18
+ "session": {
19
+ "infoSeparator": null,
20
+ "cost": { "enabled": false, "format": "decimal1" },
21
+ "duration": { "enabled": true },
22
+ "tokens": { "enabled": true, "showMax": false, "showDecimals": false },
23
+ "percentage": {
24
+ "enabled": true,
25
+ "showValue": true,
26
+ "progressBar": {
27
+ "enabled": true,
28
+ "length": 10,
29
+ "style": "braille",
30
+ "color": "progressive",
31
+ "background": "none"
32
+ }
33
+ }
34
+ },
35
+ "context": {
36
+ "usePayloadContextWindow": true,
37
+ "maxContextTokens": 200000,
38
+ "autocompactBufferTokens": 45000,
39
+ "useUsableContextOnly": true,
40
+ "overheadTokens": 0
41
+ },
42
+ "limits": {
43
+ "enabled": false,
44
+ "showTimeLeft": false,
45
+ "showPacingDelta": false,
46
+ "cost": { "enabled": false, "format": "decimal1" },
47
+ "percentage": {
48
+ "enabled": false,
49
+ "showValue": false,
50
+ "progressBar": {
51
+ "enabled": false,
52
+ "length": 10,
53
+ "style": "braille",
54
+ "color": "progressive",
55
+ "background": "none"
56
+ }
57
+ }
58
+ },
59
+ "weeklyUsage": {
60
+ "enabled": false,
61
+ "showTimeLeft": false,
62
+ "showPacingDelta": false,
63
+ "cost": { "enabled": false, "format": "decimal1" },
64
+ "percentage": {
65
+ "enabled": false,
66
+ "showValue": false,
67
+ "progressBar": {
68
+ "enabled": false,
69
+ "length": 10,
70
+ "style": "braille",
71
+ "color": "progressive",
72
+ "background": "none"
73
+ }
74
+ }
75
+ },
76
+ "dailySpend": {
77
+ "cost": { "enabled": false, "format": "decimal1" }
78
+ }
79
+ }