@h-rig/cli 0.0.6-alpha.77 → 0.0.6-alpha.78

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.
@@ -0,0 +1,294 @@
1
+ // @bun
2
+ // packages/cli/src/app/drone-ui.ts
3
+ import { ProcessTerminal, TUI, Text, Input, SelectList, matchesKey } from "@earendil-works/pi-tui";
4
+
5
+ // packages/cli/src/app/theme.ts
6
+ var RIG_PALETTE = {
7
+ ink: "#f2f3f6",
8
+ ink2: "#aeb0ba",
9
+ ink3: "#6c6e79",
10
+ ink4: "#44464f",
11
+ accent: "#ccff4d",
12
+ accentDim: "#a9d63f",
13
+ cyan: "#56d8ff",
14
+ red: "#ff5d5d",
15
+ yellow: "#ffd24d"
16
+ };
17
+ function hexToRgb(hex) {
18
+ const value = hex.replace("#", "");
19
+ return [
20
+ Number.parseInt(value.slice(0, 2), 16),
21
+ Number.parseInt(value.slice(2, 4), 16),
22
+ Number.parseInt(value.slice(4, 6), 16)
23
+ ];
24
+ }
25
+ function fg(hex) {
26
+ const [r, g, b] = hexToRgb(hex);
27
+ return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
28
+ }
29
+ var ink = fg(RIG_PALETTE.ink);
30
+ var ink2 = fg(RIG_PALETTE.ink2);
31
+ var ink3 = fg(RIG_PALETTE.ink3);
32
+ var ink4 = fg(RIG_PALETTE.ink4);
33
+ var accent = fg(RIG_PALETTE.accent);
34
+ var accentDim = fg(RIG_PALETTE.accentDim);
35
+ var cyan = fg(RIG_PALETTE.cyan);
36
+ var red = fg(RIG_PALETTE.red);
37
+ var yellow = fg(RIG_PALETTE.yellow);
38
+ function bold(text) {
39
+ return `\x1B[1m${text}\x1B[22m`;
40
+ }
41
+ var DRONE_ART = [
42
+ " .-=-. .-=-. ",
43
+ " ( !!! ) ( !!! ) ",
44
+ " '-=-'._ _.'-=-' ",
45
+ " '._ _.' ",
46
+ " '=$$$$$$$=.' ",
47
+ " =$$$$$$$$$$$= ",
48
+ " $$$@@@@@@@@@@$$$ ",
49
+ " $$$@@ @@$$$ ",
50
+ " $$@ ? @$$$ ",
51
+ " $$$@ '-' @$$$ ",
52
+ " $$$@@ @@$$$ ",
53
+ " $$$@@@@@@@@@@$$$ ",
54
+ " =$$$$$$$$$$$= ",
55
+ " '=$$$$$$$=.' ",
56
+ " _.' '._ ",
57
+ " .-=-.' '.-=-. ",
58
+ " ( !!! ) ( !!! ) ",
59
+ " '-=-' '-=-' "
60
+ ];
61
+ var EYE_FRAMES = ["@", "o", "."];
62
+ var DRONE_WIDTH = DRONE_ART[0].length;
63
+ var DRONE_HEIGHT = DRONE_ART.length;
64
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
65
+ function microDroneFrame(tick) {
66
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
67
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
68
+ return `(${blade})${eye}(${blade})`;
69
+ }
70
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
71
+ function renderMicroDroneFrame(tick) {
72
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
73
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
74
+ return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
75
+ }
76
+
77
+ // packages/cli/src/commands/_spinner.ts
78
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
79
+ function createTtySpinner(input) {
80
+ const output = input.output ?? process.stdout;
81
+ const isTty = output.isTTY === true;
82
+ const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
83
+ let label = input.label;
84
+ let frame = 0;
85
+ let paused = false;
86
+ let stopped = false;
87
+ let lastPrintedLabel = "";
88
+ const render = () => {
89
+ if (stopped || paused)
90
+ return;
91
+ if (!isTty) {
92
+ if (label !== lastPrintedLabel) {
93
+ output.write(`${label}
94
+ `);
95
+ lastPrintedLabel = label;
96
+ }
97
+ return;
98
+ }
99
+ frame = (frame + 1) % frames.length;
100
+ const glyph = frames[frame] ?? frames[0] ?? "";
101
+ output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
102
+ };
103
+ const clearLine = () => {
104
+ if (isTty)
105
+ output.write("\r\x1B[2K");
106
+ };
107
+ render();
108
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
109
+ return {
110
+ setLabel(next) {
111
+ label = next;
112
+ render();
113
+ },
114
+ pause() {
115
+ paused = true;
116
+ clearLine();
117
+ },
118
+ resume() {
119
+ if (stopped)
120
+ return;
121
+ paused = false;
122
+ render();
123
+ },
124
+ stop(finalLine) {
125
+ if (stopped)
126
+ return;
127
+ stopped = true;
128
+ if (timer)
129
+ clearInterval(timer);
130
+ clearLine();
131
+ if (finalLine)
132
+ output.write(`${finalLine}
133
+ `);
134
+ }
135
+ };
136
+ }
137
+
138
+ // packages/cli/src/app/drone-ui.ts
139
+ var isTty = () => Boolean(process.stdout.isTTY);
140
+ function hairline(width = Math.min(process.stdout.columns ?? 80, 100)) {
141
+ return ink4("\u2500".repeat(Math.max(10, width)));
142
+ }
143
+ function droneIntro(title, subtitle) {
144
+ console.log("");
145
+ console.log(` ${accent("\u258D")}${bold(ink(title))}${subtitle ? ink3(` \u2014 ${subtitle}`) : ""}`);
146
+ console.log(hairline());
147
+ }
148
+ function droneOutro(text) {
149
+ console.log(hairline());
150
+ console.log(` ${accent("\u25C6")} ${ink2(text)}`);
151
+ console.log("");
152
+ }
153
+ function droneNote(message, title) {
154
+ if (title)
155
+ console.log(` ${accentDim("\u25C7")} ${bold(ink2(title))}`);
156
+ for (const line of message.split(`
157
+ `)) {
158
+ console.log(` ${ink4("\u2502")} ${line}`);
159
+ }
160
+ }
161
+ function droneStep(text) {
162
+ console.log(` ${accent("\u203A")} ${ink(text)}`);
163
+ }
164
+ function droneInfo(text) {
165
+ console.log(` ${cyan("\xB7")} ${ink2(text)}`);
166
+ }
167
+ function droneWarn(text) {
168
+ console.log(` ${yellow("\u25B2")} ${ink2(text)}`);
169
+ }
170
+ function droneError(text) {
171
+ console.log(` ${red("\u2716")} ${ink2(text)}`);
172
+ }
173
+ function droneCancel(text) {
174
+ console.log(` ${red("\u2716")} ${ink3(text)}`);
175
+ }
176
+ function droneSpinner() {
177
+ let active = null;
178
+ return {
179
+ start(message) {
180
+ active = createTtySpinner({
181
+ label: message,
182
+ frames: MICRO_DRONE_FRAMES,
183
+ styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
184
+ });
185
+ },
186
+ stop(message) {
187
+ active?.stop(message ? ` ${accent("\u25C6")} ${ink2(message)}` : undefined);
188
+ active = null;
189
+ },
190
+ error(message) {
191
+ active?.stop(message ? ` ${red("\u2716")} ${ink2(message)}` : undefined);
192
+ active = null;
193
+ }
194
+ };
195
+ }
196
+ var SELECT_THEME = {
197
+ selectedPrefix: (text) => accent(text),
198
+ selectedText: (text) => bold(ink(text)),
199
+ description: (text) => ink3(text),
200
+ scrollInfo: (text) => ink4(text),
201
+ noMatch: (text) => ink3(text)
202
+ };
203
+ async function runMiniTui(build) {
204
+ const terminal = new ProcessTerminal;
205
+ const tui = new TUI(terminal);
206
+ let settled = false;
207
+ return await new Promise((resolve) => {
208
+ const finish = (result) => {
209
+ if (settled)
210
+ return;
211
+ settled = true;
212
+ tui.stop();
213
+ resolve(result);
214
+ };
215
+ build(tui, finish);
216
+ tui.start();
217
+ });
218
+ }
219
+ async function droneSelect(input) {
220
+ if (!isTty() || input.options.length === 0) {
221
+ return input.initialValue ?? input.options[0]?.value ?? null;
222
+ }
223
+ return runMiniTui((tui, finish) => {
224
+ tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}`));
225
+ const items = input.options.map((option) => ({
226
+ value: option.value,
227
+ label: option.label,
228
+ ...option.hint ? { description: option.hint } : {}
229
+ }));
230
+ const list = new SelectList(items, Math.min(items.length, 12), SELECT_THEME);
231
+ const initialIndex = input.initialValue ? items.findIndex((item) => item.value === input.initialValue) : -1;
232
+ if (initialIndex > 0)
233
+ list.setSelectedIndex(initialIndex);
234
+ list.onSelect = (item) => finish(item.value);
235
+ list.onCancel = () => finish(null);
236
+ tui.addChild(list);
237
+ tui.addChild(new Text(ink4(" \u2191\u2193 navigate \xB7 enter select \xB7 esc cancel")));
238
+ tui.setFocus(list);
239
+ tui.addInputListener((data) => {
240
+ if (matchesKey(data, "ctrl+c") || matchesKey(data, "escape")) {
241
+ finish(null);
242
+ return { consume: true };
243
+ }
244
+ return;
245
+ });
246
+ });
247
+ }
248
+ async function droneText(input) {
249
+ if (!isTty())
250
+ return input.initialValue ?? null;
251
+ return runMiniTui((tui, finish) => {
252
+ tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}${input.placeholder ? ink4(` (${input.placeholder})`) : ""}`));
253
+ const field = new Input;
254
+ if (input.initialValue)
255
+ field.setValue(input.initialValue);
256
+ field.onSubmit = (value) => finish(value);
257
+ field.onEscape = () => finish(null);
258
+ tui.addChild(field);
259
+ tui.addChild(new Text(ink4(" enter submit \xB7 esc cancel")));
260
+ tui.setFocus(field);
261
+ tui.addInputListener((data) => {
262
+ if (matchesKey(data, "ctrl+c")) {
263
+ finish(null);
264
+ return { consume: true };
265
+ }
266
+ return;
267
+ });
268
+ });
269
+ }
270
+ async function droneConfirm(input) {
271
+ const answer = await droneSelect({
272
+ message: input.message,
273
+ options: [
274
+ { value: "yes", label: "Yes" },
275
+ { value: "no", label: "No" }
276
+ ],
277
+ initialValue: input.initialValue === false ? "no" : "yes"
278
+ });
279
+ return answer === null ? null : answer === "yes";
280
+ }
281
+ export {
282
+ droneWarn,
283
+ droneText,
284
+ droneStep,
285
+ droneSpinner,
286
+ droneSelect,
287
+ droneOutro,
288
+ droneNote,
289
+ droneIntro,
290
+ droneInfo,
291
+ droneError,
292
+ droneConfirm,
293
+ droneCancel
294
+ };
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- // packages/cli/src/commands/_tui-theme.ts
2
+ // packages/cli/src/app/theme.ts
3
3
  var RIG_PALETTE = {
4
4
  ink: "#f2f3f6",
5
5
  ink2: "#aeb0ba",
@@ -114,11 +114,25 @@ function renderDroneFrame(tick) {
114
114
  }
115
115
  var DRONE_WIDTH = DRONE_ART[0].length;
116
116
  var DRONE_HEIGHT = DRONE_ART.length;
117
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
118
+ function microDroneFrame(tick) {
119
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
120
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
121
+ return `(${blade})${eye}(${blade})`;
122
+ }
123
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
124
+ function renderMicroDroneFrame(tick) {
125
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
126
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
127
+ return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
128
+ }
117
129
  export {
118
130
  yellow,
119
131
  statusColor,
132
+ renderMicroDroneFrame,
120
133
  renderDroneFrame,
121
134
  red,
135
+ microDroneFrame,
122
136
  ink4,
123
137
  ink3,
124
138
  ink2,
@@ -130,6 +144,7 @@ export {
130
144
  accent,
131
145
  RIG_SPINNER_FRAMES,
132
146
  RIG_PALETTE,
147
+ MICRO_DRONE_FRAMES,
133
148
  DRONE_WIDTH,
134
149
  DRONE_HEIGHT
135
150
  };
@@ -91,8 +91,79 @@ var RESUMABLE_RUN_STATUSES = new Set([
91
91
  "needs_attention"
92
92
  ]);
93
93
 
94
+ // packages/cli/src/app/theme.ts
95
+ var RIG_PALETTE = {
96
+ ink: "#f2f3f6",
97
+ ink2: "#aeb0ba",
98
+ ink3: "#6c6e79",
99
+ ink4: "#44464f",
100
+ accent: "#ccff4d",
101
+ accentDim: "#a9d63f",
102
+ cyan: "#56d8ff",
103
+ red: "#ff5d5d",
104
+ yellow: "#ffd24d"
105
+ };
106
+ function hexToRgb(hex) {
107
+ const value = hex.replace("#", "");
108
+ return [
109
+ Number.parseInt(value.slice(0, 2), 16),
110
+ Number.parseInt(value.slice(2, 4), 16),
111
+ Number.parseInt(value.slice(4, 6), 16)
112
+ ];
113
+ }
114
+ function fg(hex) {
115
+ const [r, g, b] = hexToRgb(hex);
116
+ return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
117
+ }
118
+ var ink = fg(RIG_PALETTE.ink);
119
+ var ink2 = fg(RIG_PALETTE.ink2);
120
+ var ink3 = fg(RIG_PALETTE.ink3);
121
+ var ink4 = fg(RIG_PALETTE.ink4);
122
+ var accent = fg(RIG_PALETTE.accent);
123
+ var accentDim = fg(RIG_PALETTE.accentDim);
124
+ var cyan = fg(RIG_PALETTE.cyan);
125
+ var red = fg(RIG_PALETTE.red);
126
+ var yellow = fg(RIG_PALETTE.yellow);
127
+ function bold(text) {
128
+ return `\x1B[1m${text}\x1B[22m`;
129
+ }
130
+ var DRONE_ART = [
131
+ " .-=-. .-=-. ",
132
+ " ( !!! ) ( !!! ) ",
133
+ " '-=-'._ _.'-=-' ",
134
+ " '._ _.' ",
135
+ " '=$$$$$$$=.' ",
136
+ " =$$$$$$$$$$$= ",
137
+ " $$$@@@@@@@@@@$$$ ",
138
+ " $$$@@ @@$$$ ",
139
+ " $$@ ? @$$$ ",
140
+ " $$$@ '-' @$$$ ",
141
+ " $$$@@ @@$$$ ",
142
+ " $$$@@@@@@@@@@$$$ ",
143
+ " =$$$$$$$$$$$= ",
144
+ " '=$$$$$$$=.' ",
145
+ " _.' '._ ",
146
+ " .-=-.' '.-=-. ",
147
+ " ( !!! ) ( !!! ) ",
148
+ " '-=-' '-=-' "
149
+ ];
150
+ var EYE_FRAMES = ["@", "o", "."];
151
+ var DRONE_WIDTH = DRONE_ART[0].length;
152
+ var DRONE_HEIGHT = DRONE_ART.length;
153
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
154
+ function microDroneFrame(tick) {
155
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
156
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
157
+ return `(${blade})${eye}(${blade})`;
158
+ }
159
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
160
+ function renderMicroDroneFrame(tick) {
161
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
162
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
163
+ return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
164
+ }
165
+
94
166
  // packages/cli/src/commands/_async-ui.ts
95
- var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
96
167
  var DONE_SYMBOL = pc.green("\u25C7");
97
168
  var FAIL_SYMBOL = pc.red("\u25A0");
98
169
  var activeUpdate = null;
@@ -126,8 +197,8 @@ async function withSpinner(label, work, options = {}) {
126
197
  const spinner = createTtySpinner({
127
198
  label,
128
199
  output,
129
- frames: CLACK_SPINNER_FRAMES,
130
- styleFrame: (frame) => pc.magenta(frame)
200
+ frames: MICRO_DRONE_FRAMES,
201
+ styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
131
202
  });
132
203
  const update = (next) => {
133
204
  lastLabel = next;
@@ -1,9 +1,8 @@
1
1
  // @bun
2
- // packages/cli/src/commands/_cli-format.ts
3
- import { log, note } from "@clack/prompts";
4
- import pc from "picocolors";
2
+ // packages/cli/src/app/drone-ui.ts
3
+ import { ProcessTerminal, TUI, Text, Input, SelectList, matchesKey } from "@earendil-works/pi-tui";
5
4
 
6
- // packages/cli/src/commands/_tui-theme.ts
5
+ // packages/cli/src/app/theme.ts
7
6
  var RIG_PALETTE = {
8
7
  ink: "#f2f3f6",
9
8
  ink2: "#aeb0ba",
@@ -36,6 +35,9 @@ var accentDim = fg(RIG_PALETTE.accentDim);
36
35
  var cyan = fg(RIG_PALETTE.cyan);
37
36
  var red = fg(RIG_PALETTE.red);
38
37
  var yellow = fg(RIG_PALETTE.yellow);
38
+ function bold(text) {
39
+ return `\x1B[1m${text}\x1B[22m`;
40
+ }
39
41
  var DRONE_ART = [
40
42
  " .-=-. .-=-. ",
41
43
  " ( !!! ) ( !!! ) ",
@@ -56,10 +58,29 @@ var DRONE_ART = [
56
58
  " ( !!! ) ( !!! ) ",
57
59
  " '-=-' '-=-' "
58
60
  ];
61
+ var EYE_FRAMES = ["@", "o", "."];
59
62
  var DRONE_WIDTH = DRONE_ART[0].length;
60
63
  var DRONE_HEIGHT = DRONE_ART.length;
64
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
65
+ function microDroneFrame(tick) {
66
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
67
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
68
+ return `(${blade})${eye}(${blade})`;
69
+ }
70
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
71
+
72
+ // packages/cli/src/app/drone-ui.ts
73
+ function droneNote(message, title) {
74
+ if (title)
75
+ console.log(` ${accentDim("\u25C7")} ${bold(ink2(title))}`);
76
+ for (const line of message.split(`
77
+ `)) {
78
+ console.log(` ${ink4("\u2502")} ${line}`);
79
+ }
80
+ }
61
81
 
62
82
  // packages/cli/src/commands/_cli-format.ts
83
+ import pc from "picocolors";
63
84
  var themeDim = (value) => ink3(value);
64
85
  var themeFaint = (value) => ink4(value);
65
86
  function stringField(record, key, fallback = "") {
@@ -147,10 +168,7 @@ function printFormattedOutput(message, options = {}) {
147
168
  console.log(message);
148
169
  return;
149
170
  }
150
- if (options.title)
151
- note(message, options.title);
152
- else
153
- log.message(message);
171
+ droneNote(message, options.title);
154
172
  }
155
173
  function formatStatusPill(status) {
156
174
  const label = status || "unknown";
@@ -311,7 +311,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
311
311
  })() : null;
312
312
  if (!response.ok) {
313
313
  const diagnostics = diagnosticMessage(payload);
314
- const detail = diagnostics ?? (text || response.statusText);
314
+ const rawDetail = diagnostics ?? (text || response.statusText);
315
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
316
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
315
317
  const failure = await buildServerFailureContext(context.projectRoot, server);
316
318
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
317
319
  ${failure.contextLine}`, 1, { hint: failure.hint });
@@ -1,7 +1,9 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/_help-catalog.ts
3
- import { intro, log, note, outro } from "@clack/prompts";
4
3
  import pc from "picocolors";
4
+ function helpCatalog() {
5
+ return { sections: TOP_LEVEL_SECTIONS, groups: ALL_GROUPS };
6
+ }
5
7
  var TOP_LEVEL_SECTIONS = [
6
8
  {
7
9
  title: "Pi console",
@@ -416,79 +418,14 @@ function suggestGroupCommandForWord(word) {
416
418
  }
417
419
  return null;
418
420
  }
419
- function shouldUseClackOutput() {
420
- return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
421
- }
422
421
  function printTopLevelHelp(state = {}) {
423
- if (!shouldUseClackOutput()) {
424
- console.log(renderTopLevelHelp());
425
- return;
426
- }
427
- console.log(renderRigBanner(state.version));
428
- console.log("");
429
- if (state.projectInitialized === false) {
430
- intro("no rig project in this directory");
431
- note([
432
- commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
433
- commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
434
- commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
435
- ].join(`
436
- `), "Get started");
437
- outro("After init: rig task run --next puts an agent on your next task.");
438
- return;
439
- }
440
- intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
441
- for (const section of TOP_LEVEL_SECTIONS) {
442
- note(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
443
- }
444
- log.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
445
- note([
446
- commandLine("--project <path>", "Use a project root instead of auto-discovery."),
447
- commandLine("--json", "Emit structured output for scripts/agents."),
448
- commandLine("--dry-run", "Print the command plan without mutating state.")
449
- ].join(`
450
- `), "Global options");
451
- outro("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
422
+ console.log(renderTopLevelHelp());
452
423
  }
453
424
  function printAdvancedHelp() {
454
- if (!shouldUseClackOutput()) {
455
- console.log(renderAdvancedHelp());
456
- return;
457
- }
458
- intro("rig advanced");
459
- note(ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)).join(`
460
- `), "Advanced commands");
461
- note(ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)).join(`
462
- `), "Advanced groups");
463
- outro("Primary daily flow: rig server \xB7 rig task \xB7 rig run \xB7 rig inbox.");
425
+ console.log(renderAdvancedHelp());
464
426
  }
465
427
  function printGroupHelpDocument(groupName) {
466
- const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
467
- if (!shouldUseClackOutput()) {
468
- console.log(rendered);
469
- return;
470
- }
471
- const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
472
- if (!group) {
473
- printTopLevelHelp();
474
- return;
475
- }
476
- intro(`rig ${group.name}`);
477
- note(group.summary, "Purpose");
478
- note(group.usage.join(`
479
- `), "Usage");
480
- note(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
481
- `), "Commands");
482
- if (group.examples?.length)
483
- note(group.examples.map((line) => `$ ${line}`).join(`
484
- `), "Examples");
485
- if (group.next?.length)
486
- note(group.next.map((line) => `\u203A ${line}`).join(`
487
- `), "Next steps");
488
- if (group.advanced?.length)
489
- log.info(group.advanced.join(`
490
- `));
491
- outro("Run with --json when scripts need structured output.");
428
+ console.log(renderGroupHelp(groupName) ?? renderTopLevelHelp());
492
429
  }
493
430
  export {
494
431
  suggestGroupCommandForWord,
@@ -499,5 +436,6 @@ export {
499
436
  printTopLevelHelp,
500
437
  printGroupHelpDocument,
501
438
  printAdvancedHelp,
502
- listHelpGroups
439
+ listHelpGroups,
440
+ helpCatalog
503
441
  };