@wrongstack/cli 0.317.2 → 0.319.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 (33) hide show
  1. package/data/providers.json +1 -22
  2. package/dist/{acp-CEQINXWB.js → acp-5ANIAOZC.js} +4 -4
  3. package/dist/arg-parser.d.ts +4 -0
  4. package/dist/{auth-3OSF6BMU.js → auth-KF5TAD7V.js} +10 -10
  5. package/dist/{chunk-GKHUHAIK.js → chunk-42JD25KU.js} +5 -5
  6. package/dist/{chunk-QYIIOMLE.js → chunk-E4I2TF5S.js} +2 -2
  7. package/dist/{chunk-37SPPLUD.js → chunk-F5GA2QW2.js} +15 -2
  8. package/dist/chunk-GGGUZSAU.js +235 -0
  9. package/dist/{chunk-QC5I4VWZ.js → chunk-H7GABTGS.js} +6 -2
  10. package/dist/chunk-OZDE3OWD.js +52 -0
  11. package/dist/chunk-P2OKBDCH.js +1166 -0
  12. package/dist/chunk-PCBJSXYV.js +65 -0
  13. package/dist/{chunk-KG4X5F7Z.js → chunk-VFCJOWJB.js} +10 -12
  14. package/dist/chunk-VWCZL4OH.js +46 -0
  15. package/dist/{chunk-YX6KUIDF.js → chunk-XHIEA6LG.js} +861 -29
  16. package/dist/{chunk-BXFYBQKR.js → chunk-XPX432BZ.js} +8 -1
  17. package/dist/cli-context-LH4QP4W2.js +3369 -0
  18. package/dist/{cli-main-ILRTNPDP.js → cli-main-72XUFUCL.js} +50 -44
  19. package/dist/{execution-BN4QIFH6.js → execution-DKJDNPYF.js} +17 -17
  20. package/dist/index.js +20 -4440
  21. package/dist/{modeldiag-4NYBRSFP.js → modeldiag-5FRMT6FQ.js} +2 -2
  22. package/dist/per-subcommand-help-6VCIKDUW.js +23 -0
  23. package/dist/{plugin-usage-AP7SJCDA.js → plugin-usage-CYUORYM6.js} +2 -2
  24. package/dist/{plugins-HQ5FU2AM.js → plugins-RV3OBBND.js} +3 -3
  25. package/dist/pre-launch/first-run.d.ts +51 -0
  26. package/dist/pre-launch.d.ts +1 -0
  27. package/dist/{providers-models-663NDPRQ.js → providers-models-OKKQZIWU.js} +2 -2
  28. package/dist/{sessions-config-P2LK2L32.js → sessions-config-KAMEBVOX.js} +4 -4
  29. package/dist/short-circuit-flags-U6CJAF6J.js +11 -0
  30. package/dist/subcommands-J4JMWC5W.js +10 -0
  31. package/dist/{webui-server-OJLLM6PE.js → webui-server-SY4EQCKD.js} +5 -5
  32. package/package.json +28 -28
  33. package/dist/chunk-L6ZNCTRJ.js +0 -1067
@@ -0,0 +1,1166 @@
1
+ import {
2
+ renderAuthLocalHelpToString
3
+ } from "./chunk-2VMJ3E5Z.js";
4
+
5
+ // src/subcommands/handlers/per-subcommand-help.ts
6
+ import { color as color3 } from "@wrongstack/core/utils";
7
+
8
+ // src/subcommands/handlers/bench-run-help.ts
9
+ import { color } from "@wrongstack/core/utils";
10
+ var BENCH_RUN_FLAGS = [
11
+ // -- Suite selection ------------------------------------------------
12
+ {
13
+ name: "suite",
14
+ flag: "--suite <id>",
15
+ description: "Benchmark suite id (`polyglot` or `swebench`).",
16
+ group: "suite",
17
+ kind: "value",
18
+ defaultValue: "polyglot"
19
+ },
20
+ {
21
+ name: "polyglot-dir",
22
+ flag: "--polyglot-dir <path>",
23
+ description: "Path to the Aider polyglot dataset (required when --suite polyglot).",
24
+ group: "suite",
25
+ kind: "value",
26
+ required: true
27
+ },
28
+ {
29
+ name: "languages",
30
+ flag: "--languages <csv>",
31
+ description: "Comma-separated language list to filter the polyglot suite (e.g. `python,go`).",
32
+ group: "suite",
33
+ kind: "value"
34
+ },
35
+ {
36
+ name: "dataset-dir",
37
+ flag: "--dataset-dir <path>",
38
+ description: "Path to the SWE-bench Verified dataset (optional, defaults to the official cache).",
39
+ group: "suite",
40
+ kind: "value"
41
+ },
42
+ {
43
+ name: "docker",
44
+ flag: "--docker",
45
+ description: "Enable the SWE-bench Docker runtime (required for live grading).",
46
+ group: "suite",
47
+ kind: "boolean"
48
+ },
49
+ // -- Model matrix ---------------------------------------------------
50
+ {
51
+ name: "models",
52
+ flag: "--models <config>",
53
+ description: "Path to the model-cells config (JSON).",
54
+ group: "models",
55
+ kind: "value",
56
+ defaultValue: "bench.config.json"
57
+ },
58
+ // -- Run control ----------------------------------------------------
59
+ {
60
+ name: "limit",
61
+ flag: "--limit <N>",
62
+ description: "Cap the number of tasks per cell (useful for smoke tests).",
63
+ group: "control",
64
+ kind: "value"
65
+ },
66
+ {
67
+ name: "out",
68
+ flag: "--out <dir>",
69
+ description: "Base directory for run output (each run gets a timestamped subdir).",
70
+ group: "control",
71
+ kind: "value",
72
+ defaultValue: "bench-results"
73
+ },
74
+ {
75
+ name: "concurrency",
76
+ flag: "--concurrency <N>",
77
+ description: "Override the per-cell concurrency from the model config.",
78
+ group: "control",
79
+ kind: "value"
80
+ }
81
+ ];
82
+ var BENCH_RUN_BOOLEAN_FLAG_NAMES = BENCH_RUN_FLAGS.filter(
83
+ (f) => f.kind === "boolean"
84
+ ).map((f) => f.name);
85
+ var BENCH_RUN_VALUE_FLAG_NAMES = BENCH_RUN_FLAGS.filter(
86
+ (f) => f.kind === "value"
87
+ ).map((f) => f.name);
88
+ var BENCH_RUN_FLAG_COLUMN_WIDTH = 28;
89
+ function renderBenchRunHelpToString() {
90
+ const lines = [
91
+ color.bold("wstack bench run \u2014 execute a benchmark suite across a model matrix"),
92
+ color.dim(" Runs a benchmark suite (polyglot or swebench) across every model cell"),
93
+ color.dim(" in the config. Output is a per-run directory with `report.md`, JSON"),
94
+ color.dim(" artifacts, and (for swebench) per-cell predictions for the official"),
95
+ color.dim(" harness."),
96
+ "",
97
+ color.bold("Usage"),
98
+ ` ${buildUsageLine()}`,
99
+ "",
100
+ color.bold("Flags"),
101
+ ...buildFlagBlock(),
102
+ "",
103
+ color.dim(
104
+ "See also: wstack bench list (show available suites + cells); wstack bench report <dir>"
105
+ )
106
+ ];
107
+ return lines.join("\n") + "\n";
108
+ }
109
+ function buildUsageLine() {
110
+ const parts = ["wstack bench run"];
111
+ for (const f of BENCH_RUN_FLAGS) {
112
+ if (f.kind === "value") {
113
+ parts.push(`[${f.flag}]`);
114
+ } else {
115
+ parts.push(`[${f.flag}]`);
116
+ }
117
+ }
118
+ return parts.join(" ");
119
+ }
120
+ function buildFlagBlock() {
121
+ const rows = [];
122
+ let currentGroup;
123
+ for (const f of BENCH_RUN_FLAGS) {
124
+ if (f.group !== currentGroup) {
125
+ const header = f.group === "suite" ? "Suite selection:" : f.group === "models" ? "Model matrix:" : "Run control:";
126
+ rows.push(color.dim(` ${header}`));
127
+ currentGroup = f.group;
128
+ }
129
+ const paddedFlag = f.flag.padEnd(BENCH_RUN_FLAG_COLUMN_WIDTH, " ");
130
+ let desc = f.description;
131
+ if (f.required) {
132
+ desc = desc + " " + color.bold("(required)");
133
+ } else if (f.defaultValue !== void 0) {
134
+ desc = desc + " " + color.dim(`(default: ${f.defaultValue})`);
135
+ }
136
+ rows.push(` ${paddedFlag} ${desc}`);
137
+ }
138
+ return rows;
139
+ }
140
+
141
+ // src/subcommands/handlers/models-add-help.ts
142
+ import { color as color2 } from "@wrongstack/core/utils";
143
+ var MODELS_ADD_FLAGS = [
144
+ // -- Identity --------------------------------------------------------
145
+ {
146
+ name: "provider",
147
+ flag: "--provider <id>",
148
+ description: "Provider id the model belongs to (defaults to the saved alias).",
149
+ group: "identity",
150
+ kind: "value"
151
+ },
152
+ {
153
+ name: "name",
154
+ flag: "--name <name>",
155
+ description: "Human-readable display name (defaults to <mid>).",
156
+ group: "identity",
157
+ kind: "value"
158
+ },
159
+ // -- Capabilities ---------------------------------------------------
160
+ {
161
+ name: "max-context",
162
+ flag: "--max-context <N>",
163
+ description: "Context window in tokens (e.g. 200000 for 200k, or `128k`).",
164
+ group: "capabilities",
165
+ kind: "value"
166
+ },
167
+ {
168
+ name: "max-output",
169
+ flag: "--max-output <N>",
170
+ description: "Max output tokens per request.",
171
+ group: "capabilities",
172
+ kind: "value"
173
+ },
174
+ {
175
+ name: "tools",
176
+ flag: "--tools / --no-tools",
177
+ description: "Toggle tool/function-calling support.",
178
+ group: "capabilities",
179
+ kind: "boolean"
180
+ },
181
+ {
182
+ name: "vision",
183
+ flag: "--vision / --no-vision",
184
+ description: "Toggle image-input support.",
185
+ group: "capabilities",
186
+ kind: "boolean"
187
+ },
188
+ {
189
+ name: "reasoning",
190
+ flag: "--reasoning / --no-reasoning",
191
+ description: "Mark the model as a reasoning model.",
192
+ group: "capabilities",
193
+ kind: "boolean"
194
+ },
195
+ {
196
+ name: "streaming",
197
+ flag: "--streaming / --no-streaming",
198
+ description: "Toggle streaming response support.",
199
+ group: "capabilities",
200
+ kind: "boolean"
201
+ },
202
+ {
203
+ name: "json-mode",
204
+ flag: "--json-mode",
205
+ description: "Mark the model as supporting native JSON output.",
206
+ group: "capabilities",
207
+ kind: "boolean"
208
+ }
209
+ ];
210
+ var MODELS_ADD_BOOLEAN_FLAG_NAMES = MODELS_ADD_FLAGS.filter(
211
+ (f) => f.kind === "boolean"
212
+ ).map((f) => f.name);
213
+ var MODELS_ADD_VALUE_FLAG_NAMES = MODELS_ADD_FLAGS.filter(
214
+ (f) => f.kind === "value"
215
+ ).map((f) => f.name);
216
+ var MODELS_ADD_FLAG_COLUMN_WIDTH = 30;
217
+ function renderModelsAddHelpToString() {
218
+ const lines = [
219
+ color2.bold("wstack models add <mid> \u2014 register a custom model"),
220
+ color2.dim(" Add or override a custom model (for self-hosted endpoints, fine-tuned"),
221
+ color2.dim(" weights, or models not in the public models.dev catalog). The flags are"),
222
+ color2.dim(" organized into two groups: identity (`--provider`, `--name`) and"),
223
+ color2.dim(" capabilities (`--max-context`, `--tools`, `--vision`, etc.)."),
224
+ "",
225
+ color2.bold("Usage"),
226
+ ` ${buildUsageLine2()}`,
227
+ "",
228
+ color2.bold("Flags"),
229
+ ...buildFlagBlock2(),
230
+ "",
231
+ color2.dim("See also: wstack models list (verify the entry); wstack models remove")
232
+ ];
233
+ return lines.join("\n") + "\n";
234
+ }
235
+ function buildUsageLine2() {
236
+ const parts = ["wstack models add <mid>"];
237
+ for (const f of MODELS_ADD_FLAGS) {
238
+ if (f.kind === "value") {
239
+ parts.push(`[${f.flag}]`);
240
+ } else {
241
+ parts.push(`[${f.flag}]`);
242
+ }
243
+ }
244
+ return parts.join(" ");
245
+ }
246
+ function buildFlagBlock2() {
247
+ const rows = [];
248
+ let currentGroup;
249
+ for (const f of MODELS_ADD_FLAGS) {
250
+ if (f.group !== currentGroup) {
251
+ const header = f.group === "identity" ? "Identity:" : "Capabilities:";
252
+ rows.push(color2.dim(` ${header}`));
253
+ currentGroup = f.group;
254
+ }
255
+ const paddedFlag = f.flag.padEnd(MODELS_ADD_FLAG_COLUMN_WIDTH, " ");
256
+ rows.push(` ${paddedFlag} ${f.description}`);
257
+ }
258
+ return rows;
259
+ }
260
+
261
+ // src/subcommands/handlers/per-subcommand-deep-help-table.ts
262
+ var deepHelpTable = {
263
+ // -- mcp -----------------------------------------------------------------
264
+ "mcp:add": {
265
+ name: "mcp:add",
266
+ title: "wstack mcp add <name> \u2014 register a built-in MCP server",
267
+ description: "Register a built-in MCP server by alias (e.g. `github`, `playwright`) and write the entry to the global config. The server is added in `disabled` state by default; pass `--enable` to register it active immediately.",
268
+ usage: "wstack mcp add <name> [--enable]",
269
+ subcommands: [
270
+ {
271
+ name: "<name>",
272
+ description: "The built-in server alias (run `wstack mcp add` for the list)."
273
+ },
274
+ {
275
+ name: "--enable / -e",
276
+ description: "Register the server enabled (default: disabled until you opt in)."
277
+ }
278
+ ],
279
+ seeAlso: "wstack mcp list (verify the entry landed); wstack mcp remove"
280
+ },
281
+ "mcp:remove": {
282
+ name: "mcp:remove",
283
+ title: "wstack mcp remove <name> \u2014 unregister an MCP server",
284
+ description: "Unregister an MCP server by alias. Removes the entry from the global config; the server process is not killed (REPL restart required to fully tear down the running process).",
285
+ usage: "wstack mcp remove <name>",
286
+ subcommands: [{ name: "<name>", description: "The server alias to unregister." }]
287
+ },
288
+ // -- plugin --------------------------------------------------------------
289
+ "plugin:add": {
290
+ name: "plugin:add",
291
+ title: "wstack plugin add <spec> \u2014 install a tool plugin",
292
+ description: "Add a tool plugin by specifier (npm package name) or official alias (`telegram`, `lsp`). Pass `--disabled` to install the plugin but leave it off until you explicitly enable it. The plugin requires a restart of the wrongstack process to take effect.",
293
+ usage: "wstack plugin add <spec|alias> [--disabled]",
294
+ subcommands: [
295
+ {
296
+ name: "<spec|alias>",
297
+ description: "NPM specifier (e.g. `@org/wrongstack-x`) or official alias."
298
+ },
299
+ {
300
+ name: "--disabled",
301
+ description: "Install the plugin but leave it disabled until you enable it."
302
+ }
303
+ ],
304
+ seeAlso: "wstack plugin official (list the official registry); wstack plugin enable"
305
+ },
306
+ "plugin:remove": {
307
+ name: "plugin:remove",
308
+ title: "wstack plugin remove <spec> \u2014 uninstall a tool plugin",
309
+ description: "Remove a tool plugin from the config. The plugin requires a restart of the wrongstack process to take effect. Aliases: `rm`, `uninstall`.",
310
+ usage: "wstack plugin remove <spec|alias>",
311
+ subcommands: [
312
+ { name: "<spec|alias>", description: "The specifier or official alias to remove." }
313
+ ]
314
+ },
315
+ "plugin:enable": {
316
+ name: "plugin:enable",
317
+ title: "wstack plugin enable <spec> \u2014 re-enable a previously-disabled plugin",
318
+ description: "Re-enable a plugin that was installed with `--disabled` or toggled off with `wstack plugin disable`. Requires a restart.",
319
+ usage: "wstack plugin enable <spec|alias>",
320
+ subcommands: [
321
+ { name: "<spec|alias>", description: "The specifier or official alias to enable." }
322
+ ]
323
+ },
324
+ "plugin:disable": {
325
+ name: "plugin:disable",
326
+ title: "wstack plugin disable <spec> \u2014 temporarily disable a plugin",
327
+ description: "Temporarily disable a plugin without removing it from the config. Use `wstack plugin enable` to re-enable. Requires a restart.",
328
+ usage: "wstack plugin disable <spec|alias>",
329
+ subcommands: [
330
+ { name: "<spec|alias>", description: "The specifier or official alias to disable." }
331
+ ]
332
+ },
333
+ "plugin:toggle": {
334
+ name: "plugin:toggle",
335
+ title: "wstack plugin toggle <name> \u2014 toggle an audit-list plugin row",
336
+ description: "Toggle one built-in audit-list plugin by its runtime name. Default-active plugins are disabled by writing `{ enabled: false }` overrides; enabling them again removes that override. All bundled audit-list rows are toggleable; future non-toggleable rows are reported as locked. Requires a restart for loaded plugin code to change in the current session.",
337
+ usage: "wstack plugin toggle <name>",
338
+ subcommands: [
339
+ { name: "<name>", description: "Audit-list runtime name, e.g. `format-on-save`." }
340
+ ],
341
+ seeAlso: "wstack plugin report (see effective state and toggle policy)"
342
+ },
343
+ "plugin:report": {
344
+ name: "plugin:report",
345
+ title: "wstack plugin report \u2014 show the plugin audit table",
346
+ description: "Print the built-in plugin audit table. Each row shows effective state, whether that state came from config or default boot behavior, risk, and the toggle policy for that row.",
347
+ usage: "wstack plugin report (alias: wstack plugin audit)",
348
+ seeAlso: "wstack plugin toggle <name> (toggle audit-list rows); wstack plugin list"
349
+ },
350
+ "plugin:menu": {
351
+ name: "plugin:menu",
352
+ title: "wstack plugin menu \u2014 open or describe the plugin picker",
353
+ description: "In the TUI, `/plugin menu` opens the interactive plugin picker. From the non-interactive `wstack plugin menu` surface, the command prints the same audit report as `wstack plugin report`.",
354
+ usage: "wstack plugin menu",
355
+ seeAlso: "/plugin menu (interactive picker in the TUI); wstack plugin report"
356
+ },
357
+ // -- models --------------------------------------------------------------
358
+ // The `models:add` deep entry delegates its body to
359
+ // `models-add-help.ts` via the `customBody` field. The flag
360
+ // list lives in exactly one place (`MODELS_ADD_FLAGS`), and
361
+ // every surface that renders the help — `wstack models add --help`,
362
+ // `/models add help`, `/help models add` — produces the same
363
+ // string. The `title` / `description` / `usage` / `seeAlso`
364
+ // fields below are required by the `PerSubcommandHelp` shape
365
+ // but never rendered (the `customBody` thunk owns the full
366
+ // layout). They're filled in with sensible defaults so a
367
+ // future refactor that drops `customBody` (e.g. to use the
368
+ // standard layout) still has a coherent fallback.
369
+ "models:add": {
370
+ name: "models:add",
371
+ title: "wstack models add <mid> \u2014 register a custom model",
372
+ description: "See renderModelsAddHelpToString() in models-add-help.ts for the full block.",
373
+ usage: "wstack models add <mid> [...flags]",
374
+ customBody: renderModelsAddHelpToString
375
+ },
376
+ "models:remove": {
377
+ name: "models:remove",
378
+ title: "wstack models remove <mid> \u2014 unregister a custom model",
379
+ description: "Remove a custom model from the config. The catalog is unaffected (catalog models are managed by `wstack models refresh`).",
380
+ usage: "wstack models remove <mid>",
381
+ subcommands: [{ name: "<mid>", description: "The model id to remove." }]
382
+ },
383
+ // -- audit / replay (--list deep-subcommand) ---------------------------
384
+ "audit:list": {
385
+ name: "audit:list",
386
+ title: "wstack audit --list \u2014 list every session with an audit log",
387
+ description: "Scan the project sessions dir for `.audit.jsonl` sidecars and print a one-line summary per session (entry count + chain status). Useful for finding a session to inspect with `wstack audit <id>`.",
388
+ usage: "wstack audit --list / wstack audit -l",
389
+ seeAlso: "wstack audit <id> (inspect a single session's chain)"
390
+ },
391
+ "replay:list": {
392
+ name: "replay:list",
393
+ title: "wstack replay --list \u2014 list every session with a replay log",
394
+ description: "Scan the project sessions dir for `.replay.jsonl` sidecars and print a one-line summary per session (entry count + log path). Useful for finding a session to inspect with `wstack replay <id>`.",
395
+ usage: "wstack replay --list / wstack replay -l",
396
+ seeAlso: "wstack replay <id> (inspect a single session's recorded responses)"
397
+ },
398
+ // -- sessions (deep subcommands) ---------------------------------------
399
+ "sessions:resume": {
400
+ name: "sessions:resume",
401
+ title: "wstack sessions resume [<id>] \u2014 resume a prior session",
402
+ description: `Resume a session by id, or the most recent one if no id is given. The REPL replays the session's history into the new run so context is preserved. Use the most recent id when the user just asked "pick up where we left off" without naming a specific session.`,
403
+ usage: "wstack sessions resume [<id>]",
404
+ subcommands: [
405
+ { name: "[<id>]", description: "Session id to resume (defaults to the most recent)." }
406
+ ],
407
+ seeAlso: "wstack sessions list (find a recent id); wstack sessions show <id> (preview before resuming)"
408
+ },
409
+ "sessions:fork": {
410
+ name: "sessions:fork",
411
+ title: "wstack sessions fork [<id>] [--to N] \u2014 branch a session journal",
412
+ description: "Create a non-destructive child JSONL journal from the latest persisted boundary or checkpoint N. The parent is unchanged and the returned checkpoint hash identifies the exact parent event prefix. New Git-backed checkpoints also report a content-addressed workspace manifest, but the fork command does not apply it automatically: files remain shared until a host materializes that manifest into a separate clean checkout.",
413
+ usage: "wstack sessions fork [<id>] [--to N]",
414
+ subcommands: [
415
+ { name: "[<id>]", description: "Parent session id (defaults to the most recent)." },
416
+ { name: "--to N", description: "Fork at checkpoint prompt index N." }
417
+ ],
418
+ seeAlso: "wstack rewind --list (find checkpoints); wstack sessions resume <child-id>"
419
+ },
420
+ "sessions:fleet": {
421
+ name: "sessions:fleet",
422
+ title: "wstack sessions fleet \u2014 list the active fleet of sessions",
423
+ description: "List the active multi-agent fleet runs (the director, the subagent set, the iteration count, the journal size). Distinct from `wstack sessions list` which only shows single-agent sessions.",
424
+ usage: "wstack sessions fleet",
425
+ seeAlso: "wstack sessions list (single-agent sessions); /fleet (the in-REPL equivalent)"
426
+ },
427
+ "sessions:show": {
428
+ name: "sessions:show",
429
+ title: "wstack sessions show <id> \u2014 preview a session in detail",
430
+ description: "Print the session metadata, the first N turns, the token/cost totals, and any errors. Use this to decide whether to resume a session before committing to it.",
431
+ usage: "wstack sessions show <id>",
432
+ subcommands: [{ name: "<id>", description: "The session id to show." }]
433
+ },
434
+ "sessions:list": {
435
+ name: "sessions:list",
436
+ title: "wstack sessions list \u2014 list recent single-agent sessions",
437
+ description: "Print a one-line summary per recorded session (id, timestamp, last prompt, model, token totals). Distinct from `wstack sessions fleet` which shows active multi-agent runs. Use this to find a session id to resume, show, or export.",
438
+ usage: "wstack sessions list",
439
+ seeAlso: "wstack sessions fleet (active runs); wstack sessions resume <id> (resume one)"
440
+ },
441
+ "sessions:config": {
442
+ name: "sessions:config",
443
+ title: "wstack sessions config \u2014 session-specific config",
444
+ description: "Show or edit the session-specific config overrides (e.g. per-session provider + model). Subcommand: see the underlying config-history commands for the full surface \u2014 this is the shortcut alias.",
445
+ usage: "wstack sessions config"
446
+ },
447
+ // -- config (subcommands of the top-level config) ---------------------
448
+ "config:show": {
449
+ name: "config:show",
450
+ title: "wstack config show \u2014 print the resolved config",
451
+ description: "Print the resolved config (active profile plus all on-disk overrides applied) to stdout. Secrets are masked. The default subcommand \u2014 `wstack config` without a sub invokes this.",
452
+ usage: "wstack config show",
453
+ seeAlso: "wstack config edit (interactive); wstack auth (most config edits are auth/key changes)"
454
+ },
455
+ "config:edit": {
456
+ name: "config:edit",
457
+ title: "wstack config edit \u2014 open the active profile config in $EDITOR",
458
+ description: "Print the active profile config path (typically `~/.wrongstack/profiles/default/config.json`) and the command to open it. Does not spawn the editor itself \u2014 the user runs the printed command (or sets `$EDITOR` and re-runs). Useful for offline edits when you want to see the full file at once.",
459
+ usage: "wstack config edit",
460
+ seeAlso: "wstack config show (verify after edit); wstack config history (audit trail)"
461
+ },
462
+ "config:history": {
463
+ name: "config:history",
464
+ title: "wstack config history \u2014 list recent config-history entries",
465
+ description: "List every recent change to the active profile config, with a one-line description and a snapshot id. Pass `--id <id>` to see the full diff + masked snapshot. The audit trail is append-only (entries are never modified post-creation).",
466
+ usage: "wstack config history [--id <id>]",
467
+ subcommands: [
468
+ { name: "<no subcommand>", description: "List every history entry (newest first)." },
469
+ { name: "--id <id>", description: "Show the full diff + masked snapshot for one entry." }
470
+ ],
471
+ seeAlso: "wstack config restore <id>|--latest (revert); wstack config show (current state)"
472
+ },
473
+ "config:restore": {
474
+ name: "config:restore",
475
+ title: "wstack config restore <id>|--latest \u2014 revert to a prior config",
476
+ description: "Restore a previous config-history entry. Pass either the history id (from `wstack config history`) or `--latest` to revert to the most recent prior version. A backup of the current config is created before the restore, so the change is itself recorded in the history (a history of histories).",
477
+ usage: "wstack config restore <id> | --latest / -l",
478
+ subcommands: [
479
+ {
480
+ name: "<id>",
481
+ description: "The history id to restore (from `wstack config history` output)."
482
+ },
483
+ {
484
+ name: "--latest / -l",
485
+ description: "Restore to the most recent prior version (without naming an id)."
486
+ }
487
+ ],
488
+ seeAlso: "wstack config history (list entries); wstack config show (verify the restore)"
489
+ },
490
+ // -- rewind (flag-shaped deep subcommands) ----------------------------
491
+ "rewind:list": {
492
+ name: "rewind:list",
493
+ title: "wstack rewind --list \u2014 list rewind checkpoints for a session",
494
+ description: "Print every checkpoint for the session (default: latest). Each checkpoint is a snapshot of the working tree + session history at a given prompt index. Use the checkpoint index as the value for `--to <idx>` when rewinding. Default `wstack rewind` (no flags) is an error \u2014 pair `--list` with a session id (positional) to discover available checkpoints first.",
495
+ usage: "wstack rewind [<sessionId>] --list",
496
+ seeAlso: "wstack rewind --to <idx> (rewind to a specific checkpoint); wstack rewind --all"
497
+ },
498
+ "rewind:all": {
499
+ name: "rewind:all",
500
+ title: "wstack rewind --all \u2014 rewind to the start of the session",
501
+ description: "Rewind the working tree + session state to the very start of the session (the first prompt). Every file modified since the start is reverted. Pair with `--resume` to also truncate the session history at the start (so a fresh `wstack` invocation begins from there).",
502
+ usage: "wstack rewind [<sessionId>] --all [--resume]",
503
+ seeAlso: "wstack rewind --last N (rewind fewer steps); wstack rewind --to <idx> (specific checkpoint)"
504
+ },
505
+ "rewind:last": {
506
+ name: "rewind:last",
507
+ title: "wstack rewind --last N \u2014 rewind the last N prompts",
508
+ description: "Rewind the last `N` prompts. For a session that was on track for prompts 1..10 and went off the rails at 11..15, `--last 5` rewinds to the state at the end of prompt 10. Pair with `--resume` to truncate the history at the rewound point.",
509
+ usage: "wstack rewind [<sessionId>] --last <N> [--resume]",
510
+ subcommands: [
511
+ { name: "<N>", description: "Number of recent prompts to rewind (must be \u2265 1)." }
512
+ ],
513
+ seeAlso: "wstack rewind --all (rewind further); wstack rewind --to <idx> (precise checkpoint)"
514
+ },
515
+ "rewind:to": {
516
+ name: "rewind:to",
517
+ title: "wstack rewind --to <idx> \u2014 rewind to a specific checkpoint",
518
+ description: "Rewind to checkpoint at the given prompt index (from `wstack rewind --list`). The most precise rewind form \u2014 lets you step back to exactly the state at a specific prompt rather than the bulk `--all` or approximate `--last N`.",
519
+ usage: "wstack rewind [<sessionId>] --to <idx> [--resume]",
520
+ subcommands: [
521
+ {
522
+ name: "<idx>",
523
+ description: "Prompt index to rewind to (must be \u2265 0). Use `wstack rewind --list` to find indices."
524
+ }
525
+ ],
526
+ seeAlso: "wstack rewind --list (find checkpoint indices); wstack rewind --resume (truncate history at the checkpoint)"
527
+ },
528
+ "rewind:resume": {
529
+ name: "rewind:resume",
530
+ title: "wstack rewind --resume \u2014 truncate session history at the checkpoint",
531
+ description: "After the rewind (any of `--all` / `--last N` / `--to N`), also truncate the session's recorded history at the rewound checkpoint so the next `wstack` invocation begins fresh from there. Without `--resume`, the rewind only reverts the working tree \u2014 the session history is preserved (you'd see the rewind point as a checkpoint in subsequent runs).",
532
+ usage: "wstack rewind [<sessionId>] {--all|--last <N>|--to <idx>} --resume",
533
+ seeAlso: "wstack rewind --list (find checkpoints); wstack sessions resume <id> (resume a rewound session)"
534
+ },
535
+ // -- mcp:restart (REPL-only) -----------------------------------------
536
+ "mcp:restart": {
537
+ name: "mcp:restart",
538
+ title: "wstack mcp restart \u2014 restart a running MCP server (REPL only)",
539
+ description: "Restart a single running MCP server by alias. This subcommand is only meaningful inside the REPL (`wstack` with no `<task>` argument) \u2014 from the top-level CLI it prints a warning and exits 0 because there's no live process to restart. Use the `/mcp restart <name>` slash command from inside the REPL.",
540
+ usage: "wstack mcp restart <name> (REPL only)",
541
+ seeAlso: "/mcp restart <name> (the in-REPL slash command); wstack mcp remove + wstack mcp add (replace the server config)"
542
+ },
543
+ // -- plugin (list / official) -----------------------------------------
544
+ "plugin:list": {
545
+ name: "plugin:list",
546
+ title: "wstack plugin list \u2014 list configured plugins",
547
+ description: "Print every plugin registered in the config, grouped by enabled vs disabled. Alias: `plugin status`. For the official registry (a curated list maintained by the WrongStack project), use `wstack plugin official` instead.",
548
+ usage: "wstack plugin list (alias: wstack plugin status)",
549
+ seeAlso: "wstack plugin official (curated registry); wstack plugin enable / disable (toggle state)"
550
+ },
551
+ "plugin:official": {
552
+ name: "plugin:official",
553
+ title: "wstack plugin official \u2014 list the curated official registry",
554
+ description: "Print every plugin in the official registry (currently `telegram` and `lsp`). Each row shows the alias (for shorthand on the command line) and the full NPM specifier (what `wstack plugin add <spec>` actually installs). Aliases: `plugin officials` (plural).",
555
+ usage: "wstack plugin official (alias: wstack plugin officials)",
556
+ seeAlso: "wstack plugin add <alias> (install one); wstack plugin list (what you have)"
557
+ },
558
+ "plugin:officials": {
559
+ // The plural form `plugin officials` is accepted as an
560
+ // alias of `plugin official` in the underlying dispatch
561
+ // (`plugin-management.ts`). The deep-help table mirrors
562
+ // the alias so `wstack plugin officials --help` and
563
+ // `wstack plugin official --help` both render the same
564
+ // focused block.
565
+ name: "plugin:officials",
566
+ title: "wstack plugin officials \u2014 list the curated official registry (plural alias)",
567
+ description: "Alias of `wstack plugin official`. Prints every plugin in the official registry. Same output as the singular form.",
568
+ usage: "wstack plugin officials (plural alias of `wstack plugin official`)",
569
+ seeAlso: "wstack plugin official (the singular form)"
570
+ },
571
+ // -- models (refresh + list) -----------------------------------------
572
+ "models:refresh": {
573
+ name: "models:refresh",
574
+ title: "wstack models refresh \u2014 force-refresh the models.dev cache",
575
+ description: "Re-fetch the models.dev catalog and replace the cached `models.json` in the global config dir. Useful when a new model is published mid-session and you want to see it in `wstack providers` / `wstack models` without restarting. The cache age is shown in the footer of every `wstack models` listing so you know when to refresh.",
576
+ usage: "wstack models refresh",
577
+ seeAlso: "wstack models <provider> (list models after refresh); wstack providers (force-refresh the provider catalog)"
578
+ },
579
+ "models:list": {
580
+ name: "models:list",
581
+ title: "wstack models list \u2014 list custom models registered locally",
582
+ description: "Print every model that's been added via `wstack models add` (i.e. the entries in `config.json`'s `models` section, not the catalog). Distinct from `wstack models <provider>` which lists the catalog for a specific provider. The list is the audit surface for self-hosted / fine-tuned / overridden models.",
583
+ usage: "wstack models list",
584
+ seeAlso: "wstack models <provider> (catalog); wstack models add <mid> (register a custom model)"
585
+ },
586
+ // -- auth (list / status / remove) -------------------------------------
587
+ // The top-level `wstack auth` entry in `helpTable` lists the
588
+ // subcommands; these deep entries give each one its own focused
589
+ // block so `wstack auth list --help`, `/help auth status`, and
590
+ // `/auth status help` all render the same string the underlying
591
+ // handler would emit. The descriptions match the actual
592
+ // handler behavior in `packages/cli/src/subcommands/handlers/auth.ts`
593
+ // — note that the `remove` subcommand is always interactive
594
+ // (prompts for confirmation); the `[--force]` token in the
595
+ // handler's error message is a documented hint that is not
596
+ // yet wired up in the parser.
597
+ "auth:list": {
598
+ name: "auth:list",
599
+ title: "wstack auth list \u2014 list saved providers and key status",
600
+ description: "Read-only listing of every provider in the active profile config. Each provider block shows the family, baseUrl, model-allowlist size, and the saved API keys (the active key is marked with a green `\u25CF`, inactive keys with a dim `\u25CB`; all values are masked). Alias: `wstack auth ls`.",
601
+ usage: "wstack auth list (alias: wstack auth ls)",
602
+ subcommands: [
603
+ { name: "list", description: "List every saved provider (this command)." },
604
+ { name: "ls", description: "Alias of list." }
605
+ ],
606
+ seeAlso: "wstack auth status <id> (detail for one provider); wstack auth remove <id> (delete one)"
607
+ },
608
+ "auth:status": {
609
+ name: "auth:status",
610
+ title: "wstack auth status <provider> \u2014 show detail for one provider",
611
+ description: "Print the full `config.json` entry for a single provider: type, family, baseUrl, the `models` allowlist, the `envVars` list, and every saved key (active key marked with a green `\u25CF`, masked value, ISO timestamp). The provider id is required as a positional \u2014 `wstack auth status` with no id prints the usage hint and exits 1.",
612
+ usage: "wstack auth status <provider>",
613
+ subcommands: [
614
+ {
615
+ name: "<provider>",
616
+ description: "The provider id to inspect (e.g. `openai`, `anthropic`)."
617
+ }
618
+ ],
619
+ seeAlso: "wstack auth list (find the id); wstack auth remove <id> (delete it); wstack auth (interactive edit)"
620
+ },
621
+ "auth:remove": {
622
+ name: "auth:remove",
623
+ title: "wstack auth remove <provider> \u2014 delete a provider and its keys",
624
+ description: "Remove a provider entry and all its saved API keys from the active profile config. The flow is always interactive: after printing a confirmation prompt the handler waits for a `y` / `yes` answer (default `N`). The active session's in-memory provider is NOT reloaded \u2014 restart the REPL to fully tear down a running provider. Alias: `wstack auth rm`.",
625
+ usage: "wstack auth remove <provider> (alias: wstack auth rm <provider>)",
626
+ subcommands: [
627
+ { name: "<provider>", description: "The provider id to remove." },
628
+ { name: "rm", description: "Alias of remove." }
629
+ ],
630
+ seeAlso: "wstack auth list (find the id); wstack auth status <id> (inspect before removing); wstack auth <provider> (re-add a different one)"
631
+ },
632
+ // The `auth:local` deep entry delegates its body to
633
+ // `auth-local-help.ts` via the `customBody` field. The flag
634
+ // list lives in exactly one place (`LOCAL_AUTH_FLAGS`), and
635
+ // every surface that renders the help — `wstack auth local --help`,
636
+ // `/auth local help`, `/help auth local` — produces the same
637
+ // string. The `title` / `description` / `usage` / `seeAlso` fields
638
+ // below are required by the `PerSubcommandHelp` shape but
639
+ // never rendered (the `customBody` thunk owns the full layout).
640
+ // They're filled in with sensible defaults so a future refactor
641
+ // that drops `customBody` (e.g. to use the standard layout)
642
+ // still has a coherent fallback.
643
+ "auth:local": {
644
+ name: "auth:local",
645
+ title: "wstack auth local \u2014 quick-add Ollama / vLLM / LM Studio",
646
+ description: "Pre-fills the base URL, runs a health probe, and persists the allowlist so you can `wstack --provider <id>` right away. Use `--no-probe` to skip the probe when the server is not running yet; `--audit <file>` captures the save lifecycle as JSONL.",
647
+ usage: "wstack auth local [--name <id>] [--base-url <url>] [--no-key] [--no-probe|--probe-only] [--model <spec>] [--audit [target]]",
648
+ seeAlso: "wstack auth (interactive menu); wstack auth <provider> (catalog add)",
649
+ customBody: renderAuthLocalHelpToString
650
+ },
651
+ // -- bench (run — delegated to bench-run-help.ts via customBody) ------
652
+ // The `bench:run` deep entry delegates its body to
653
+ // `bench-run-help.ts` via the `customBody` field. The flag
654
+ // list lives in exactly one place (`BENCH_RUN_FLAGS`), and
655
+ // every surface that renders the help — `wstack bench run --help`,
656
+ // `/bench run help`, `/help bench run` — produces the same
657
+ // string. The `title` / `description` / `usage` / `seeAlso`
658
+ // fields below are required by the `PerSubcommandHelp` shape
659
+ // but never rendered (the `customBody` thunk owns the full
660
+ // layout). They're filled in with sensible defaults so a
661
+ // future refactor that drops `customBody` (e.g. to use the
662
+ // standard layout) still has a coherent fallback.
663
+ "bench:run": {
664
+ name: "bench:run",
665
+ title: "wstack bench run \u2014 execute a benchmark suite across a model matrix",
666
+ description: "See renderBenchRunHelpToString() in bench-run-help.ts for the full block.",
667
+ usage: "wstack bench run [...flags]",
668
+ customBody: renderBenchRunHelpToString
669
+ }
670
+ };
671
+
672
+ // src/subcommands/handlers/per-subcommand-help-table.ts
673
+ var helpTable = {
674
+ init: {
675
+ name: "init",
676
+ title: "wstack init \u2014 DEPRECATED (use wstack auth)",
677
+ description: "\u26A0 This command is deprecated. Use wstack auth for setup, key management, and model selection in one interactive workflow.",
678
+ usage: "wstack init (deprecated)",
679
+ seeAlso: "wstack auth (interactive setup + key manager)"
680
+ },
681
+ version: {
682
+ name: "version",
683
+ title: "wstack version \u2014 print the CLI version",
684
+ description: "Prints the WrongStack CLI version, the apiVersion, the Node.js version, and the host platform. Useful for bug reports and CI logs.",
685
+ usage: "wstack version"
686
+ },
687
+ mcp: {
688
+ name: "mcp",
689
+ title: "wstack mcp \u2014 manage Model Context Protocol servers",
690
+ description: "List, add, remove, restart, and serve MCP servers registered in the global config. Servers are referenced by id and use the stdio, SSE, or streamable-HTTP transports.",
691
+ usage: "wstack mcp [list|add|remove|restart|serve] [...]",
692
+ subcommands: [
693
+ { name: "list", description: "List all configured MCP servers." },
694
+ { name: "add <id> <command>", description: "Register a new stdio MCP server." },
695
+ { name: "remove <id>", description: "Unregister an MCP server." },
696
+ { name: "restart <id>", description: "Restart a running MCP server." },
697
+ {
698
+ name: "serve",
699
+ description: "Run the wstack MCP server; --resources/--prompts explicitly expose selected files."
700
+ }
701
+ ],
702
+ seeAlso: "wstack plugin (manage tool plugins similarly)"
703
+ },
704
+ plugin: {
705
+ name: "plugin",
706
+ title: "wstack plugin \u2014 manage tool plugins",
707
+ description: "List, inspect, install, add, remove, enable, disable, and toggle tool plugins. Plugins extend the agent with custom tool packs (e.g. GitHub, Playwright, project-local helpers).",
708
+ usage: "wstack plugin [list|status|report|menu|official|add|install|toggle|remove|enable|disable|manager] [...]",
709
+ subcommands: [
710
+ { name: "list", description: "List installed plugins (alias: status)." },
711
+ { name: "report", description: "Show effective state, risk, and lock/toggle policy." },
712
+ { name: "menu", description: "Print the audit report outside the TUI plugin picker." },
713
+ { name: "official", description: "List plugins from the official registry." },
714
+ { name: "add <id>", description: "Add a plugin by id (alias: install)." },
715
+ { name: "toggle <id>", description: "Toggle a safe audit-list plugin row." },
716
+ { name: "remove <id>", description: "Remove an installed plugin (aliases: rm, uninstall)." },
717
+ { name: "enable <id>", description: "Re-enable a previously-disabled plugin." },
718
+ { name: "disable <id>", description: "Temporarily disable a plugin without removing it." },
719
+ {
720
+ name: "manager [lock|unlock] <id|*>",
721
+ description: "Control whether the LLM may enable/disable individual plugins."
722
+ }
723
+ ],
724
+ seeAlso: "wstack mcp (MCP servers are registered as tool plugins)"
725
+ },
726
+ models: {
727
+ name: "models",
728
+ title: "wstack models \u2014 list and override models",
729
+ description: "List models from the models.dev catalog, or override the default model for a provider with a custom id (for self-hosted or fine-tuned models not in the public catalog).",
730
+ usage: "wstack models [<provider>] [add|remove|list|refresh] [...]",
731
+ subcommands: [
732
+ { name: "<no-subcommand>", description: "List models for the default provider." },
733
+ { name: "<provider>", description: "List models for a specific provider." },
734
+ {
735
+ name: "add <mid>",
736
+ description: "Add or override a custom model (--max-context, --tools, --vision, \u2026)."
737
+ },
738
+ { name: "remove <mid>", description: "Remove a custom model." },
739
+ { name: "list", description: "List all custom models registered locally." },
740
+ { name: "refresh", description: "Force-refresh the models.dev cache." }
741
+ ],
742
+ seeAlso: "wstack providers (list provider families and their defaults)"
743
+ },
744
+ config: {
745
+ name: "config",
746
+ title: "wstack config \u2014 show or edit effective config",
747
+ description: "Print the resolved config (with the on-disk overrides merged on top), or open the active profile config in $EDITOR for interactive edits. Also exposes a small audit log of recent config-history changes for diagnostics.",
748
+ usage: "wstack config [show|edit|history|restore] [...]",
749
+ subcommands: [
750
+ { name: "show", description: "Print the resolved config to stdout (default)." },
751
+ { name: "edit", description: "Open the active profile config in $EDITOR." },
752
+ { name: "history", description: "List recent config-history entries." },
753
+ { name: "restore <id>", description: "Restore a previous config-history entry." }
754
+ ],
755
+ seeAlso: "wstack auth (most config edits are auth/key changes)"
756
+ },
757
+ // -- API key / auth management -----------------------------------------
758
+ auth: {
759
+ name: "auth",
760
+ title: "wstack auth \u2014 manage API keys and provider credentials",
761
+ description: "Add, view, and remove provider API keys. The interactive menu supports a custom-URL path for self-hosted / local servers, a quick-shortcut path for Ollama / vLLM / LM Studio, and a catalog path for the well-known providers.",
762
+ usage: "wstack auth [list|status|remove] [...] | wstack auth <provider> | wstack auth local [...]",
763
+ subcommands: [
764
+ { name: "list", description: "List saved providers and key status." },
765
+ { name: "status <id>", description: "Show detail for one provider." },
766
+ { name: "remove <id>", description: "Remove a provider and its keys." },
767
+ { name: "<provider>", description: "Add a key for a named provider (--label, --family, \u2026)." },
768
+ {
769
+ name: "local",
770
+ description: "Pre-fill Ollama / vLLM / LM Studio (--name, --base-url, --no-probe, --model, --audit \u2026)."
771
+ },
772
+ {
773
+ name: "login <chatgpt|claude|copilot>",
774
+ description: "Subscription OAuth login: chatgpt (\u2192 openai-codex), claude (\u2192 anthropic-oauth), or copilot (\u2192 github-copilot). Opens browser; no API key. \u26A0 Using subscriptions outside official clients may violate provider ToS (account ban risk); an API key is the sanctioned path."
775
+ }
776
+ ],
777
+ seeAlso: "wstack auth local (pre-fill Ollama / vLLM / LM Studio)"
778
+ },
779
+ // -- Session list / resume / show / fork --------------------------------
780
+ sessions: {
781
+ name: "sessions",
782
+ title: "wstack sessions \u2014 list and resume recent sessions",
783
+ description: "List recent sessions, show one session in detail, resume a session, or inspect a session's audit log. The audit log is stored as JSONL next to each session's recording.",
784
+ usage: "wstack sessions [list|show|resume|fork|doctor|config|fleet] [...]",
785
+ subcommands: [
786
+ { name: "list", description: "List the most recent sessions." },
787
+ {
788
+ name: "doctor [--fix] [--json] [--limit N]",
789
+ description: "Diagnose every journal in this project: unparsable lines, truncated tails, sessions that died mid-turn, missing or stale summary sidecars, and journals large enough to be slow to open. --fix rebuilds only derived artifacts (summary sidecars + the catalog index); journals are never edited."
790
+ },
791
+ { name: "show <id>", description: "Show one session in detail." },
792
+ { name: "resume [<id>]", description: "Resume a session (latest if no id given)." },
793
+ {
794
+ name: "fork [<id>] [--to N]",
795
+ description: "Create an isolated child journal at a persisted boundary."
796
+ },
797
+ { name: "config", description: "Show or edit session-specific config." },
798
+ { name: "fleet", description: "List the active fleet of sessions." }
799
+ ],
800
+ seeAlso: "wstack audit (the session-level audit log reader)"
801
+ },
802
+ // -- Diagnostics --------------------------------------------------------
803
+ doctor: {
804
+ name: "doctor",
805
+ title: "wstack doctor \u2014 health checks",
806
+ description: "Run a series of health checks (provider + key + models cache + secret vault + sessions dir + MCP server config) and exit non-zero if any check fails. Use as a CI gate or a post-install smoke test. With --daemons, inspect this project\u2019s IPC daemons instead: each is reported live, stale, or stopped. A stale endpoint is one whose owner died without releasing it; daemons reclaim it on their next start, or --clear-stale removes it now. Listing never spawns a daemon.",
807
+ usage: "wstack doctor [--daemons [--clear-stale]]",
808
+ seeAlso: "wstack diag (read-only environment dump for bug reports)"
809
+ },
810
+ diag: {
811
+ name: "diag",
812
+ title: "wstack diag \u2014 read-only environment dump",
813
+ description: "Print a key=value environment snapshot (apiVersion, cwd, project info, paths, cache age, configured provider + model, tool/plugin counts, MCP server count). Never modifies state \u2014 safe to paste into bug reports.",
814
+ usage: "wstack diag",
815
+ seeAlso: "wstack doctor (pass/fail health checks vs. this is a dump)"
816
+ },
817
+ // -- Session audit / replay / rewind -----------------------------------
818
+ audit: {
819
+ name: "audit",
820
+ title: "wstack audit \u2014 inspect a session's tamper-evident audit log",
821
+ description: "Show the chained-hash entries for a recorded session and run a verification pass to surface any post-hoc modification. Each entry is SHA-256-chained to the previous; any tampering breaks the chain and is reported.",
822
+ usage: "wstack audit [<sessionId>] [--list]",
823
+ subcommands: [
824
+ { name: "<sessionId>", description: "Show entries + verify chain (positional)." },
825
+ { name: "--list / -l", description: "List every session that has an audit log." }
826
+ ],
827
+ seeAlso: "wstack replay (the corresponding provider-response log)"
828
+ },
829
+ replay: {
830
+ name: "replay",
831
+ title: "wstack replay \u2014 inspect a session's recorded provider responses",
832
+ description: "Show the recorded request/response pairs for a session \u2014 the frozen inputs the agent saw, in order. This is the inspection surface; to actually re-run the agent with those responses, use `wstack --replay <sessionId>`.",
833
+ usage: "wstack replay [<sessionId>] [--list]",
834
+ subcommands: [
835
+ { name: "<sessionId>", description: "Show the recorded entries (positional)." },
836
+ { name: "--list / -l", description: "List every session that has a replay log." }
837
+ ],
838
+ seeAlso: "wstack audit (the tamper-evident tool-call log)"
839
+ },
840
+ rewind: {
841
+ name: "rewind",
842
+ title: "wstack rewind \u2014 rewind a session to an earlier state",
843
+ description: "Restore a session's in-memory state to a previous point in its recording. The rewind is non-destructive: the original session is preserved, and a new resumed session picks up from the rewound point. Useful for re-running a fork of an exploration without losing the original.",
844
+ usage: "wstack rewind [<sessionId>] [--all|--last <n>|--to <id>] [--list] [--resume]",
845
+ subcommands: [
846
+ { name: "<sessionId>", description: "Session id (positional; defaults to the latest)." },
847
+ { name: "--all", description: "Rewind to the start of the session." },
848
+ { name: "--last <n>", description: "Rewind to `n` steps back from the end." },
849
+ { name: "--to <id>", description: "Rewind to a specific step id." },
850
+ { name: "--list", description: "List available rewind points for the session." },
851
+ { name: "--resume", description: "Resume the rewound session after the rewind." }
852
+ ],
853
+ seeAlso: "wstack replay (the underlying provider-response log)"
854
+ },
855
+ // -- Export & usage ----------------------------------------------------
856
+ export: {
857
+ name: "export",
858
+ title: "wstack export \u2014 render a session to a portable format",
859
+ description: "Render a recorded session to Markdown, JSON, or plain text. Use Markdown for human-readable share/audit artifacts, JSON for downstream tooling, or text for grep-friendly search. Tools and diagnostics are included by default; toggle either off with `--no-tools` or `--no-diagnostics`.",
860
+ usage: "wstack export <sessionId> [--format markdown|json|text] [--out <file>] [--no-tools] [--no-diagnostics]",
861
+ subcommands: [
862
+ { name: "<sessionId>", description: "The session id to render (positional)." },
863
+ {
864
+ name: "--format <f> / -f <f>",
865
+ description: "Output format: markdown (default), json, or text."
866
+ },
867
+ { name: "--out <file> / -o <file>", description: "Write to <file> instead of stdout." },
868
+ { name: "--no-tools", description: "Omit tool-call entries from the output." },
869
+ {
870
+ name: "--no-diagnostics",
871
+ description: "Omit diagnostic entries (errors, retries) from the output."
872
+ }
873
+ ],
874
+ seeAlso: "wstack replay (the recorded provider-response log)"
875
+ },
876
+ usage: {
877
+ name: "usage",
878
+ title: "wstack usage \u2014 token + cost summary",
879
+ description: "Print a per-session token + cost summary from the audit log. Useful for cost reviews and the post-session billing recap. Aggregates input/output tokens and the per-model cost; requires the session to have been recorded with audit enabled.",
880
+ usage: "wstack usage",
881
+ seeAlso: "wstack export (full session render for archival)"
882
+ },
883
+ // -- Listing subcommands -----------------------------------------------
884
+ providers: {
885
+ name: "providers",
886
+ title: "wstack providers \u2014 list providers from models.dev",
887
+ description: "List provider families from the live models.dev catalog. Default view shows the popular three (Anthropic, OpenAI, Google); pass `--all` to include every supported family, or `--unsupported` to surface the ones without a built-in transport (which require a plugin).",
888
+ usage: "wstack providers [--all] [--unsupported]",
889
+ subcommands: [
890
+ { name: "--all", description: "Include every supported family, not just the popular three." },
891
+ {
892
+ name: "--unsupported",
893
+ description: "Include families without a built-in transport (need a plugin)."
894
+ }
895
+ ],
896
+ seeAlso: "wstack models (list models within a provider)"
897
+ },
898
+ tools: {
899
+ name: "tools",
900
+ title: "wstack tools \u2014 list registered tools",
901
+ description: "List every tool the agent can invoke, with its owner (built-in / plugin) and permission level. Useful for auditing what a session can do, especially after installing a new plugin.",
902
+ usage: "wstack tools",
903
+ seeAlso: "wstack skills (list skills; tools + skills are the two extension surfaces)"
904
+ },
905
+ skills: {
906
+ name: "skills",
907
+ title: "wstack skills \u2014 list discovered skills",
908
+ description: "List every skill the agent can invoke, grouped by source (bundled / user-installed / project-local). Skills are on-demand context packs that load only when triggered.",
909
+ usage: "wstack skills",
910
+ seeAlso: "wstack tools (tools are always-loaded; skills are on-demand)"
911
+ },
912
+ projects: {
913
+ name: "projects",
914
+ title: "wstack projects \u2014 list tracked projects",
915
+ description: "List every project WrongStack has seen (tracked by a hashed root). Each entry shows the project root and the last-seen timestamp. Useful for cleaning up the global projects dir after a workspace migration.",
916
+ usage: "wstack projects"
917
+ },
918
+ // -- Lifecycle ---------------------------------------------------------
919
+ update: {
920
+ name: "update",
921
+ title: "wstack update \u2014 self-update the CLI",
922
+ description: "Check the latest npm version and update the globally-installed `wrongstack` package. Use `--check-only` to just print the current/latest without installing. Pass `--pm <manager>` (or its shorthand `--npm`, `--pnpm`, `--yarn`, `--bun`) to force a specific package manager; pass `--allow-scripts` (alias `--lifecycle-scripts`) to opt into package lifecycle scripts during the update (off by default). The update is global; run from any project root.",
923
+ usage: "wstack update [--check-only] [--pm <manager>] [--allow-scripts (alias: --lifecycle-scripts)]",
924
+ seeAlso: "wstack version (read-only version info)"
925
+ },
926
+ // -- ACP (Agent Client Protocol) --------------------------------------
927
+ acp: {
928
+ name: "acp",
929
+ title: "wstack acp \u2014 Agent Client Protocol (ACP) integration",
930
+ description: "Run WrongStack as an ACP server (stdio) for editor clients (Zed, JetBrains, VS Code ACP), or orchestrate external ACP agents through spawn, probe, bench, and parallel fan-out.",
931
+ usage: "wstack acp [server|list|sync|spawn|parallel|probe|bench] [...]",
932
+ subcommands: [
933
+ { name: "server / serve", description: "Start WrongStack as an ACP stdio server (default)." },
934
+ { name: "list", description: "List available ACP agents from the cache." },
935
+ { name: "sync", description: "Sync the official ACP agent registry into local cache." },
936
+ { name: "spawn <id> <task>", description: "Spawn an ACP agent and wait for results." },
937
+ {
938
+ name: "parallel <csv> <task>",
939
+ description: "Fan a task out to multiple ACP agents in parallel."
940
+ },
941
+ { name: "probe [csv]", description: "Handshake-test installed ACP agents." },
942
+ { name: "bench [csv] [--fs]", description: "End-to-end benchmark and grade ACP agents." }
943
+ ],
944
+ seeAlso: "wstack mcp serve (the MCP equivalent; pick the protocol your client speaks)"
945
+ },
946
+ // -- Model diagnostics (read-only) -----------------------------------
947
+ modeldiag: {
948
+ name: "modeldiag",
949
+ title: "wstack modeldiag \u2014 model benchmarks + heuristic diagnostics",
950
+ description: "Read-only diagnostics for the configured model: key check, capability scan (vision / tools / context window), heuristic strengths/weaknesses (bestFor / avoidFor), sequential live provider/model smoke tests, and real benchmarks against a small prompt suite. Smoke tests use tiny prompts and never print credentials.",
951
+ usage: "wstack modeldiag [test|eval] [...]",
952
+ subcommands: [
953
+ {
954
+ name: "<no subcommand>",
955
+ description: "Print configured model capabilities, context limits, and recommendations."
956
+ },
957
+ {
958
+ name: "test [--plan|--all-models|--json]",
959
+ description: "Run live sequential smoke tests across configured models."
960
+ },
961
+ {
962
+ name: "eval [--providers <csv>]",
963
+ description: "Run model competency matrix evaluation across tasks."
964
+ }
965
+ ],
966
+ seeAlso: "wstack modeldiag test --plan; wstack modeldiag test; wstack modeldiag test --all-models"
967
+ },
968
+ // -- Bench (developer / CI only) -------------------------------------
969
+ bench: {
970
+ name: "bench",
971
+ title: "wstack bench \u2014 run model-independent agentic benchmarks",
972
+ description: "Run WrongStack against the Aider polyglot or SWE-bench Verified suites with deterministic graders. Used internally to compare model quality across releases; also useful for evaluating a new model before adopting it.",
973
+ usage: "wstack bench [run|report|list] [...]",
974
+ subcommands: [
975
+ { name: "run", description: "Run a benchmark suite (--suite <id> --models <config>)." },
976
+ { name: "report <dir>", description: "Render the Markdown report for a prior run." },
977
+ { name: "list", description: "List available suites and the model configs in the catalog." }
978
+ ],
979
+ seeAlso: "wstack modeldiag (read-only diagnostics; bench actually runs the model)"
980
+ },
981
+ // -- Quick launch ------------------------------------------------------
982
+ quick: {
983
+ name: "quick",
984
+ title: "wstack quick \u2014 launch the TUI with sensible defaults",
985
+ description: "Accept every default, list installed plugins, and open the TUI with the agents-monitor panel pre-shown. Equivalent to `wstack --tui --quick`; the dedicated subcommand is for discoverability and tab-completion. The actual TUI launch is intercepted in `boot()` before this handler runs.",
986
+ usage: "wstack quick",
987
+ seeAlso: "wstack --tui (the underlying flag; quick is just a shortcut)"
988
+ },
989
+ // -- Aliases and meta commands ───────────────────────────────────────
990
+ plugins: {
991
+ name: "plugins",
992
+ title: "wstack plugins \u2014 alias for wstack plugin",
993
+ description: "Alias for `wstack plugin`. See `wstack plugin --help` for the full set of subcommands.",
994
+ usage: "wstack plugins (alias for wstack plugin)",
995
+ seeAlso: "wstack plugin (the canonical command)"
996
+ },
997
+ help: {
998
+ name: "help",
999
+ title: "wstack help \u2014 print top-level help",
1000
+ description: "Print the top-level help text listing every subcommand with a one-line summary. Equivalent to `wstack --help`.",
1001
+ usage: "wstack help",
1002
+ seeAlso: "wstack --help"
1003
+ },
1004
+ // -- HQ (dashboard server) ──────────────────────────────────────────
1005
+ hq: {
1006
+ name: "hq",
1007
+ title: "wstack hq \u2014 start HQ command center or manage tokens",
1008
+ description: "Start the HQ server \u2014 a web dashboard for monitoring sessions, fleet status, and agent activity across projects \u2014 or manage browser and client authentication tokens.",
1009
+ usage: "wstack hq [serve] [--port <n>] [--password <secret>] [--tunnel] [--open] | wstack hq token [create|list|revoke]",
1010
+ subcommands: [
1011
+ { name: "serve", description: "Start the HQ dashboard server (default)." },
1012
+ {
1013
+ name: "token create [label]",
1014
+ description: "Mint a browser or client authentication token."
1015
+ },
1016
+ { name: "token list", description: "List active HQ authentication tokens." },
1017
+ { name: "token revoke <id>", description: "Revoke an issued HQ authentication token." }
1018
+ ],
1019
+ seeAlso: "wstack sessions fleet (CLI equivalent for fleet status)"
1020
+ },
1021
+ // -- Mailbox (external agent bridge) ────────────────────────────────
1022
+ mailbox: {
1023
+ name: "mailbox",
1024
+ title: "wstack mailbox \u2014 serve the external-agent mailbox HTTP bridge",
1025
+ description: "Start the mailbox HTTP bridge that lets external coding agents (Claude Code, Aider, custom scripts) communicate with the shared project mailbox. The server exposes a REST + SSE API for sending, checking, and acknowledging messages. Use `wstack mailbox serve` to start the listener.",
1026
+ usage: "wstack mailbox serve [--port <n>]",
1027
+ subcommands: [{ name: "serve", description: "Start the mailbox HTTP bridge listener." }],
1028
+ seeAlso: "wstack hq (the HQ server includes mailbox routing)"
1029
+ },
1030
+ // -- Permissions ────────────────────────────────────────────────────
1031
+ permissions: {
1032
+ name: "permissions",
1033
+ title: "wstack permissions \u2014 explain tool permission decisions",
1034
+ description: "Side-effect-free permission decision explainer. Evaluates the effective permission rules for a tool and input arguments without prompting, modifying trust files, or mutating state.",
1035
+ usage: "wstack permissions explain <tool> [--input '<json>'] [--json]",
1036
+ subcommands: [
1037
+ {
1038
+ name: "explain <tool>",
1039
+ description: "Explain how the permission policy evaluates a tool call."
1040
+ }
1041
+ ],
1042
+ seeAlso: "wstack tools (list available tools)"
1043
+ },
1044
+ // -- Project management ─────────────────────────────────────────────
1045
+ project: {
1046
+ name: "project",
1047
+ title: "wstack project \u2014 manage committed repository identity",
1048
+ description: "Manage the committed repository identity (project.json) used to scope HQ dashboards, Kanban state, and multi-agent coordination. Commit the generated ID file so every clone shares the same project.",
1049
+ usage: "wstack project [id|init|rekey] [--yes]",
1050
+ subcommands: [
1051
+ { name: "id", description: "Show the current project ID and config path (default)." },
1052
+ { name: "init", description: "Initialize a project ID if not already present." },
1053
+ { name: "rekey", description: "Generate a new project ID for a fork (requires --yes)." }
1054
+ ],
1055
+ seeAlso: "wstack projects (list all tracked projects)"
1056
+ },
1057
+ governance: {
1058
+ name: "governance",
1059
+ title: "wstack governance \u2014 inspect deterministic project-daemon health",
1060
+ description: "Read token-free attachment-broker health from the current project daemon. Warnings are advisory: they surface deterministic operator escalation signals without stopping active tasks or model execution.",
1061
+ usage: "wstack governance status [--json]",
1062
+ subcommands: [{ name: "status", description: "Show daemon and attachment-broker health." }],
1063
+ seeAlso: "wstack doctor (broader environment diagnostics)"
1064
+ },
1065
+ // -- Chronicle ──────────────────────────────────────────────────────
1066
+ chronicle: {
1067
+ name: "chronicle",
1068
+ title: "wstack chronicle \u2014 query cross-session provenance ledger",
1069
+ description: "Query the cross-session event ledger, inspect daemon status, compute facet aggregations, view token/cost metrics, or purge old retention entries.",
1070
+ usage: "wstack chronicle [query|status|facet|metrics|prune|compact] [...]",
1071
+ subcommands: [
1072
+ { name: "query [field=value ...]", description: "Query recorded provenance events." },
1073
+ { name: "status", description: "Check the Chronicle daemon and pipeline status." },
1074
+ { name: "facet <field>", description: "Group and count events across a facet." },
1075
+ {
1076
+ name: "metrics [providers|tasks|files|summary]",
1077
+ description: "Query aggregated metrics from metrics.db."
1078
+ },
1079
+ {
1080
+ name: "prune [--days N] [--dry-run]",
1081
+ description: "Purge journal entries older than N days."
1082
+ },
1083
+ { name: "compact", description: "Defragment and compact SQLite ledger." }
1084
+ ],
1085
+ seeAlso: "wstack audit (per-session audit log); wstack usage (cost summary)"
1086
+ }
1087
+ };
1088
+
1089
+ // src/subcommands/handlers/per-subcommand-help.ts
1090
+ var COLUMN_WIDTH = 28;
1091
+ function renderBlockToString(help) {
1092
+ if (help.customBody) {
1093
+ return help.customBody();
1094
+ }
1095
+ const lines = [
1096
+ color3.bold(help.title),
1097
+ color3.dim(` ${help.description}`),
1098
+ "",
1099
+ color3.bold("Usage"),
1100
+ ` ${help.usage}`
1101
+ ];
1102
+ if (help.subcommands && help.subcommands.length > 0) {
1103
+ lines.push("");
1104
+ lines.push(color3.bold("Subcommands"));
1105
+ for (const { name, description } of help.subcommands) {
1106
+ const padded = name.padEnd(COLUMN_WIDTH, " ");
1107
+ lines.push(` ${color3.cyan(padded)}${description}`);
1108
+ }
1109
+ }
1110
+ if (help.seeAlso) {
1111
+ lines.push("");
1112
+ lines.push(color3.dim(` See also: ${help.seeAlso}`));
1113
+ }
1114
+ lines.push("");
1115
+ lines.push(color3.dim(" Tip: `wstack --help` lists every top-level command."));
1116
+ return lines.join("\n") + "\n";
1117
+ }
1118
+ function renderBlock(help, renderer) {
1119
+ renderer.write(renderBlockToString(help));
1120
+ }
1121
+ function renderDeepHelp(key, renderer) {
1122
+ const help = deepHelpTable[key];
1123
+ if (!help) return false;
1124
+ renderBlock(help, renderer);
1125
+ return true;
1126
+ }
1127
+ function renderDeepHelpToString(key) {
1128
+ const help = deepHelpTable[key];
1129
+ return help ? renderBlockToString(help) : void 0;
1130
+ }
1131
+ var deepSubcommandsWithFocusedHelp = Object.keys(deepHelpTable);
1132
+ function renderFocusedHelp(subcommand, renderer) {
1133
+ const help = helpTable[subcommand];
1134
+ if (!help) return false;
1135
+ renderBlock(help, renderer);
1136
+ return true;
1137
+ }
1138
+ function renderFocusedHelpToString(subcommand) {
1139
+ const help = helpTable[subcommand];
1140
+ return help ? renderBlockToString(help) : void 0;
1141
+ }
1142
+ var subcommandsWithFocusedHelp = Object.keys(helpTable);
1143
+ function renderGenericHelp(subcommand, renderer) {
1144
+ const lines = [
1145
+ color3.bold(`wstack ${subcommand}`),
1146
+ color3.dim(
1147
+ ` No focused help block is registered for this subcommand. Run \`wstack ${subcommand}\` for the interactive surface, or \`wstack --help\` for the top-level command list.`
1148
+ ),
1149
+ "",
1150
+ color3.dim(" Tip: each subcommand's help is data-driven; see"),
1151
+ color3.dim(" `per-subcommand-help.ts` for the focused entries.")
1152
+ ];
1153
+ renderer.write(lines.join("\n") + "\n");
1154
+ }
1155
+
1156
+ export {
1157
+ renderBlockToString,
1158
+ renderDeepHelp,
1159
+ renderDeepHelpToString,
1160
+ deepSubcommandsWithFocusedHelp,
1161
+ renderFocusedHelp,
1162
+ renderFocusedHelpToString,
1163
+ subcommandsWithFocusedHelp,
1164
+ renderGenericHelp
1165
+ };
1166
+ //# sourceMappingURL=chunk-P2OKBDCH.js.map