@united-workforce/cli 0.6.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +120 -5
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__tests__/agent-resolution-llm-free.test.js +9 -2
  4. package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -1
  5. package/dist/__tests__/broker-prompt.test.d.ts +10 -0
  6. package/dist/__tests__/broker-prompt.test.d.ts.map +1 -0
  7. package/dist/__tests__/broker-prompt.test.js +129 -0
  8. package/dist/__tests__/broker-prompt.test.js.map +1 -0
  9. package/dist/__tests__/broker-step-active-turns.test.d.ts +20 -0
  10. package/dist/__tests__/broker-step-active-turns.test.d.ts.map +1 -0
  11. package/dist/__tests__/broker-step-active-turns.test.js +428 -0
  12. package/dist/__tests__/broker-step-active-turns.test.js.map +1 -0
  13. package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts +13 -0
  14. package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts.map +1 -0
  15. package/dist/__tests__/broker-step-turn-chain-phase2.test.js +429 -0
  16. package/dist/__tests__/broker-step-turn-chain-phase2.test.js.map +1 -0
  17. package/dist/__tests__/config.test.js +33 -37
  18. package/dist/__tests__/config.test.js.map +1 -1
  19. package/dist/__tests__/e2e-broker-step-suspend.test.d.ts +18 -0
  20. package/dist/__tests__/e2e-broker-step-suspend.test.d.ts.map +1 -0
  21. package/dist/__tests__/e2e-broker-step-suspend.test.js +313 -0
  22. package/dist/__tests__/e2e-broker-step-suspend.test.js.map +1 -0
  23. package/dist/__tests__/e2e-broker-step.test.d.ts +13 -0
  24. package/dist/__tests__/e2e-broker-step.test.d.ts.map +1 -0
  25. package/dist/__tests__/e2e-broker-step.test.js +278 -0
  26. package/dist/__tests__/e2e-broker-step.test.js.map +1 -0
  27. package/dist/__tests__/e2e-mock-agent.test.js +1 -1
  28. package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
  29. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts +28 -0
  30. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts.map +1 -0
  31. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js +322 -0
  32. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js.map +1 -0
  33. package/dist/__tests__/log-tag-validity.test.d.ts +2 -0
  34. package/dist/__tests__/log-tag-validity.test.d.ts.map +1 -0
  35. package/dist/__tests__/log-tag-validity.test.js +110 -0
  36. package/dist/__tests__/log-tag-validity.test.js.map +1 -0
  37. package/dist/__tests__/setup-agent-discovery.test.js +35 -23
  38. package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
  39. package/dist/__tests__/setup-no-llm.test.js +5 -2
  40. package/dist/__tests__/setup-no-llm.test.js.map +1 -1
  41. package/dist/__tests__/step-ask.test.js +9 -6
  42. package/dist/__tests__/step-ask.test.js.map +1 -1
  43. package/dist/__tests__/step-show-json.test.js +5 -5
  44. package/dist/__tests__/step-show-json.test.js.map +1 -1
  45. package/dist/__tests__/step-show-text.test.d.ts +2 -0
  46. package/dist/__tests__/step-show-text.test.d.ts.map +1 -0
  47. package/dist/__tests__/step-show-text.test.js +192 -0
  48. package/dist/__tests__/step-show-text.test.js.map +1 -0
  49. package/dist/__tests__/step-turns-cli-subprocess.test.d.ts +21 -0
  50. package/dist/__tests__/step-turns-cli-subprocess.test.d.ts.map +1 -0
  51. package/dist/__tests__/step-turns-cli-subprocess.test.js +356 -0
  52. package/dist/__tests__/step-turns-cli-subprocess.test.js.map +1 -0
  53. package/dist/__tests__/step-turns-panorama-phase3.test.d.ts +21 -0
  54. package/dist/__tests__/step-turns-panorama-phase3.test.d.ts.map +1 -0
  55. package/dist/__tests__/step-turns-panorama-phase3.test.js +476 -0
  56. package/dist/__tests__/step-turns-panorama-phase3.test.js.map +1 -0
  57. package/dist/__tests__/step-turns.test.d.ts +24 -0
  58. package/dist/__tests__/step-turns.test.d.ts.map +1 -0
  59. package/dist/__tests__/step-turns.test.js +646 -0
  60. package/dist/__tests__/step-turns.test.js.map +1 -0
  61. package/dist/__tests__/store-turn-chain.test.d.ts +2 -0
  62. package/dist/__tests__/store-turn-chain.test.d.ts.map +1 -0
  63. package/dist/__tests__/store-turn-chain.test.js +341 -0
  64. package/dist/__tests__/store-turn-chain.test.js.map +1 -0
  65. package/dist/__tests__/thread-agent-failure-suspended.test.js +3 -3
  66. package/dist/__tests__/thread-agent-failure-suspended.test.js.map +1 -1
  67. package/dist/__tests__/thread-list-limit-offset.test.d.ts +24 -0
  68. package/dist/__tests__/thread-list-limit-offset.test.d.ts.map +1 -0
  69. package/dist/__tests__/thread-list-limit-offset.test.js +254 -0
  70. package/dist/__tests__/thread-list-limit-offset.test.js.map +1 -0
  71. package/dist/__tests__/thread-list-template-ms-date.test.js +7 -2
  72. package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -1
  73. package/dist/__tests__/thread-poke.test.js +6 -6
  74. package/dist/__tests__/thread-poke.test.js.map +1 -1
  75. package/dist/__tests__/thread-resume.test.js +2 -2
  76. package/dist/__tests__/thread-resume.test.js.map +1 -1
  77. package/dist/__tests__/thread-suspend-step.test.js +1 -1
  78. package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
  79. package/dist/__tests__/thread.test.js +28 -14
  80. package/dist/__tests__/thread.test.js.map +1 -1
  81. package/dist/cli.js +910 -344
  82. package/dist/cli.js.map +1 -1
  83. package/dist/commands/broker-step.d.ts +117 -0
  84. package/dist/commands/broker-step.d.ts.map +1 -0
  85. package/dist/commands/broker-step.js +654 -0
  86. package/dist/commands/broker-step.js.map +1 -0
  87. package/dist/commands/config.d.ts.map +1 -1
  88. package/dist/commands/config.js +2 -23
  89. package/dist/commands/config.js.map +1 -1
  90. package/dist/commands/prompt.d.ts.map +1 -1
  91. package/dist/commands/prompt.js +43 -51
  92. package/dist/commands/prompt.js.map +1 -1
  93. package/dist/commands/setup.d.ts +6 -4
  94. package/dist/commands/setup.d.ts.map +1 -1
  95. package/dist/commands/setup.js +24 -27
  96. package/dist/commands/setup.js.map +1 -1
  97. package/dist/commands/step.d.ts +54 -6
  98. package/dist/commands/step.d.ts.map +1 -1
  99. package/dist/commands/step.js +484 -134
  100. package/dist/commands/step.js.map +1 -1
  101. package/dist/commands/thread.d.ts +4 -0
  102. package/dist/commands/thread.d.ts.map +1 -1
  103. package/dist/commands/thread.js +77 -151
  104. package/dist/commands/thread.js.map +1 -1
  105. package/dist/output-mappers.d.ts +8 -0
  106. package/dist/output-mappers.d.ts.map +1 -1
  107. package/dist/output-mappers.js +72 -18
  108. package/dist/output-mappers.js.map +1 -1
  109. package/dist/schemas.d.ts +3 -0
  110. package/dist/schemas.d.ts.map +1 -1
  111. package/dist/schemas.js +17 -3
  112. package/dist/schemas.js.map +1 -1
  113. package/dist/store.d.ts +147 -1
  114. package/dist/store.d.ts.map +1 -1
  115. package/dist/store.js +254 -1
  116. package/dist/store.js.map +1 -1
  117. package/dist/text-renderers.d.ts.map +1 -1
  118. package/dist/text-renderers.js +27 -2
  119. package/dist/text-renderers.js.map +1 -1
  120. package/package.json +7 -5
  121. package/src/__tests__/agent-resolution-llm-free.test.ts +14 -2
  122. package/src/__tests__/broker-prompt.test.ts +142 -0
  123. package/src/__tests__/broker-step-active-turns.test.ts +509 -0
  124. package/src/__tests__/broker-step-turn-chain-phase2.test.ts +525 -0
  125. package/src/__tests__/config.test.ts +35 -39
  126. package/src/__tests__/e2e-broker-step-suspend.test.ts +351 -0
  127. package/src/__tests__/e2e-broker-step.test.ts +320 -0
  128. package/src/__tests__/e2e-mock-agent.test.ts +1 -1
  129. package/src/__tests__/e2e-thread-resume-timeout-suspend.test.ts +360 -0
  130. package/src/__tests__/log-tag-validity.test.ts +124 -0
  131. package/src/__tests__/setup-agent-discovery.test.ts +35 -23
  132. package/src/__tests__/setup-no-llm.test.ts +5 -2
  133. package/src/__tests__/step-ask.test.ts +9 -6
  134. package/src/__tests__/step-show-json.test.ts +5 -5
  135. package/src/__tests__/step-show-text.test.ts +236 -0
  136. package/src/__tests__/step-turns-cli-subprocess.test.ts +411 -0
  137. package/src/__tests__/step-turns-panorama-phase3.test.ts +579 -0
  138. package/src/__tests__/step-turns.test.ts +734 -0
  139. package/src/__tests__/store-turn-chain.test.ts +386 -0
  140. package/src/__tests__/thread-agent-failure-suspended.test.ts +3 -3
  141. package/src/__tests__/thread-list-limit-offset.test.ts +305 -0
  142. package/src/__tests__/thread-list-template-ms-date.test.ts +7 -2
  143. package/src/__tests__/thread-poke.test.ts +6 -6
  144. package/src/__tests__/thread-resume.test.ts +2 -2
  145. package/src/__tests__/thread-suspend-step.test.ts +1 -1
  146. package/src/__tests__/thread.test.ts +29 -15
  147. package/src/cli.ts +1056 -483
  148. package/src/commands/broker-step.ts +913 -0
  149. package/src/commands/config.ts +2 -24
  150. package/src/commands/prompt.ts +43 -51
  151. package/src/commands/setup.ts +25 -29
  152. package/src/commands/step.ts +645 -176
  153. package/src/commands/thread.ts +87 -192
  154. package/src/output-mappers.ts +99 -21
  155. package/src/schemas.ts +32 -2
  156. package/src/store.ts +297 -2
  157. package/src/text-renderers.ts +35 -2
  158. package/dist/__tests__/adapter-json-roundtrip.test.d.ts +0 -2
  159. package/dist/__tests__/adapter-json-roundtrip.test.d.ts.map +0 -1
  160. package/dist/__tests__/adapter-json-roundtrip.test.js +0 -160
  161. package/dist/__tests__/adapter-json-roundtrip.test.js.map +0 -1
  162. package/dist/__tests__/spawn-agent-json.test.d.ts +0 -2
  163. package/dist/__tests__/spawn-agent-json.test.d.ts.map +0 -1
  164. package/dist/__tests__/spawn-agent-json.test.js +0 -79
  165. package/dist/__tests__/spawn-agent-json.test.js.map +0 -1
  166. package/src/__tests__/adapter-json-roundtrip.test.ts +0 -193
  167. package/src/__tests__/spawn-agent-json.test.ts +0 -100
package/dist/cli.js CHANGED
@@ -1,18 +1,31 @@
1
1
  #!/usr/bin/env -S node --disable-warning=ExperimentalWarning
2
- import { Command } from "commander";
2
+ import { readFileSync } from "node:fs";
3
+ import { dirname, join } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { createCLI } from "@ocas/cli-kit";
6
+ import { z } from "zod";
3
7
  import { cmdConfigGet, cmdConfigList, cmdConfigSet } from "./commands/config.js";
4
8
  import { cmdLogClean, cmdLogList, cmdLogShow } from "./commands/log.js";
5
9
  import { cmdPromptAdapterDeveloping, cmdPromptBootstrap, cmdPromptList, cmdPromptUsage, cmdPromptWorkflowAuthoring, } from "./commands/prompt.js";
6
10
  import { cmdSetup, cmdSetupInteractive } from "./commands/setup.js";
7
- import { cmdStepAsk, cmdStepFork, cmdStepList, cmdStepRead, cmdStepShow } from "./commands/step.js";
11
+ import { cmdStepAsk, cmdStepFork, cmdStepList, cmdStepRead, cmdStepShow, cmdStepTurns, } from "./commands/step.js";
8
12
  import { cmdThreadCancel, cmdThreadExec, cmdThreadJoin, cmdThreadList, cmdThreadPoke, cmdThreadRead, cmdThreadResume, cmdThreadShow, cmdThreadStart, cmdThreadStop, THREAD_READ_DEFAULT_QUOTA, } from "./commands/thread.js";
9
13
  import { parseTimeInput } from "./commands/thread-time-parser.js";
10
14
  import { cmdWorkflowAdd, cmdWorkflowList, cmdWorkflowShow, cmdWorkflowValidate, } from "./commands/workflow.js";
11
15
  import { formatOutput, isOutputFormat, SUPPORTED_FORMATS, writeEnvelope, } from "./format.js";
12
16
  import { toStepDetailPayload, toStepListPayload, toThreadExecPayload, toThreadListPayload, toThreadStartPayload, toThreadStatusPayload, toValidateResultPayload, toWorkflowAddPayload, toWorkflowDetailPayload, toWorkflowListPayload, } from "./output-mappers.js";
13
17
  import { createUwfStore, resolveStorageRoot } from "./store.js";
18
+ // --- Package version (readFileSync replaces dynamic import) ---
19
+ const __dirname = dirname(fileURLToPath(import.meta.url));
20
+ const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
21
+ const VERSION = pkg.version;
22
+ // --- Module-level state (cli-kit v0.2.1 workaround: no global --format) ---
23
+ // Parsed from argv early, before cli-kit sees it.
24
+ let formatOverride = null;
25
+ // Parsed from argv early — cli-kit rejects values starting with `-`.
26
+ let countOverride = null;
14
27
  function getFormat() {
15
- const raw = program.opts().format;
28
+ const raw = formatOverride ?? "text";
16
29
  if (!isOutputFormat(raw)) {
17
30
  process.stderr.write(`Invalid --format: ${raw}. Must be one of: ${SUPPORTED_FORMATS.join(", ")}\n`);
18
31
  process.exit(1);
@@ -34,121 +47,18 @@ async function writeOutput(payload, schemaName, storageRoot) {
34
47
  * (the default) it renders via the per-command registry when available
35
48
  * and falls back to JSON.
36
49
  */
37
- function writeRawOutput(data, commandPath) {
50
+ function writeRawOutput(data, commandPath = null) {
38
51
  const fmt = getFormat();
39
- process.stdout.write(`${formatOutput(data, fmt, commandPath)}\n`);
52
+ process.stdout.write(`${formatOutput(data, fmt, commandPath ?? undefined)}\n`);
40
53
  }
41
54
  function runAction(action) {
42
- action().catch((e) => {
55
+ return action().catch((e) => {
43
56
  const message = e instanceof Error ? e.message : String(e);
44
57
  process.stderr.write(`${message}\n`);
45
58
  process.exit(1);
46
59
  });
47
60
  }
48
- const program = new Command();
49
- // eslint-disable-next-line -- dynamic import for version
50
- const pkg = await import("../package.json", { with: { type: "json" } });
51
- program
52
- .name("uwf")
53
- .description("Stateless workflow CLI\n\n" +
54
- "Four-layer architecture:\n" +
55
- " workflow → thread → step → turn")
56
- .version(pkg.default.version, "-V, --version");
57
- program.option("--format <fmt>", "Output format: text (default), json, yaml, raw-json, raw-yaml", "text");
58
- const workflow = program
59
- .command("workflow")
60
- .description("Workflow definitions (layer 1: templates)");
61
- workflow
62
- .command("add")
63
- .description("Register a workflow from YAML")
64
- .argument("<file>", "Workflow YAML file")
65
- .action((file) => {
66
- const storageRoot = resolveStorageRoot();
67
- runAction(async () => {
68
- const result = await cmdWorkflowAdd(storageRoot, file);
69
- await writeOutput(toWorkflowAddPayload(result), "workflow-add", storageRoot);
70
- });
71
- });
72
- workflow
73
- .command("validate")
74
- .description("Validate a workflow YAML without registering it (CI-friendly)")
75
- .argument("<file>", "Workflow YAML file")
76
- .action((file) => {
77
- const storageRoot = resolveStorageRoot();
78
- runAction(async () => {
79
- const errors = await cmdWorkflowValidate(file);
80
- await writeOutput(toValidateResultPayload(errors), "validate-result", storageRoot);
81
- if (errors.length > 0) {
82
- process.exit(1);
83
- }
84
- });
85
- });
86
- workflow
87
- .command("show")
88
- .description("Show a workflow by name or CAS hash")
89
- .argument("<id>", "Workflow name or hash")
90
- .action((id) => {
91
- const storageRoot = resolveStorageRoot();
92
- runAction(async () => {
93
- const result = await cmdWorkflowShow(storageRoot, id, process.cwd());
94
- await writeOutput(toWorkflowDetailPayload(result), "workflow-detail", storageRoot);
95
- });
96
- });
97
- workflow
98
- .command("list")
99
- .description("List registered workflows")
100
- .action(() => {
101
- const storageRoot = resolveStorageRoot();
102
- runAction(async () => {
103
- const result = await cmdWorkflowList(storageRoot, process.cwd());
104
- await writeOutput(toWorkflowListPayload(result), "workflow-list", storageRoot);
105
- });
106
- });
107
- const thread = program.command("thread").description("Thread execution (layer 2: instances)");
108
- thread
109
- .command("start")
110
- .description("Create a thread without executing")
111
- .argument("<workflow>", "Workflow name or hash")
112
- .requiredOption("-p, --prompt <text>", "User prompt")
113
- .option("--cwd <path>", "Working directory for thread execution (default: process.cwd())")
114
- .action((workflow, opts) => {
115
- const storageRoot = resolveStorageRoot();
116
- runAction(async () => {
117
- const result = await cmdThreadStart(storageRoot, workflow, opts.prompt, process.cwd(), opts.cwd ?? process.cwd());
118
- await writeOutput(toThreadStartPayload(result), "thread-start", storageRoot);
119
- });
120
- });
121
- thread
122
- .command("exec")
123
- .description("Execute one or more steps")
124
- .argument("<thread-id>", "Thread ULID")
125
- .option("--agent <cmd>", "Override agent command")
126
- .option("-c, --count <number>", "Number of steps to run (default: 1)")
127
- .option("--background", "Run in background and return immediately")
128
- .option("--_background-worker", "Internal flag for background worker process", false)
129
- .action((threadId, opts) => {
130
- const storageRoot = resolveStorageRoot();
131
- runAction(async () => {
132
- const agentOverride = opts.agent ?? null;
133
- const count = opts.count !== undefined ? Number(opts.count) : 1;
134
- const background = opts.background ?? false;
135
- const backgroundWorker = opts._backgroundWorker ?? false;
136
- const results = await cmdThreadExec(storageRoot, threadId, agentOverride, count, background, backgroundWorker);
137
- await writeOutput(toThreadExecPayload(results), "thread-exec", storageRoot);
138
- });
139
- });
140
- thread
141
- .command("show")
142
- .description("Show thread head pointer")
143
- .argument("<thread-id>", "Thread ULID")
144
- .action((threadId) => {
145
- const storageRoot = resolveStorageRoot();
146
- runAction(async () => {
147
- const result = await cmdThreadShow(storageRoot, threadId);
148
- await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
149
- });
150
- });
151
- // Helper functions for thread list command parsing
61
+ // --- Helper functions for thread list / step turns parsing (unchanged) ---
152
62
  function parseStatusFilter(status) {
153
63
  if (status === undefined)
154
64
  return null;
@@ -203,87 +113,755 @@ function parsePaginationOptions(skip, take) {
203
113
  }
204
114
  return { skip: skipVal, take: takeVal };
205
115
  }
116
+ /**
117
+ * Parse a `step turns` `--limit`/`--offset` value into a non-negative integer, or
118
+ * `null` when the flag is absent (the OCAS `ListOptions` "no limit" / offset-0
119
+ * convention). `--limit 0` is a legal value (renders no turns); negative or
120
+ * non-numeric values are a CLI usage error (exit non-zero). The `flag` label is
121
+ * used verbatim in the error message.
122
+ */
123
+ function parseTurnsPageOption(flag, value) {
124
+ if (value === undefined) {
125
+ return null;
126
+ }
127
+ const trimmed = value.trim();
128
+ if (!/^\d+$/.test(trimmed)) {
129
+ process.stderr.write(`${flag} must be a non-negative integer\n`);
130
+ process.exit(1);
131
+ }
132
+ return Number.parseInt(trimmed, 10);
133
+ }
134
+ /**
135
+ * Resolve `thread list` pagination from both the canonical repo-wide
136
+ * `ListOptions` vocabulary (`--limit`/`--offset`, as used by `step turns`) and
137
+ * the backward-compatible legacy aliases (`--skip`/`--take`). The canonical
138
+ * flags map onto the existing `cmdThreadList` parameters: `--limit` → `take`
139
+ * (max items), `--offset` → `skip` (items skipped from the front of the
140
+ * newest-first list). When both a canonical flag and its legacy alias are
141
+ * supplied, the canonical flag wins and the alias is the fallback.
142
+ * `--limit`/`--offset` are validated via `parseTurnsPageOption` (same
143
+ * non-negative-integer rule and flag-named error as `step turns`); `--limit 0`
144
+ * is legal and yields no items (the `ListOptions` "no limit" convention treats
145
+ * an absent flag, not 0, as "all items").
146
+ */
147
+ function resolveThreadListPagination(flags) {
148
+ const legacy = parsePaginationOptions(flags.skip, flags.take);
149
+ const limit = parseTurnsPageOption("--limit", flags.limit);
150
+ const offset = parseTurnsPageOption("--offset", flags.offset);
151
+ return {
152
+ skip: offset ?? legacy.skip,
153
+ take: limit ?? legacy.take,
154
+ };
155
+ }
156
+ // --- Positional arg helper (cli-kit workaround: custom missing-arg message) ---
157
+ // cli-kit emits "Missing positional arguments" as NDJSON; tests expect a
158
+ // plain "missing required argument" message on stderr. We don't declare
159
+ // .arg() on commands and read positionals from the _positionals field that
160
+ // cli-kit injects into the flags object.
161
+ function getPositionals(flags) {
162
+ const p = flags._positionals;
163
+ return Array.isArray(p) ? p : [];
164
+ }
165
+ function requirePositional(flags, index, name) {
166
+ const positionals = getPositionals(flags);
167
+ const value = positionals[index];
168
+ if (value === undefined) {
169
+ process.stderr.write(`Error: missing required argument: ${name}\n`);
170
+ process.exit(1);
171
+ }
172
+ return value;
173
+ }
174
+ // --- Help text (cli-kit v0.2.1 workaround: no per-command --help) ---
175
+ const TOP_LEVEL_HELP = `Usage: uwf <command> [options]
176
+
177
+ Stateless workflow CLI
178
+
179
+ Four-layer architecture:
180
+ workflow → thread → step → turn
181
+
182
+ Commands:
183
+ workflow Workflow definitions (layer 1: templates)
184
+ thread Thread execution (layer 2: instances)
185
+ step Step results (layer 3: single cycle)
186
+ prompt Built-in prompt references for agents
187
+ setup Configure the default agent
188
+ log Process-level debug logs
189
+ config Configuration management
190
+
191
+ Standard flags:
192
+ --format <fmt> Output format: text (default), json, yaml, raw-json, raw-yaml
193
+ -V, --version Show version
194
+ -h, --help Show this help
195
+ `;
196
+ const PROMPT_HELP = `Usage: uwf prompt <command>
197
+
198
+ Built-in prompt references for agents
199
+
200
+ Commands:
201
+ usage Print the usage reference (CLI guide + typical workflows)
202
+ bootstrap Print setup instructions for installing uwf skills
203
+ workflow-authoring Print the workflow authoring reference (YAML design guide)
204
+ adapter-developing Print the adapter developing reference (building agent adapters)
205
+ list List all available prompt names
206
+ `;
207
+ const WORKFLOW_HELP = `Usage: uwf workflow <command>
208
+
209
+ Workflow definitions (layer 1: templates)
210
+
211
+ Commands:
212
+ add Register a workflow from YAML
213
+ validate Validate a workflow YAML without registering it (CI-friendly)
214
+ show Show a workflow by name or CAS hash
215
+ list List registered workflows
216
+ `;
217
+ const WORKFLOW_ADD_HELP = `Usage: uwf workflow add <file>
218
+
219
+ Register a workflow from YAML
220
+
221
+ Arguments:
222
+ file Workflow YAML file
223
+ `;
224
+ const WORKFLOW_VALIDATE_HELP = `Usage: uwf workflow validate <file>
225
+
226
+ Validate a workflow YAML without registering it (CI-friendly)
227
+
228
+ Arguments:
229
+ file Workflow YAML file
230
+ `;
231
+ const WORKFLOW_SHOW_HELP = `Usage: uwf workflow show <id>
232
+
233
+ Show a workflow by name or CAS hash
234
+
235
+ Arguments:
236
+ id Workflow name or hash
237
+ `;
238
+ const WORKFLOW_LIST_HELP = `Usage: uwf workflow list
239
+
240
+ List registered workflows
241
+ `;
242
+ const THREAD_HELP = `Usage: uwf thread <command>
243
+
244
+ Thread execution (layer 2: instances)
245
+
246
+ Commands:
247
+ start Create a thread without executing
248
+ exec Execute one or more steps
249
+ show Show thread head pointer
250
+ list List threads (defaults to active: idle + running + corrupt)
251
+ resume Resume a suspended thread and re-run the suspended role
252
+ poke Re-run the head step's agent with a supplementary prompt
253
+ stop Stop background execution of a thread (keep thread active)
254
+ cancel Cancel a thread (stop execution and move to history)
255
+ join Block until a running thread finishes, then return the final result
256
+ read Read thread context as human-readable markdown
257
+ `;
258
+ const THREAD_START_HELP = `Usage: uwf thread start <workflow> [options]
259
+
260
+ Create a thread without executing
261
+
262
+ Arguments:
263
+ workflow Workflow name or hash
264
+
265
+ Options:
266
+ -p, --prompt <text> User prompt (required)
267
+ --cwd <path> Working directory for thread execution (default: process.cwd())
268
+ `;
269
+ const THREAD_EXEC_HELP = `Usage: uwf thread exec <thread-id> [options]
270
+
271
+ Execute one or more steps
272
+
273
+ Arguments:
274
+ thread-id Thread ULID
275
+
276
+ Options:
277
+ --agent <cmd> Override agent command
278
+ -c, --count <number> Number of steps to run (default: 1)
279
+ --background Run in background and return immediately
280
+ `;
281
+ const THREAD_SHOW_HELP = `Usage: uwf thread show <thread-id>
282
+
283
+ Show thread head pointer
284
+
285
+ Arguments:
286
+ thread-id Thread ULID
287
+ `;
288
+ const THREAD_LIST_HELP = `Usage: uwf thread list [options]
289
+
290
+ List threads (defaults to active: idle + running + corrupt)
291
+
292
+ Options:
293
+ --status <status> Filter by status: idle, running, end, cancelled, active, or comma-separated
294
+ --all Show all threads regardless of status
295
+ --after <date> Filter threads created after this date
296
+ --before <date> Filter threads created before this date
297
+ --limit <n> Return at most n threads (newest first)
298
+ --offset <m> Skip the first m threads (newest first)
299
+ --take <n> Alias for --limit
300
+ --skip <n> Alias for --offset
301
+ `;
302
+ const THREAD_RESUME_HELP = `Usage: uwf thread resume <thread-id> [options]
303
+
304
+ Resume a suspended thread and re-run the suspended role
305
+
306
+ Arguments:
307
+ thread-id Thread ULID
308
+
309
+ Options:
310
+ -p, --prompt <text> Supplementary info to append to the resume prompt
311
+ --agent <cmd> Override agent command
312
+ `;
313
+ const THREAD_POKE_HELP = `Usage: uwf thread poke <thread-id> [options]
314
+
315
+ Re-run the head step's agent with a supplementary prompt (replaces head step)
316
+
317
+ Arguments:
318
+ thread-id Thread ULID
319
+
320
+ Options:
321
+ -p, --prompt <text> Supplementary prompt for the agent (required)
322
+ --agent <cmd> Override agent command (defaults to head step's agent)
323
+ `;
324
+ const THREAD_STOP_HELP = `Usage: uwf thread stop <thread-id>
325
+
326
+ Stop background execution of a thread (keep thread active)
327
+
328
+ Arguments:
329
+ thread-id Thread ULID
330
+ `;
331
+ const THREAD_CANCEL_HELP = `Usage: uwf thread cancel <thread-id>
332
+
333
+ Cancel a thread (stop execution and move to history)
334
+
335
+ Arguments:
336
+ thread-id Thread ULID
337
+ `;
338
+ const THREAD_JOIN_HELP = `Usage: uwf thread join <thread-id> [options]
339
+
340
+ Block until a running thread finishes, then return the final result
341
+
342
+ Arguments:
343
+ thread-id Thread ULID
344
+
345
+ Options:
346
+ --timeout <seconds> Max seconds to wait before giving up
347
+ `;
348
+ const THREAD_READ_HELP = `Usage: uwf thread read <thread-id> [options]
349
+
350
+ Read thread context as human-readable markdown
351
+
352
+ Arguments:
353
+ thread-id Thread ULID
354
+
355
+ Options:
356
+ --quota <chars> Max output characters
357
+ --before <step-hash> Load steps before this hash (exclusive)
358
+ --start Include start step in output
359
+ `;
360
+ const STEP_HELP = `Usage: uwf step <command>
361
+
362
+ Step results (layer 3: single cycle)
363
+
364
+ Commands:
365
+ list List all steps in a thread
366
+ show Show details of a specific step
367
+ ask Ask a follow-up question to a historical step's agent
368
+ read Read a step's turns as human-readable markdown
369
+ turns Show all turns across a thread's steps
370
+ fork Fork a thread from a specific step
371
+ `;
372
+ const STEP_LIST_HELP = `Usage: uwf step list <thread-id>
373
+
374
+ List all steps in a thread
375
+
376
+ Arguments:
377
+ thread-id Thread ULID
378
+ `;
379
+ const STEP_SHOW_HELP = `Usage: uwf step show <step-hash>
380
+
381
+ Show details of a specific step
382
+
383
+ Arguments:
384
+ step-hash CAS hash of the StepNode
385
+ `;
386
+ const STEP_ASK_HELP = `Usage: uwf step ask <step-hash> [options]
387
+
388
+ Ask a follow-up question to a historical step's agent (read-only; no thread mutation)
389
+
390
+ Arguments:
391
+ step-hash CAS hash of the StepNode to query
392
+
393
+ Options:
394
+ -p, --prompt <text> Question to ask the step's agent (required)
395
+ --agent <cmd> Override agent command
396
+ --no-fork Skip session-fork; spawn fresh ask session
397
+ `;
398
+ const STEP_READ_HELP = `Usage: uwf step read <step-hash> [options]
399
+
400
+ Read a step's turns as human-readable markdown
401
+
402
+ Arguments:
403
+ step-hash CAS hash of the StepNode
404
+
405
+ Options:
406
+ --quota <chars> Max output characters (default: 4000)
407
+ --prompt Show the assembled prompt sent to the agent
408
+ `;
409
+ const STEP_TURNS_HELP = `Usage: uwf step turns <thread-id> [options]
410
+
411
+ Show all turns across a thread's steps (the whole-chain panorama)
412
+
413
+ Arguments:
414
+ thread-id Thread ULID
415
+
416
+ Options:
417
+ --role <role> Filter to one role's steps across the whole chain
418
+ --live Follow the in-flight step's turns
419
+ --limit <n> Max turns to show from the flattened cross-step sequence
420
+ --offset <n> Skip the first N turns of the flattened cross-step sequence
421
+ `;
422
+ const STEP_FORK_HELP = `Usage: uwf step fork <step-hash>
423
+
424
+ Fork a thread from a specific step
425
+
426
+ Arguments:
427
+ step-hash CAS hash of the StartNode or StepNode to fork from
428
+ `;
429
+ const SETUP_HELP = `Usage: uwf setup [options]
430
+
431
+ Configure the default agent. Run without --agent for interactive wizard.
432
+
433
+ Options:
434
+ --agent <name> Default agent adapter (e.g. builtin, or a Sumeru gateway alias)
435
+ `;
436
+ const LOG_HELP = `Usage: uwf log <command>
437
+
438
+ Process-level debug logs
439
+
440
+ Commands:
441
+ list List log files with sizes
442
+ show Show and filter log entries
443
+ clean Delete log files older than given date
444
+ `;
445
+ const LOG_LIST_HELP = `Usage: uwf log list
446
+
447
+ List log files with sizes
448
+ `;
449
+ const LOG_SHOW_HELP = `Usage: uwf log show [options]
450
+
451
+ Show and filter log entries
452
+
453
+ Options:
454
+ --thread <thread-id> Filter by thread ID
455
+ --process <pid> Filter by process ID
456
+ --date <date> Filter by date (YYYY-MM-DD)
457
+ `;
458
+ const LOG_CLEAN_HELP = `Usage: uwf log clean --before <date>
459
+
460
+ Delete log files older than given date
461
+
462
+ Options:
463
+ --before <date> Delete files before this date (YYYY-MM-DD) (required)
464
+ `;
465
+ const CONFIG_HELP = `Usage: uwf config <command>
466
+
467
+ Configuration management
468
+
469
+ Commands:
470
+ list Display all configuration values (masks API keys)
471
+ get Get a specific configuration value
472
+ set Set a specific configuration value
473
+ `;
474
+ const CONFIG_LIST_HELP = `Usage: uwf config list
475
+
476
+ Display all configuration values (masks API keys)
477
+ `;
478
+ const CONFIG_GET_HELP = `Usage: uwf config get <key>
479
+
480
+ Get a specific configuration value
481
+
482
+ Arguments:
483
+ key Dot-notation path to config value
484
+ `;
485
+ const CONFIG_SET_HELP = `Usage: uwf config set <key> <value>
486
+
487
+ Set a specific configuration value
488
+
489
+ Arguments:
490
+ key Dot-notation path to config value
491
+ value New value (use JSON array for 'args' key)
492
+ `;
493
+ const HELP_MAP = {
494
+ "": TOP_LEVEL_HELP,
495
+ prompt: PROMPT_HELP,
496
+ workflow: WORKFLOW_HELP,
497
+ "workflow add": WORKFLOW_ADD_HELP,
498
+ "workflow validate": WORKFLOW_VALIDATE_HELP,
499
+ "workflow show": WORKFLOW_SHOW_HELP,
500
+ "workflow list": WORKFLOW_LIST_HELP,
501
+ thread: THREAD_HELP,
502
+ "thread start": THREAD_START_HELP,
503
+ "thread exec": THREAD_EXEC_HELP,
504
+ "thread show": THREAD_SHOW_HELP,
505
+ "thread list": THREAD_LIST_HELP,
506
+ "thread resume": THREAD_RESUME_HELP,
507
+ "thread poke": THREAD_POKE_HELP,
508
+ "thread stop": THREAD_STOP_HELP,
509
+ "thread cancel": THREAD_CANCEL_HELP,
510
+ "thread join": THREAD_JOIN_HELP,
511
+ "thread read": THREAD_READ_HELP,
512
+ step: STEP_HELP,
513
+ "step list": STEP_LIST_HELP,
514
+ "step show": STEP_SHOW_HELP,
515
+ "step ask": STEP_ASK_HELP,
516
+ "step read": STEP_READ_HELP,
517
+ "step turns": STEP_TURNS_HELP,
518
+ "step fork": STEP_FORK_HELP,
519
+ setup: SETUP_HELP,
520
+ log: LOG_HELP,
521
+ "log list": LOG_LIST_HELP,
522
+ "log show": LOG_SHOW_HELP,
523
+ "log clean": LOG_CLEAN_HELP,
524
+ config: CONFIG_HELP,
525
+ "config list": CONFIG_LIST_HELP,
526
+ "config get": CONFIG_GET_HELP,
527
+ "config set": CONFIG_SET_HELP,
528
+ };
529
+ // --- Early intercepts (cli-kit v0.2.1 workarounds) ---
530
+ /** Print help text for the command path extracted from argv, then exit. */
531
+ function printHelp(argv) {
532
+ const helpIdx = argv.findIndex((t) => t === "--help" || t === "-h");
533
+ const tokens = helpIdx >= 0 ? argv.slice(0, helpIdx).filter((t) => !t.startsWith("-")) : [];
534
+ for (let len = tokens.length; len >= 0; len--) {
535
+ const path = tokens.slice(0, len).join(" ");
536
+ const text = HELP_MAP[path];
537
+ if (text !== undefined) {
538
+ process.stdout.write(text);
539
+ process.exit(0);
540
+ }
541
+ }
542
+ process.stdout.write(TOP_LEVEL_HELP);
543
+ process.exit(0);
544
+ }
545
+ /** Intercept deprecated commands before cli-kit parsing. Prints message + exit(1). */
546
+ function handleDeprecated(argv) {
547
+ const [cmd, sub] = argv;
548
+ if (cmd === "workflow" && sub === "put") {
549
+ process.stderr.write(`Error: Command 'workflow put' has been removed.
550
+ Use 'workflow add' instead.
551
+
552
+ For more information, see: uwf help workflow add
553
+ `);
554
+ process.exit(1);
555
+ }
556
+ if (cmd === "thread") {
557
+ if (sub === "step") {
558
+ process.stderr.write(`Error: Command 'thread step' has been removed.
559
+ Use 'thread exec' instead.
560
+
561
+ For more information, see: uwf help thread exec
562
+ `);
563
+ process.exit(1);
564
+ }
565
+ if (sub === "steps") {
566
+ process.stderr.write(`Error: Command 'thread steps' has been removed.
567
+ Use 'step list' instead.
568
+
569
+ For more information, see: uwf help step list
570
+ `);
571
+ process.exit(1);
572
+ }
573
+ if (sub === "step-details") {
574
+ process.stderr.write(`Error: Command 'thread step-details' has been removed.
575
+ Use 'step show' instead.
576
+
577
+ For more information, see: uwf help step show
578
+ `);
579
+ process.exit(1);
580
+ }
581
+ if (sub === "fork") {
582
+ process.stderr.write(`Error: Command 'thread fork' has been removed.
583
+ Use 'step fork' instead.
584
+
585
+ For more information, see: uwf help step fork
586
+ `);
587
+ process.exit(1);
588
+ }
589
+ if (sub === "kill") {
590
+ process.stderr.write(`Error: Command 'thread kill' has been removed.
591
+ Use 'thread stop' to stop background execution (keep thread active),
592
+ or 'thread cancel' to cancel and archive the thread.
593
+
594
+ For more information, see:
595
+ uwf help thread stop
596
+ uwf help thread cancel
597
+ `);
598
+ process.exit(1);
599
+ }
600
+ if (sub === "running") {
601
+ process.stderr.write(`Error: Command 'thread running' has been removed.
602
+ Use 'thread list --status running' instead.
603
+
604
+ For more information, see: uwf help thread list
605
+ `);
606
+ process.exit(1);
607
+ }
608
+ }
609
+ }
610
+ /** Strip `--format <value>` / `--format=value` from argv, returning cleaned argv. */
611
+ function stripFormatFlag(argv) {
612
+ const out = [];
613
+ for (let i = 0; i < argv.length; i++) {
614
+ const token = argv[i];
615
+ if (token === "--format") {
616
+ const value = argv[i + 1];
617
+ if (value !== undefined) {
618
+ formatOverride = value;
619
+ i++;
620
+ }
621
+ continue;
622
+ }
623
+ if (token.startsWith("--format=")) {
624
+ formatOverride = token.slice("--format=".length);
625
+ continue;
626
+ }
627
+ out.push(token);
628
+ }
629
+ return out;
630
+ }
631
+ /** Strip `--count <value>` / `--count=value` / `-c <value>` from argv. */
632
+ function stripCountFlag(argv) {
633
+ const out = [];
634
+ for (let i = 0; i < argv.length; i++) {
635
+ const token = argv[i];
636
+ if (token === "--count" || token === "-c") {
637
+ const value = argv[i + 1];
638
+ if (value !== undefined) {
639
+ countOverride = value;
640
+ i++;
641
+ }
642
+ continue;
643
+ }
644
+ if (token.startsWith("--count=")) {
645
+ countOverride = token.slice("--count=".length);
646
+ continue;
647
+ }
648
+ out.push(token);
649
+ }
650
+ return out;
651
+ }
652
+ // --- Build CLI with @ocas/cli-kit ---
653
+ const cli = createCLI({
654
+ name: "uwf",
655
+ version: VERSION,
656
+ });
657
+ const unknownSchema = z.unknown();
658
+ // ── workflow group ───────────────────────────────────────────────────────────
659
+ const workflow = cli.command("workflow");
660
+ workflow
661
+ .command("add")
662
+ .returns(unknownSchema, "")
663
+ .action(async (_args, flags) => {
664
+ const file = requirePositional(flags, 0, "file");
665
+ const storageRoot = resolveStorageRoot();
666
+ await runAction(async () => {
667
+ const result = await cmdWorkflowAdd(storageRoot, file);
668
+ await writeOutput(toWorkflowAddPayload(result), "workflow-add", storageRoot);
669
+ });
670
+ return undefined;
671
+ });
672
+ workflow
673
+ .command("validate")
674
+ .returns(unknownSchema, "")
675
+ .action(async (_args, flags) => {
676
+ const file = requirePositional(flags, 0, "file");
677
+ const storageRoot = resolveStorageRoot();
678
+ await runAction(async () => {
679
+ const errors = await cmdWorkflowValidate(file);
680
+ await writeOutput(toValidateResultPayload(errors), "validate-result", storageRoot);
681
+ if (errors.length > 0) {
682
+ process.exit(1);
683
+ }
684
+ });
685
+ return undefined;
686
+ });
687
+ workflow
688
+ .command("show")
689
+ .returns(unknownSchema, "")
690
+ .action(async (_args, flags) => {
691
+ const id = requirePositional(flags, 0, "id");
692
+ const storageRoot = resolveStorageRoot();
693
+ await runAction(async () => {
694
+ const result = await cmdWorkflowShow(storageRoot, id, process.cwd());
695
+ await writeOutput(toWorkflowDetailPayload(result), "workflow-detail", storageRoot);
696
+ });
697
+ return undefined;
698
+ });
699
+ workflow
700
+ .command("list")
701
+ .returns(unknownSchema, "")
702
+ .action(async () => {
703
+ const storageRoot = resolveStorageRoot();
704
+ await runAction(async () => {
705
+ const result = await cmdWorkflowList(storageRoot, process.cwd());
706
+ await writeOutput(toWorkflowListPayload(result), "workflow-list", storageRoot);
707
+ });
708
+ return undefined;
709
+ });
710
+ // ── thread group ─────────────────────────────────────────────────────────────
711
+ const thread = cli.command("thread");
712
+ thread
713
+ .command("start")
714
+ .flag("prompt", { type: "string" })
715
+ .flag("p", { type: "string" })
716
+ .flag("cwd", { type: "string" })
717
+ .returns(unknownSchema, "")
718
+ .action(async (_args, flags) => {
719
+ const workflowName = requirePositional(flags, 0, "workflow");
720
+ const prompt = flags.prompt ?? flags.p;
721
+ if (prompt === undefined) {
722
+ process.stderr.write("Error: missing required option: -p, --prompt <text>\n");
723
+ process.exit(1);
724
+ }
725
+ const storageRoot = resolveStorageRoot();
726
+ await runAction(async () => {
727
+ const result = await cmdThreadStart(storageRoot, workflowName, prompt, process.cwd(), flags.cwd ?? process.cwd());
728
+ await writeOutput(toThreadStartPayload(result), "thread-start", storageRoot);
729
+ });
730
+ return undefined;
731
+ });
732
+ thread
733
+ .command("exec")
734
+ .flag("agent", { type: "string" })
735
+ .flag("background", { type: "boolean", default: false })
736
+ .flag("_background-worker", { type: "boolean", default: false })
737
+ .returns(unknownSchema, "")
738
+ .action(async (_args, flags) => {
739
+ const threadId = requirePositional(flags, 0, "thread-id");
740
+ const storageRoot = resolveStorageRoot();
741
+ await runAction(async () => {
742
+ const agentOverride = flags.agent ?? null;
743
+ const count = countOverride !== null ? Number(countOverride) : 1;
744
+ const background = flags.background;
745
+ const backgroundWorker = flags["_background-worker"] ?? false;
746
+ const results = await cmdThreadExec(storageRoot, threadId, agentOverride, count, background, backgroundWorker);
747
+ await writeOutput(toThreadExecPayload(results), "thread-exec", storageRoot);
748
+ });
749
+ return undefined;
750
+ });
751
+ thread
752
+ .command("show")
753
+ .returns(unknownSchema, "")
754
+ .action(async (_args, flags) => {
755
+ const threadId = requirePositional(flags, 0, "thread-id");
756
+ const storageRoot = resolveStorageRoot();
757
+ await runAction(async () => {
758
+ const result = await cmdThreadShow(storageRoot, threadId);
759
+ await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
760
+ });
761
+ return undefined;
762
+ });
206
763
  thread
207
764
  .command("list")
208
- .description("List threads (defaults to active: idle + running + corrupt)")
209
- .option("--status <status>", "Filter by status: idle, running, end, cancelled, active (idle+running), or comma-separated values")
210
- .option("--all", "Show all threads regardless of status (overrides default active-only filter)")
211
- .option("--after <date>", "Filter threads created after this date (ISO or relative like '7d')")
212
- .option("--before <date>", "Filter threads created before this date (ISO or relative like '7d')")
213
- .option("--skip <n>", "Skip first n threads")
214
- .option("--take <n>", "Return at most n threads")
215
- .action((opts) => {
765
+ .flag("status", { type: "string" })
766
+ .flag("all", { type: "boolean", default: false })
767
+ .flag("after", { type: "string" })
768
+ .flag("before", { type: "string" })
769
+ .flag("skip", { type: "string" })
770
+ .flag("take", { type: "string" })
771
+ .flag("limit", { type: "string" })
772
+ .flag("offset", { type: "string" })
773
+ .returns(unknownSchema, "")
774
+ .action(async (_args, flags) => {
216
775
  const storageRoot = resolveStorageRoot();
217
- runAction(async () => {
218
- const statusFilter = parseStatusFilter(opts.status);
776
+ await runAction(async () => {
777
+ const statusFilter = parseStatusFilter(flags.status);
219
778
  const nowMs = Date.now();
220
- const { afterMs, beforeMs } = parseTimeFilters(opts.after, opts.before, nowMs);
221
- const { skip, take } = parsePaginationOptions(opts.skip, opts.take);
222
- const showAll = opts.all === true;
779
+ const { afterMs, beforeMs } = parseTimeFilters(flags.after, flags.before, nowMs);
780
+ const { skip, take } = resolveThreadListPagination({
781
+ skip: flags.skip,
782
+ take: flags.take,
783
+ limit: flags.limit,
784
+ offset: flags.offset,
785
+ });
786
+ const showAll = flags.all === true;
223
787
  const result = await cmdThreadList(storageRoot, statusFilter, afterMs, beforeMs, skip, take, showAll);
224
788
  await writeOutput(toThreadListPayload(result), "thread-list", storageRoot);
225
789
  });
790
+ return undefined;
226
791
  });
227
792
  thread
228
793
  .command("resume")
229
- .description("Resume a suspended thread and re-run the suspended role")
230
- .argument("<thread-id>", "Thread ULID")
231
- .option("-p, --prompt <text>", "Supplementary info to append to the resume prompt")
232
- .option("--agent <cmd>", "Override agent command")
233
- .action((threadId, opts) => {
794
+ .flag("prompt", { type: "string" })
795
+ .flag("p", { type: "string" })
796
+ .flag("agent", { type: "string" })
797
+ .returns(unknownSchema, "")
798
+ .action(async (_args, flags) => {
799
+ const threadId = requirePositional(flags, 0, "thread-id");
234
800
  const storageRoot = resolveStorageRoot();
235
- runAction(async () => {
236
- const supplement = opts.prompt ?? null;
237
- const agentOverride = opts.agent ?? null;
801
+ const prompt = flags.prompt ?? flags.p;
802
+ await runAction(async () => {
803
+ const supplement = prompt ?? null;
804
+ const agentOverride = flags.agent ?? null;
238
805
  const result = await cmdThreadResume(storageRoot, threadId, supplement, agentOverride);
239
806
  await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
240
807
  });
808
+ return undefined;
241
809
  });
242
810
  thread
243
811
  .command("poke")
244
- .description("Re-run the head step's agent with a supplementary prompt (replaces head step)")
245
- .argument("<thread-id>", "Thread ULID")
246
- .requiredOption("-p, --prompt <text>", "Supplementary prompt for the agent")
247
- .option("--agent <cmd>", "Override agent command (defaults to head step's agent)")
248
- .action((threadId, opts) => {
812
+ .flag("prompt", { type: "string" })
813
+ .flag("p", { type: "string" })
814
+ .flag("agent", { type: "string" })
815
+ .returns(unknownSchema, "")
816
+ .action(async (_args, flags) => {
817
+ const threadId = requirePositional(flags, 0, "thread-id");
818
+ const prompt = flags.prompt ?? flags.p;
819
+ if (prompt === undefined) {
820
+ process.stderr.write("Error: missing required option: -p, --prompt <text>\n");
821
+ process.exit(1);
822
+ }
249
823
  const storageRoot = resolveStorageRoot();
250
- runAction(async () => {
251
- const agentOverride = opts.agent ?? null;
252
- const result = await cmdThreadPoke(storageRoot, threadId, opts.prompt, agentOverride);
824
+ await runAction(async () => {
825
+ const agentOverride = flags.agent ?? null;
826
+ const result = await cmdThreadPoke(storageRoot, threadId, prompt, agentOverride);
253
827
  await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
254
828
  });
829
+ return undefined;
255
830
  });
256
831
  thread
257
832
  .command("stop")
258
- .description("Stop background execution of a thread (keep thread active)")
259
- .argument("<thread-id>", "Thread ULID")
260
- .action((threadId) => {
833
+ .returns(unknownSchema, "")
834
+ .action(async (_args, flags) => {
835
+ const threadId = requirePositional(flags, 0, "thread-id");
261
836
  const storageRoot = resolveStorageRoot();
262
- runAction(async () => {
837
+ await runAction(async () => {
263
838
  const result = await cmdThreadStop(storageRoot, threadId);
264
839
  writeRawOutput(result, "thread stop");
265
840
  });
841
+ return undefined;
266
842
  });
267
843
  thread
268
844
  .command("cancel")
269
- .description("Cancel a thread (stop execution and move to history)")
270
- .argument("<thread-id>", "Thread ULID")
271
- .action((threadId) => {
845
+ .returns(unknownSchema, "")
846
+ .action(async (_args, flags) => {
847
+ const threadId = requirePositional(flags, 0, "thread-id");
272
848
  const storageRoot = resolveStorageRoot();
273
- runAction(async () => {
849
+ await runAction(async () => {
274
850
  const result = await cmdThreadCancel(storageRoot, threadId);
275
851
  writeRawOutput(result, "thread cancel");
276
852
  });
853
+ return undefined;
277
854
  });
278
855
  thread
279
856
  .command("join")
280
- .description("Block until a running thread finishes, then return the final result")
281
- .argument("<thread-id>", "Thread ULID")
282
- .option("--timeout <seconds>", "Max seconds to wait before giving up")
283
- .action((threadId, opts) => {
857
+ .flag("timeout", { type: "string" })
858
+ .returns(unknownSchema, "")
859
+ .action(async (_args, flags) => {
860
+ const threadId = requirePositional(flags, 0, "thread-id");
284
861
  const storageRoot = resolveStorageRoot();
285
- runAction(async () => {
286
- const timeoutMs = opts.timeout !== undefined ? Number(opts.timeout) * 1000 : null;
862
+ await runAction(async () => {
863
+ const timeoutRaw = flags.timeout;
864
+ const timeoutMs = timeoutRaw !== undefined ? Number(timeoutRaw) * 1000 : null;
287
865
  if (timeoutMs !== null && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
288
866
  process.stderr.write("invalid --timeout: must be a positive number\n");
289
867
  process.exit(1);
@@ -291,311 +869,299 @@ thread
291
869
  const results = await cmdThreadJoin(storageRoot, threadId, timeoutMs);
292
870
  await writeOutput(toThreadExecPayload(results), "thread-exec", storageRoot);
293
871
  });
872
+ return undefined;
294
873
  });
295
874
  thread
296
875
  .command("read")
297
- .description("Read thread context as human-readable markdown")
298
- .argument("<thread-id>", "Thread ULID")
299
- .option("--quota <chars>", "Max output characters", String(THREAD_READ_DEFAULT_QUOTA))
300
- .option("--before <step-hash>", "Load steps before this hash (exclusive)")
301
- .option("--start", "Include start step in output")
302
- .action((threadId, opts) => {
876
+ .flag("quota", { type: "string", default: String(THREAD_READ_DEFAULT_QUOTA) })
877
+ .flag("before", { type: "string" })
878
+ .flag("start", { type: "boolean", default: false })
879
+ .returns(unknownSchema, "")
880
+ .action(async (_args, flags) => {
881
+ const threadId = requirePositional(flags, 0, "thread-id");
303
882
  const storageRoot = resolveStorageRoot();
304
- runAction(async () => {
305
- const quota = Number.parseInt(opts.quota, 10);
883
+ await runAction(async () => {
884
+ const quota = Number.parseInt(flags.quota, 10);
306
885
  if (!Number.isFinite(quota) || quota < 1) {
307
886
  process.stderr.write("invalid --quota: must be a positive integer\n");
308
887
  process.exit(1);
309
888
  }
310
- const before = opts.before ?? null;
311
- const markdown = await cmdThreadRead(storageRoot, threadId, quota, before, opts.start ?? false);
889
+ const before = flags.before ?? null;
890
+ const markdown = await cmdThreadRead(storageRoot, threadId, quota, before, flags.start ?? false);
312
891
  process.stdout.write(markdown.endsWith("\n") ? markdown : `${markdown}\n`);
313
892
  });
893
+ return undefined;
314
894
  });
315
- const step = program.command("step").description("Step results (layer 3: single cycle)");
895
+ // ── step group ───────────────────────────────────────────────────────────────
896
+ const step = cli.command("step");
316
897
  step
317
898
  .command("list")
318
- .description("List all steps in a thread")
319
- .argument("<thread-id>", "Thread ULID")
320
- .action((threadId) => {
899
+ .returns(unknownSchema, "")
900
+ .action(async (_args, flags) => {
901
+ const threadId = requirePositional(flags, 0, "thread-id");
321
902
  const storageRoot = resolveStorageRoot();
322
- runAction(async () => {
903
+ await runAction(async () => {
323
904
  const result = await cmdStepList(storageRoot, threadId);
324
905
  await writeOutput(toStepListPayload(result), "step-list", storageRoot);
325
906
  });
907
+ return undefined;
326
908
  });
327
909
  step
328
910
  .command("show")
329
- .description("Show details of a specific step")
330
- .argument("<step-hash>", "CAS hash of the StepNode")
331
- .action((stepHash) => {
911
+ .returns(unknownSchema, "")
912
+ .action(async (_args, flags) => {
913
+ const stepHash = requirePositional(flags, 0, "step-hash");
332
914
  const storageRoot = resolveStorageRoot();
333
- runAction(async () => {
915
+ await runAction(async () => {
334
916
  const detail = await cmdStepShow(storageRoot, stepHash);
335
917
  await writeOutput(toStepDetailPayload(stepHash, detail), "step-detail", storageRoot);
336
918
  });
919
+ return undefined;
337
920
  });
338
921
  step
339
922
  .command("ask")
340
- .description("Ask a follow-up question to a historical step's agent (read-only; no thread mutation)")
341
- .argument("<step-hash>", "CAS hash of the StepNode to query")
342
- .requiredOption("-p, --prompt <text>", "Question to ask the step's agent")
343
- .option("--agent <cmd>", "Override agent command (defaults to the step's recorded agent)")
344
- .option("--no-fork", "Skip session-fork; spawn the agent in a fresh ask session and inject the step's detail ref for context")
345
- .action((stepHash, opts) => {
923
+ .flag("prompt", { type: "string" })
924
+ .flag("p", { type: "string" })
925
+ .flag("agent", { type: "string" })
926
+ .flag("no-fork", { type: "boolean", default: false })
927
+ .returns(unknownSchema, "")
928
+ .action(async (_args, flags) => {
929
+ const stepHash = requirePositional(flags, 0, "step-hash");
930
+ const prompt = flags.prompt ?? flags.p;
931
+ if (prompt === undefined) {
932
+ process.stderr.write("Error: missing required option: -p, --prompt <text>\n");
933
+ process.exit(1);
934
+ }
346
935
  const storageRoot = resolveStorageRoot();
347
- runAction(async () => {
936
+ await runAction(async () => {
348
937
  const stdout = await cmdStepAsk(storageRoot, stepHash, {
349
- prompt: opts.prompt,
350
- agentOverride: opts.agent ?? null,
351
- fork: opts.fork,
938
+ prompt,
939
+ agentOverride: flags.agent ?? null,
940
+ fork: !flags["no-fork"],
352
941
  });
353
942
  process.stdout.write(stdout.endsWith("\n") ? stdout : `${stdout}\n`);
354
943
  });
944
+ return undefined;
355
945
  });
356
946
  step
357
947
  .command("read")
358
- .description("Read a step's turns as human-readable markdown")
359
- .argument("<step-hash>", "CAS hash of the StepNode")
360
- .option("--quota <chars>", "Max output characters", "4000")
361
- .option("--prompt", "Show the assembled prompt sent to the agent instead of turns")
362
- .action((stepHash, opts) => {
948
+ .flag("quota", { type: "string", default: "4000" })
949
+ .flag("prompt", { type: "boolean", default: false })
950
+ .returns(unknownSchema, "")
951
+ .action(async (_args, flags) => {
952
+ const stepHash = requirePositional(flags, 0, "step-hash");
363
953
  const storageRoot = resolveStorageRoot();
364
- runAction(async () => {
365
- const quota = Number.parseInt(opts.quota, 10);
954
+ await runAction(async () => {
955
+ const quota = Number.parseInt(flags.quota, 10);
366
956
  if (!Number.isFinite(quota) || quota < 1) {
367
957
  process.stderr.write("invalid --quota: must be a positive integer\n");
368
958
  process.exit(1);
369
959
  }
370
- const markdown = await cmdStepRead(storageRoot, stepHash, quota, opts.prompt === true);
960
+ const markdown = await cmdStepRead(storageRoot, stepHash, quota, flags.prompt === true);
371
961
  process.stdout.write(markdown.endsWith("\n") ? markdown : `${markdown}\n`);
372
962
  });
963
+ return undefined;
964
+ });
965
+ step
966
+ .command("turns")
967
+ .flag("role", { type: "string" })
968
+ .flag("live", { type: "boolean", default: false })
969
+ .flag("limit", { type: "string" })
970
+ .flag("offset", { type: "string" })
971
+ .returns(unknownSchema, "")
972
+ .action(async (_args, flags) => {
973
+ const threadId = requirePositional(flags, 0, "thread-id");
974
+ const storageRoot = resolveStorageRoot();
975
+ await runAction(async () => {
976
+ const limit = parseTurnsPageOption("--limit", flags.limit);
977
+ const offset = parseTurnsPageOption("--offset", flags.offset) ?? 0;
978
+ const markdown = await cmdStepTurns(storageRoot, threadId, {
979
+ role: flags.role ?? null,
980
+ live: flags.live === true,
981
+ limit,
982
+ offset,
983
+ });
984
+ if (markdown !== "") {
985
+ process.stdout.write(markdown.endsWith("\n") ? markdown : `${markdown}\n`);
986
+ }
987
+ });
988
+ return undefined;
373
989
  });
374
990
  step
375
991
  .command("fork")
376
- .description("Fork a thread from a specific step")
377
- .argument("<step-hash>", "CAS hash of the StartNode or StepNode to fork from")
378
- .action((stepHash) => {
992
+ .returns(unknownSchema, "")
993
+ .action(async (_args, flags) => {
994
+ const stepHash = requirePositional(flags, 0, "step-hash");
379
995
  const storageRoot = resolveStorageRoot();
380
- runAction(async () => {
996
+ await runAction(async () => {
381
997
  const result = await cmdStepFork(storageRoot, stepHash);
382
998
  writeRawOutput(result);
383
999
  });
1000
+ return undefined;
384
1001
  });
385
- // ── Deprecation Handlers ──────────────────────────────────────────────────────
386
- // These commands have been removed. Show helpful error messages.
387
- workflow
388
- .command("put")
389
- .description("[DEPRECATED] Use 'workflow add' instead")
390
- .argument("<file>", "Workflow YAML file")
391
- .action(() => {
392
- process.stderr.write(`Error: Command 'workflow put' has been removed.
393
- Use 'workflow add' instead.
394
-
395
- For more information, see: uwf help workflow add
396
- `);
397
- process.exit(1);
398
- });
399
- thread
400
- .command("step")
401
- .description("[DEPRECATED] Use 'thread exec' instead")
402
- .argument("<thread-id>", "Thread ULID")
403
- .allowUnknownOption()
404
- .action(() => {
405
- process.stderr.write(`Error: Command 'thread step' has been removed.
406
- Use 'thread exec' instead.
407
-
408
- For more information, see: uwf help thread exec
409
- `);
410
- process.exit(1);
411
- });
412
- thread
413
- .command("steps")
414
- .description("[DEPRECATED] Use 'step list' instead")
415
- .argument("<thread-id>", "Thread ULID")
416
- .action(() => {
417
- process.stderr.write(`Error: Command 'thread steps' has been removed.
418
- Use 'step list' instead.
419
-
420
- For more information, see: uwf help step list
421
- `);
422
- process.exit(1);
423
- });
424
- thread
425
- .command("step-details")
426
- .description("[DEPRECATED] Use 'step show' instead")
427
- .argument("<step-hash>", "Step hash")
428
- .action(() => {
429
- process.stderr.write(`Error: Command 'thread step-details' has been removed.
430
- Use 'step show' instead.
431
-
432
- For more information, see: uwf help step show
433
- `);
434
- process.exit(1);
435
- });
436
- thread
437
- .command("fork")
438
- .description("[DEPRECATED] Use 'step fork' instead")
439
- .argument("<step-hash>", "Step hash")
440
- .action(() => {
441
- process.stderr.write(`Error: Command 'thread fork' has been removed.
442
- Use 'step fork' instead.
443
-
444
- For more information, see: uwf help step fork
445
- `);
446
- process.exit(1);
447
- });
448
- thread
449
- .command("kill")
450
- .description("[DEPRECATED] Use 'thread stop' or 'thread cancel' instead")
451
- .argument("<thread-id>", "Thread ULID")
452
- .action(() => {
453
- process.stderr.write(`Error: Command 'thread kill' has been removed.
454
- Use 'thread stop' to stop background execution (keep thread active),
455
- or 'thread cancel' to cancel and archive the thread.
456
-
457
- For more information, see:
458
- uwf help thread stop
459
- uwf help thread cancel
460
- `);
461
- process.exit(1);
462
- });
463
- thread
464
- .command("running")
465
- .description("[DEPRECATED] Use 'thread list --status running' instead")
466
- .action(() => {
467
- process.stderr.write(`Error: Command 'thread running' has been removed.
468
- Use 'thread list --status running' instead.
469
-
470
- For more information, see: uwf help thread list
471
- `);
472
- process.exit(1);
473
- });
474
- const prompt = program.command("prompt").description("Built-in prompt references for agents");
475
- prompt.addHelpCommand(false);
476
- prompt
1002
+ // ── prompt group ─────────────────────────────────────────────────────────────
1003
+ const promptGroup = cli.command("prompt");
1004
+ promptGroup
477
1005
  .command("usage")
478
- .description("Print the usage reference (CLI guide + typical workflows)")
479
- .action(() => {
1006
+ .returns(unknownSchema, "")
1007
+ .action(async () => {
480
1008
  console.log(cmdPromptUsage());
1009
+ return undefined;
481
1010
  });
482
- prompt
1011
+ promptGroup
483
1012
  .command("bootstrap")
484
- .description("Print setup instructions for installing uwf skills")
485
- .action(() => {
1013
+ .returns(unknownSchema, "")
1014
+ .action(async () => {
486
1015
  console.log(cmdPromptBootstrap());
1016
+ return undefined;
487
1017
  });
488
- prompt
1018
+ promptGroup
489
1019
  .command("workflow-authoring")
490
- .description("Print the workflow authoring reference (YAML design guide)")
491
- .action(() => {
1020
+ .returns(unknownSchema, "")
1021
+ .action(async () => {
492
1022
  console.log(cmdPromptWorkflowAuthoring());
1023
+ return undefined;
493
1024
  });
494
- prompt
1025
+ promptGroup
495
1026
  .command("adapter-developing")
496
- .description("Print the adapter developing reference (building agent adapters)")
497
- .action(() => {
1027
+ .returns(unknownSchema, "")
1028
+ .action(async () => {
498
1029
  console.log(cmdPromptAdapterDeveloping());
1030
+ return undefined;
499
1031
  });
500
- prompt
1032
+ promptGroup
501
1033
  .command("list")
502
- .description("List all available prompt names")
503
- .action(() => {
1034
+ .returns(unknownSchema, "")
1035
+ .action(async () => {
504
1036
  console.log(cmdPromptList().join("\n"));
1037
+ return undefined;
505
1038
  });
506
- program
1039
+ // ── setup (top-level) ────────────────────────────────────────────────────────
1040
+ cli
507
1041
  .command("setup")
508
- .description("Configure the default agent. Run without --agent for interactive wizard.\n" +
509
- "Each adapter owns its own LLM configuration — the engine config is LLM-free.")
510
- .option("--agent <name>", "Default agent adapter (e.g. hermes → uwf-hermes)")
511
- .action((opts) => {
1042
+ .flag("agent", { type: "string" })
1043
+ .returns(unknownSchema, "")
1044
+ .action(async (_args, flags) => {
512
1045
  const storageRoot = resolveStorageRoot();
513
- runAction(async () => {
514
- if (opts.agent !== undefined && opts.agent !== "") {
515
- const result = await cmdSetup({ agent: opts.agent, storageRoot });
1046
+ const agent = flags.agent;
1047
+ await runAction(async () => {
1048
+ if (agent !== undefined && agent !== "") {
1049
+ const result = await cmdSetup({ agent, storageRoot });
516
1050
  writeRawOutput(result);
517
1051
  }
518
1052
  else {
519
1053
  await cmdSetupInteractive(storageRoot);
520
1054
  }
521
1055
  });
1056
+ return undefined;
522
1057
  });
523
- const log = program.command("log").description("Process-level debug logs");
1058
+ // ── log group ────────────────────────────────────────────────────────────────
1059
+ const log = cli.command("log");
524
1060
  log
525
1061
  .command("list")
526
- .description("List log files with sizes")
527
- .action(() => {
1062
+ .returns(unknownSchema, "")
1063
+ .action(async () => {
528
1064
  const storageRoot = resolveStorageRoot();
529
- runAction(async () => {
1065
+ await runAction(async () => {
530
1066
  const result = await cmdLogList(storageRoot);
531
1067
  writeRawOutput(result, "log list");
532
1068
  });
1069
+ return undefined;
533
1070
  });
534
1071
  log
535
1072
  .command("show")
536
- .description("Show and filter log entries")
537
- .option("--thread <thread-id>", "Filter by thread ID")
538
- .option("--process <pid>", "Filter by process ID")
539
- .option("--date <date>", "Filter by date (YYYY-MM-DD)")
540
- .action((opts) => {
1073
+ .flag("thread", { type: "string" })
1074
+ .flag("process", { type: "string" })
1075
+ .flag("date", { type: "string" })
1076
+ .returns(unknownSchema, "")
1077
+ .action(async (_args, flags) => {
541
1078
  const storageRoot = resolveStorageRoot();
542
- runAction(async () => {
1079
+ await runAction(async () => {
543
1080
  const result = await cmdLogShow(storageRoot, {
544
- thread: opts.thread ?? null,
545
- process: opts.process ?? null,
546
- date: opts.date ?? null,
1081
+ thread: flags.thread ?? null,
1082
+ process: flags.process ?? null,
1083
+ date: flags.date ?? null,
547
1084
  });
548
1085
  writeRawOutput(result, "log show");
549
1086
  });
1087
+ return undefined;
550
1088
  });
551
1089
  log
552
1090
  .command("clean")
553
- .description("Delete log files older than given date")
554
- .requiredOption("--before <date>", "Delete files before this date (YYYY-MM-DD)")
555
- .action((opts) => {
1091
+ .flag("before", { type: "string" })
1092
+ .returns(unknownSchema, "")
1093
+ .action(async (_args, flags) => {
1094
+ const before = flags.before;
1095
+ if (before === undefined) {
1096
+ process.stderr.write("Error: missing required option: --before <date>\n");
1097
+ process.exit(1);
1098
+ }
556
1099
  const storageRoot = resolveStorageRoot();
557
- runAction(async () => {
558
- const result = await cmdLogClean(storageRoot, opts.before);
1100
+ await runAction(async () => {
1101
+ const result = await cmdLogClean(storageRoot, before);
559
1102
  writeRawOutput(result);
560
1103
  });
1104
+ return undefined;
561
1105
  });
562
- const config = program.command("config").description("Configuration management");
1106
+ // ── config group ─────────────────────────────────────────────────────────────
1107
+ const config = cli.command("config");
563
1108
  config
564
1109
  .command("list")
565
- .description("Display all configuration values (masks API keys)")
566
- .action(() => {
1110
+ .returns(unknownSchema, "")
1111
+ .action(async () => {
567
1112
  const storageRoot = resolveStorageRoot();
568
- runAction(async () => {
1113
+ await runAction(async () => {
569
1114
  const result = await cmdConfigList(storageRoot);
570
1115
  writeRawOutput(result, "config list");
571
1116
  });
1117
+ return undefined;
572
1118
  });
573
1119
  config
574
1120
  .command("get")
575
- .description("Get a specific configuration value")
576
- .argument("<key>", "Dot-notation path to config value (e.g., defaultAgent, providers.dashscope.baseUrl)")
577
- .action((key) => {
1121
+ .returns(unknownSchema, "")
1122
+ .action(async (_args, flags) => {
1123
+ const key = requirePositional(flags, 0, "key");
578
1124
  const storageRoot = resolveStorageRoot();
579
- runAction(async () => {
1125
+ await runAction(async () => {
580
1126
  const result = await cmdConfigGet(storageRoot, key);
581
1127
  writeRawOutput({ value: result }, "config get");
582
1128
  });
1129
+ return undefined;
583
1130
  });
584
1131
  config
585
1132
  .command("set")
586
- .description("Set a specific configuration value")
587
- .argument("<key>", "Dot-notation path to config value")
588
- .argument("<value>", "New value (use JSON array for 'args' key, e.g., '[\"--flag\"]')")
589
- .action((key, value) => {
1133
+ .returns(unknownSchema, "")
1134
+ .action(async (_args, flags) => {
1135
+ const key = requirePositional(flags, 0, "key");
1136
+ const value = requirePositional(flags, 1, "value");
590
1137
  const storageRoot = resolveStorageRoot();
591
- runAction(async () => {
1138
+ await runAction(async () => {
592
1139
  const result = await cmdConfigSet(storageRoot, key, value);
593
1140
  writeRawOutput(result, "config set");
594
1141
  });
1142
+ return undefined;
595
1143
  });
596
- program.parseAsync(process.argv).catch((e) => {
597
- const message = e instanceof Error ? e.message : String(e);
598
- process.stderr.write(`${message}\n`);
599
- process.exit(1);
600
- });
1144
+ // --- Main execution: early intercepts + cli.run() ---
1145
+ const rawArgv = process.argv.slice(2);
1146
+ // 1. --version / -V (cli-kit doesn't handle these)
1147
+ const firstToken = rawArgv[0];
1148
+ if (firstToken === "--version" || firstToken === "-V") {
1149
+ process.stdout.write(`${VERSION}\n`);
1150
+ process.exit(0);
1151
+ }
1152
+ // 2. Strip --format (cli-kit has no global --format; parse into module-level var)
1153
+ const argvNoFormat = stripFormatFlag(rawArgv);
1154
+ // 3. --help / -h / no args (cli-kit has no per-command --help)
1155
+ if (argvNoFormat.length === 0 || argvNoFormat.includes("--help") || argvNoFormat.includes("-h")) {
1156
+ printHelp(argvNoFormat);
1157
+ }
1158
+ // 4. Deprecated commands (intercept before cli-kit parsing)
1159
+ handleDeprecated(argvNoFormat);
1160
+ // 5. Strip --count / -c (cli-kit rejects values starting with `-`)
1161
+ const argvNoCount = stripCountFlag(argvNoFormat);
1162
+ // 6. Run cli-kit
1163
+ const exitCode = await cli.run({ argv: argvNoCount });
1164
+ if (exitCode !== 0) {
1165
+ process.exit(exitCode);
1166
+ }
601
1167
  //# sourceMappingURL=cli.js.map