get-shit-done-cc 1.9.11 → 1.10.0-experimental.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +10 -9
  2. package/agents/design-specialist.md +222 -0
  3. package/agents/gsd-executor.md +37 -375
  4. package/agents/gsd-planner.md +15 -108
  5. package/bin/install.js +92 -5
  6. package/commands/gsd/autopilot.md +518 -0
  7. package/commands/gsd/checkpoints.md +229 -0
  8. package/commands/gsd/design-system.md +70 -0
  9. package/commands/gsd/discuss-design.md +77 -0
  10. package/commands/gsd/extend.md +80 -0
  11. package/commands/gsd/help.md +46 -17
  12. package/commands/gsd/new-project.md +94 -8
  13. package/commands/gsd/plan-phase.md +35 -5
  14. package/get-shit-done/references/ccr-integration.md +468 -0
  15. package/get-shit-done/references/checkpoint-execution.md +369 -0
  16. package/get-shit-done/references/checkpoint-types.md +728 -0
  17. package/get-shit-done/references/deviation-rules.md +215 -0
  18. package/get-shit-done/references/framework-patterns.md +543 -0
  19. package/get-shit-done/references/ui-principles.md +258 -0
  20. package/get-shit-done/references/verification-patterns.md +1 -1
  21. package/get-shit-done/skills/gsd-extend/SKILL.md +154 -0
  22. package/get-shit-done/skills/gsd-extend/references/agent-structure.md +305 -0
  23. package/get-shit-done/skills/gsd-extend/references/extension-anatomy.md +123 -0
  24. package/get-shit-done/skills/gsd-extend/references/reference-structure.md +408 -0
  25. package/get-shit-done/skills/gsd-extend/references/template-structure.md +370 -0
  26. package/get-shit-done/skills/gsd-extend/references/validation-rules.md +140 -0
  27. package/get-shit-done/skills/gsd-extend/references/workflow-structure.md +253 -0
  28. package/get-shit-done/skills/gsd-extend/templates/agent-template.md +234 -0
  29. package/get-shit-done/skills/gsd-extend/templates/reference-template.md +239 -0
  30. package/get-shit-done/skills/gsd-extend/templates/workflow-template.md +169 -0
  31. package/get-shit-done/skills/gsd-extend/workflows/create-approach.md +332 -0
  32. package/get-shit-done/skills/gsd-extend/workflows/list-extensions.md +133 -0
  33. package/get-shit-done/skills/gsd-extend/workflows/remove-extension.md +93 -0
  34. package/get-shit-done/skills/gsd-extend/workflows/validate-extension.md +184 -0
  35. package/get-shit-done/templates/autopilot-script-simple.sh +181 -0
  36. package/get-shit-done/templates/autopilot-script.sh +1142 -0
  37. package/get-shit-done/templates/autopilot-script.sh.backup +1142 -0
  38. package/get-shit-done/templates/design-system.md +238 -0
  39. package/get-shit-done/templates/phase-design.md +205 -0
  40. package/get-shit-done/templates/phase-models-template.json +71 -0
  41. package/get-shit-done/templates/phase-prompt.md +4 -4
  42. package/get-shit-done/templates/state.md +37 -0
  43. package/get-shit-done/tui/App.tsx +169 -0
  44. package/get-shit-done/tui/README.md +107 -0
  45. package/get-shit-done/tui/build.js +37 -0
  46. package/get-shit-done/tui/components/ActivityFeed.tsx +126 -0
  47. package/get-shit-done/tui/components/PhaseCard.tsx +86 -0
  48. package/get-shit-done/tui/components/StatsBar.tsx +147 -0
  49. package/get-shit-done/tui/dist/index.js +387 -0
  50. package/get-shit-done/tui/index.tsx +12 -0
  51. package/get-shit-done/tui/package-lock.json +1074 -0
  52. package/get-shit-done/tui/package.json +22 -0
  53. package/get-shit-done/tui/utils/pipeReader.ts +129 -0
  54. package/get-shit-done/workflows/design-system.md +245 -0
  55. package/get-shit-done/workflows/discuss-design.md +330 -0
  56. package/get-shit-done/workflows/execute-phase.md +44 -1
  57. package/get-shit-done/workflows/execute-plan-auth.md +122 -0
  58. package/get-shit-done/workflows/execute-plan-checkpoints.md +541 -0
  59. package/get-shit-done/workflows/execute-plan.md +34 -856
  60. package/package.json +8 -3
  61. package/commands/gsd/whats-new.md +0 -124
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
+ }) : x)(function(x) {
5
+ if (typeof require !== "undefined") return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // index.tsx
10
+ import React5 from "react";
11
+ import { render } from "ink";
12
+
13
+ // App.tsx
14
+ import React4, { useState as useState2, useEffect as useEffect2, useMemo } from "react";
15
+ import { Box as Box4, Text as Text4 } from "ink";
16
+
17
+ // components/PhaseCard.tsx
18
+ import React from "react";
19
+ import { Box, Text } from "ink";
20
+ var PhaseCard = ({
21
+ phase,
22
+ phaseName,
23
+ totalPhases,
24
+ currentPhaseIndex,
25
+ stages,
26
+ description,
27
+ progress
28
+ }) => {
29
+ const getStageColor = (stage) => {
30
+ var _a;
31
+ if (stage.completed) return "green";
32
+ if (stage.name === ((_a = stages[stages.length - 1]) == null ? void 0 : _a.name)) return "cyan";
33
+ return "gray";
34
+ };
35
+ return /* @__PURE__ */ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1 }, /* @__PURE__ */ React.createElement(Box, { justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React.createElement(Text, { bold: true, color: "cyan" }, `PHASE ${phase}`), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, currentPhaseIndex + 1, " / ", totalPhases)), /* @__PURE__ */ React.createElement(Text, { bold: true }, phaseName), !!description && /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, description)), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Progress"), /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Box, { width: 40 }, /* @__PURE__ */ React.createElement(Text, null, Array.from({ length: 40 }, (_, i) => {
36
+ const fillPercent = i / 40 * 100;
37
+ return /* @__PURE__ */ React.createElement(Text, { key: i, backgroundColor: fillPercent <= progress ? "cyan" : void 0 }, fillPercent <= progress ? "\u2588" : "\u2591");
38
+ }))), /* @__PURE__ */ React.createElement(Text, null, " ", Math.round(progress), "%"))), /* @__PURE__ */ React.createElement(Box, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React.createElement(Text, { bold: true }, "Stages"), stages.map((stage, idx) => /* @__PURE__ */ React.createElement(Box, { key: idx, justifyContent: "space-between" }, /* @__PURE__ */ React.createElement(Text, { color: getStageColor(stage) }, stage.completed ? "\u2713" : "\u25CB", " ", stage.name), /* @__PURE__ */ React.createElement(Text, { dimColor: true }, stage.elapsed || "in progress...")))));
39
+ };
40
+
41
+ // components/ActivityFeed.tsx
42
+ import React2, { useEffect, useState } from "react";
43
+ import { Box as Box2, Text as Text2 } from "ink";
44
+ var ActivityFeed = ({ activities, maxItems = 12 }) => {
45
+ const [dots, setDots] = useState("");
46
+ useEffect(() => {
47
+ const timer = setInterval(() => {
48
+ setDots((prev) => {
49
+ if (prev.length >= 3) return "";
50
+ return prev + ".";
51
+ });
52
+ }, 500);
53
+ return () => clearInterval(timer);
54
+ }, []);
55
+ const displayActivities = activities.slice(-maxItems);
56
+ const getActivityIcon = (type) => {
57
+ switch (type) {
58
+ case "read":
59
+ return "\u{1F4D6}";
60
+ case "write":
61
+ return "\u270D\uFE0F";
62
+ case "edit":
63
+ return "\u{1F4DD}";
64
+ case "commit":
65
+ return "\u2713";
66
+ case "test":
67
+ return "\u{1F9EA}";
68
+ case "stage":
69
+ return "\u2699\uFE0F";
70
+ case "error":
71
+ return "\u26D4";
72
+ case "info":
73
+ return "\u2139\uFE0F";
74
+ default:
75
+ return "\u2022";
76
+ }
77
+ };
78
+ const getActivityColor = (type) => {
79
+ switch (type) {
80
+ case "read":
81
+ return "blue";
82
+ case "write":
83
+ return "green";
84
+ case "edit":
85
+ return "yellow";
86
+ case "commit":
87
+ return "green";
88
+ case "test":
89
+ return "magenta";
90
+ case "stage":
91
+ return "cyan";
92
+ case "error":
93
+ return "red";
94
+ case "info":
95
+ return "gray";
96
+ default:
97
+ return "white";
98
+ }
99
+ };
100
+ const getTypeLabel = (type) => {
101
+ const labels = {
102
+ read: "READ",
103
+ write: "WRITE",
104
+ edit: "EDIT",
105
+ commit: "COMMIT",
106
+ test: "TEST",
107
+ stage: "STAGE",
108
+ error: "ERROR",
109
+ info: "INFO"
110
+ };
111
+ return labels[type] || "ACTIVITY";
112
+ };
113
+ return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 1, height: 18 }, /* @__PURE__ */ React2.createElement(Box2, { justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React2.createElement(Text2, { bold: true }, "Activity Feed"), /* @__PURE__ */ React2.createElement(Text2, { color: "gray" }, dots)), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1, overflow: "hidden" }, displayActivities.length === 0 ? /* @__PURE__ */ React2.createElement(Text2, { dimColor: true, italic: true }, "Waiting for activity...") : displayActivities.map((activity, idx) => /* @__PURE__ */ React2.createElement(
114
+ Box2,
115
+ {
116
+ key: idx,
117
+ justifyContent: "space-between",
118
+ alignItems: "center",
119
+ marginBottom: idx < displayActivities.length - 1 ? 0 : 0
120
+ },
121
+ /* @__PURE__ */ React2.createElement(Box2, { flexGrow: 1 }, /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, "[", activity.timestamp.toLocaleTimeString(), "]"), " ", /* @__PURE__ */ React2.createElement(Text2, { color: getActivityColor(activity.type) }, getActivityIcon(activity.type)), " ", /* @__PURE__ */ React2.createElement(Text2, { dimColor: true }, getTypeLabel(activity.type), ":"), " ", activity.detail))
122
+ ))));
123
+ };
124
+
125
+ // components/StatsBar.tsx
126
+ import React3 from "react";
127
+ import { Box as Box3, Text as Text3 } from "ink";
128
+ var StatsBar = ({
129
+ totalPhases,
130
+ completedPhases,
131
+ elapsedTime,
132
+ estimatedTimeRemaining,
133
+ tokens,
134
+ cost,
135
+ budget
136
+ }) => {
137
+ const progress = completedPhases / totalPhases * 100;
138
+ const formatTime = (seconds) => {
139
+ const hrs = Math.floor(seconds / 3600);
140
+ const mins = Math.floor(seconds % 3600 / 60);
141
+ const secs = seconds % 60;
142
+ if (hrs > 0) {
143
+ return `${hrs}h ${mins}m`;
144
+ } else if (mins > 0) {
145
+ return `${mins}m ${secs}s`;
146
+ } else {
147
+ return `${secs}s`;
148
+ }
149
+ };
150
+ return /* @__PURE__ */ React3.createElement(
151
+ Box3,
152
+ {
153
+ flexDirection: "column",
154
+ borderStyle: "round",
155
+ borderColor: "green",
156
+ padding: 1,
157
+ marginTop: 1
158
+ },
159
+ /* @__PURE__ */ React3.createElement(Box3, { justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "green" }, "\u{1F4CA} Execution Stats"), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, elapsedTime)),
160
+ /* @__PURE__ */ React3.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, flexDirection: "column", marginRight: 2 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Phases"), /* @__PURE__ */ React3.createElement(Box3, { alignItems: "center" }, /* @__PURE__ */ React3.createElement(Box3, { width: 30 }, /* @__PURE__ */ React3.createElement(Text3, null, Array.from({ length: 30 }, (_, i) => {
161
+ const fillPercent = i / 30 * 100;
162
+ return /* @__PURE__ */ React3.createElement(
163
+ Text3,
164
+ {
165
+ key: i,
166
+ backgroundColor: fillPercent <= progress ? "green" : void 0
167
+ },
168
+ fillPercent <= progress ? "\u2588" : "\u2591"
169
+ );
170
+ }))), /* @__PURE__ */ React3.createElement(Text3, null, " ", completedPhases, "/", totalPhases))), /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, flexDirection: "column", marginLeft: 2 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Time"), /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "cyan" }, elapsedTime, estimatedTimeRemaining && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " (remaining: ", estimatedTimeRemaining, ")")))),
171
+ /* @__PURE__ */ React3.createElement(Box3, { marginTop: 1, justifyContent: "space-between" }, /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Tokens: "), /* @__PURE__ */ React3.createElement(Text3, { bold: true }, tokens.toLocaleString())), /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Cost: "), /* @__PURE__ */ React3.createElement(Text3, { bold: true, color: "green" }, "$", cost)), budget && /* @__PURE__ */ React3.createElement(Box3, null, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Budget: "), /* @__PURE__ */ React3.createElement(
172
+ Text3,
173
+ {
174
+ bold: true,
175
+ color: budget.used / budget.limit > 0.8 ? "red" : budget.used / budget.limit > 0.6 ? "yellow" : "green"
176
+ },
177
+ "$",
178
+ budget.used.toFixed(2),
179
+ " / $",
180
+ budget.limit
181
+ ))),
182
+ budget && /* @__PURE__ */ React3.createElement(Box3, { marginTop: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "Budget Usage: "), /* @__PURE__ */ React3.createElement(Box3, { width: 40 }, /* @__PURE__ */ React3.createElement(Text3, null, Array.from({ length: 40 }, (_, i) => {
183
+ const fillPercent = i / 40 * (budget.used / budget.limit) * 100;
184
+ const color = budget.used / budget.limit > 0.8 ? "red" : budget.used / budget.limit > 0.6 ? "yellow" : "green";
185
+ return /* @__PURE__ */ React3.createElement(Text3, { key: i, backgroundColor: color }, fillPercent <= 100 ? "\u2588" : "\u2591");
186
+ }))), /* @__PURE__ */ React3.createElement(Text3, null, " ", Math.round(budget.used / budget.limit * 100), "%"))
187
+ );
188
+ };
189
+
190
+ // utils/pipeReader.ts
191
+ import { createInterface } from "readline";
192
+ var ActivityPipeReader = class {
193
+ pipePath;
194
+ listeners = [];
195
+ constructor(pipePath) {
196
+ this.pipePath = pipePath;
197
+ }
198
+ onMessage(listener) {
199
+ this.listeners.push(listener);
200
+ }
201
+ start() {
202
+ const rl = createInterface({
203
+ input: __require("fs").createReadStream(this.pipePath),
204
+ crlfDelay: Infinity
205
+ });
206
+ rl.on("line", (line) => {
207
+ if (!line.trim()) return;
208
+ try {
209
+ const msg = this.parseMessage(line);
210
+ if (msg) {
211
+ this.listeners.forEach((listener) => listener(msg));
212
+ }
213
+ } catch (error) {
214
+ console.error("Error parsing message:", error);
215
+ }
216
+ });
217
+ rl.on("error", (err) => {
218
+ if (err.code !== "ENOENT") {
219
+ console.error("Pipe reader error:", err);
220
+ }
221
+ });
222
+ }
223
+ parseMessage(line) {
224
+ const parts = line.split(":");
225
+ if (parts.length < 2) return null;
226
+ const prefix = parts[0];
227
+ switch (prefix) {
228
+ case "STAGE": {
229
+ const type = parts[1];
230
+ const detail = parts.slice(2).join(":");
231
+ return {
232
+ type: "stage",
233
+ stage: type,
234
+ detail,
235
+ timestamp: /* @__PURE__ */ new Date()
236
+ };
237
+ }
238
+ case "FILE": {
239
+ const op = parts[1];
240
+ const file = parts.slice(2).join(":");
241
+ return {
242
+ type: "file",
243
+ detail: `${op}: ${file}`,
244
+ timestamp: /* @__PURE__ */ new Date()
245
+ };
246
+ }
247
+ case "COMMIT": {
248
+ const message = parts.slice(1).join(":");
249
+ return {
250
+ type: "commit",
251
+ detail: message,
252
+ timestamp: /* @__PURE__ */ new Date()
253
+ };
254
+ }
255
+ case "TEST": {
256
+ return {
257
+ type: "test",
258
+ detail: "Running tests",
259
+ timestamp: /* @__PURE__ */ new Date()
260
+ };
261
+ }
262
+ case "INFO": {
263
+ const message = parts.slice(1).join(":");
264
+ return {
265
+ type: "info",
266
+ detail: message,
267
+ timestamp: /* @__PURE__ */ new Date()
268
+ };
269
+ }
270
+ case "ERROR": {
271
+ const message = parts.slice(1).join(":");
272
+ return {
273
+ type: "error",
274
+ detail: message,
275
+ timestamp: /* @__PURE__ */ new Date()
276
+ };
277
+ }
278
+ default:
279
+ return null;
280
+ }
281
+ }
282
+ };
283
+
284
+ // App.tsx
285
+ var App = () => {
286
+ const [activities, setActivities] = useState2([]);
287
+ const [currentStage, setCurrentStage] = useState2(null);
288
+ const [completedStages, setCompletedStages] = useState2([]);
289
+ const [currentPhase, setCurrentPhase] = useState2("1");
290
+ const [phaseName, setPhaseName] = useState2("Initializing...");
291
+ const [totalPhases] = useState2(3);
292
+ const [completedPhases, setCompletedPhases] = useState2(0);
293
+ const [startTime] = useState2(/* @__PURE__ */ new Date());
294
+ const [tokens, setTokens] = useState2(0);
295
+ const [cost, setCost] = useState2("0.00");
296
+ const [budget] = useState2(void 0);
297
+ useEffect2(() => {
298
+ const pipePath = process.env.GSD_ACTIVITY_PIPE || ".planning/logs/activity.pipe";
299
+ const reader = new ActivityPipeReader(pipePath);
300
+ reader.onMessage((msg) => {
301
+ setActivities((prev) => [...prev, msg]);
302
+ if (msg.type === "stage") {
303
+ const [stageType, ...descParts] = msg.detail.split(":");
304
+ const description = descParts.join(":");
305
+ if (currentStage && currentStage.stage !== stageType) {
306
+ setCompletedStages((prev) => [
307
+ ...prev,
308
+ { name: currentStage.stage, elapsed: currentStage.elapsed }
309
+ ]);
310
+ }
311
+ setCurrentStage({
312
+ stage: stageType,
313
+ stageDesc: description,
314
+ elapsed: "0:00"
315
+ });
316
+ }
317
+ if (msg.type === "file") {
318
+ }
319
+ if (msg.type === "commit") {
320
+ }
321
+ });
322
+ reader.start();
323
+ return () => {
324
+ };
325
+ }, []);
326
+ const elapsedTime = useMemo(() => {
327
+ const diff = Math.floor((Date.now() - startTime.getTime()) / 1e3);
328
+ const hrs = Math.floor(diff / 3600);
329
+ const mins = Math.floor(diff % 3600 / 60);
330
+ const secs = diff % 60;
331
+ if (hrs > 0) {
332
+ return `${hrs}h ${mins}m ${secs}s`;
333
+ } else if (mins > 0) {
334
+ return `${mins}m ${secs}s`;
335
+ } else {
336
+ return `${secs}s`;
337
+ }
338
+ }, [startTime]);
339
+ const stages = useMemo(() => {
340
+ const stages2 = [
341
+ ...completedStages.map((s) => ({ ...s, completed: true }))
342
+ ];
343
+ if (currentStage) {
344
+ stages2.push({
345
+ name: currentStage.stage,
346
+ elapsed: currentStage.elapsed,
347
+ completed: false
348
+ });
349
+ }
350
+ return stages2;
351
+ }, [completedStages, currentStage]);
352
+ const progress = useMemo(() => {
353
+ if (stages.length === 0) return 0;
354
+ const completed = stages.filter((s) => s.completed).length;
355
+ return completed / (stages.length + 3) * 100;
356
+ }, [stages]);
357
+ return /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", padding: 1 }, /* @__PURE__ */ React4.createElement(Box4, { justifyContent: "center", marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "cyan" }, "\u2554\u2550\u2550\u2550\u2557 \u2554\u2557 \u2554\u2557 \u2554\u2550\u2550\u2557 \u2551\u2554\u2550\u2550\u255D \u2551\u2551 \u2551\u2551 \u2551\u2554\u2557\u2551 \u2551\u255A\u2550\u2550\u2557 \u2551\u2551 \u2551\u2551 \u2551\u255A\u255D\u2551 \u2551\u2554\u2550\u2550\u255D \u2551\u2551 \u2551\u2551 \u2551\u2554\u2557\u2551 \u2551\u255A\u2550\u2550\u2557 \u2551\u255A\u2550\u2550\u2557\u2551\u255A\u2550\u2550\u2557 \u2551\u255A\u255D\u2551 \u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D")), /* @__PURE__ */ React4.createElement(Text4, { bold: true, color: "cyan" }, "GET SHIT DONE - AUTOPILOT"), /* @__PURE__ */ React4.createElement(Box4, { marginY: 1 }, /* @__PURE__ */ React4.createElement(Text4, { dimColor: true }, "\u2500".repeat(60))), /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "row", gap: 1, flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React4.createElement(
358
+ PhaseCard,
359
+ {
360
+ phase: currentPhase,
361
+ phaseName,
362
+ totalPhases,
363
+ currentPhaseIndex: completedPhases,
364
+ stages,
365
+ description: currentStage == null ? void 0 : currentStage.stageDesc,
366
+ progress
367
+ }
368
+ )), /* @__PURE__ */ React4.createElement(Box4, { flexDirection: "column", flexGrow: 1 }, /* @__PURE__ */ React4.createElement(ActivityFeed, { activities }))), /* @__PURE__ */ React4.createElement(
369
+ StatsBar,
370
+ {
371
+ totalPhases,
372
+ completedPhases,
373
+ elapsedTime,
374
+ tokens,
375
+ cost,
376
+ budget
377
+ }
378
+ ));
379
+ };
380
+ var App_default = App;
381
+
382
+ // index.tsx
383
+ var { waitUntilExit } = render(/* @__PURE__ */ React5.createElement(App_default, null));
384
+ waitUntilExit().then(() => {
385
+ console.log("TUI closed");
386
+ process.exit(0);
387
+ });
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ import React from 'react';
4
+ import { render } from 'ink';
5
+ import App from './App.js';
6
+
7
+ const { waitUntilExit } = render(<App />);
8
+
9
+ waitUntilExit().then(() => {
10
+ console.log('TUI closed');
11
+ process.exit(0);
12
+ });