@outfitter/cli 0.5.2 → 1.0.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 (110) hide show
  1. package/README.md +179 -60
  2. package/dist/actions.d.ts +5 -2
  3. package/dist/actions.js +2 -2
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.js +8 -1
  6. package/dist/colors/index.js +1 -17
  7. package/dist/command.d.ts +3 -43
  8. package/dist/command.js +241 -13
  9. package/dist/envelope.d.ts +5 -0
  10. package/dist/envelope.js +160 -0
  11. package/dist/flags.d.ts +5 -189
  12. package/dist/flags.js +5 -1
  13. package/dist/hints.d.ts +34 -0
  14. package/dist/hints.js +26 -0
  15. package/dist/index.d.ts +3 -2
  16. package/dist/index.js +2 -17
  17. package/dist/input.d.ts +3 -124
  18. package/dist/input.js +14 -359
  19. package/dist/internal/envelope-helpers.d.ts +4 -0
  20. package/dist/internal/envelope-helpers.js +24 -0
  21. package/dist/internal/envelope-types.d.ts +3 -0
  22. package/dist/internal/flag-builders.d.ts +3 -0
  23. package/dist/internal/flag-builders.js +155 -0
  24. package/dist/internal/flag-types.d.ts +3 -0
  25. package/dist/internal/flag-types.js +13 -0
  26. package/dist/internal/hint-action-graph.d.ts +5 -0
  27. package/dist/internal/hint-action-graph.js +11 -0
  28. package/dist/internal/hint-command-tree.d.ts +5 -0
  29. package/dist/internal/hint-command-tree.js +9 -0
  30. package/dist/internal/hint-error-recovery.d.ts +2 -0
  31. package/dist/internal/hint-error-recovery.js +7 -0
  32. package/dist/internal/hint-types.d.ts +4 -0
  33. package/dist/internal/hint-types.js +1 -0
  34. package/dist/internal/input-helpers.d.ts +18 -0
  35. package/dist/internal/input-helpers.js +11 -0
  36. package/dist/internal/input-normalization.d.ts +3 -0
  37. package/dist/internal/input-normalization.js +9 -0
  38. package/dist/internal/input-parsers.d.ts +3 -0
  39. package/dist/internal/input-parsers.js +19 -0
  40. package/dist/internal/input-security.d.ts +22 -0
  41. package/dist/internal/input-security.js +11 -0
  42. package/dist/internal/output-formatting.d.ts +3 -0
  43. package/dist/internal/output-formatting.js +21 -0
  44. package/dist/internal/presets.d.ts +3 -0
  45. package/dist/{shared/@outfitter/cli-pdb7znbq.js → internal/presets.js} +49 -223
  46. package/dist/internal/schema-commands.d.ts +3 -0
  47. package/dist/{shared/@outfitter/cli-0cjts94k.js → internal/schema-commands.js} +12 -100
  48. package/dist/internal/schema-formatting.d.ts +2 -0
  49. package/dist/internal/schema-formatting.js +7 -0
  50. package/dist/internal/schema-types.d.ts +2 -0
  51. package/dist/internal/schema-types.js +1 -0
  52. package/dist/output.d.ts +4 -3
  53. package/dist/output.js +10 -2
  54. package/dist/pagination.d.ts +1 -1
  55. package/dist/query.d.ts +84 -2
  56. package/dist/query.js +8 -45
  57. package/dist/schema-input.d.ts +80 -0
  58. package/dist/schema-input.js +15 -0
  59. package/dist/schema.d.ts +4 -1
  60. package/dist/schema.js +1 -1
  61. package/dist/shared/@outfitter/cli-10wxfc78.d.ts +45 -0
  62. package/dist/shared/@outfitter/cli-16wg5mka.d.ts +71 -0
  63. package/dist/shared/@outfitter/cli-1q5redaj.js +267 -0
  64. package/dist/shared/@outfitter/cli-2dfxs239.js +98 -0
  65. package/dist/shared/@outfitter/cli-30mt7c5w.d.ts +112 -0
  66. package/dist/shared/@outfitter/cli-3jta1h1h.js +134 -0
  67. package/dist/shared/@outfitter/cli-4h85mpth.js +76 -0
  68. package/dist/shared/@outfitter/cli-6shkwxdc.js +28 -0
  69. package/dist/shared/@outfitter/cli-89335n9a.js +16 -0
  70. package/dist/shared/@outfitter/cli-8999qjdd.js +3 -0
  71. package/dist/shared/@outfitter/cli-8cfxdady.js +60 -0
  72. package/dist/shared/@outfitter/cli-bcajqy33.d.ts +25 -0
  73. package/dist/shared/@outfitter/cli-c09332vm.d.ts +39 -0
  74. package/dist/shared/@outfitter/cli-cgha038c.d.ts +3 -0
  75. package/dist/shared/@outfitter/{cli-zahqsaby.js → cli-d40m2x1d.js} +19 -3
  76. package/dist/shared/@outfitter/{cli-7wp5nj0s.js → cli-dg0cz7rw.js} +39 -81
  77. package/dist/shared/@outfitter/cli-dv8kk4jw.d.ts +24 -0
  78. package/dist/shared/@outfitter/cli-g43887b7.js +20 -0
  79. package/dist/shared/@outfitter/cli-gqtkhgw4.js +52 -0
  80. package/dist/shared/@outfitter/cli-h4ejpmjs.d.ts +104 -0
  81. package/dist/shared/@outfitter/cli-htzez8v2.js +70 -0
  82. package/dist/shared/@outfitter/cli-hvg2m5gf.js +79 -0
  83. package/dist/shared/@outfitter/cli-n54zs151.d.ts +78 -0
  84. package/dist/shared/@outfitter/cli-nbpgw7z7.d.ts +15 -0
  85. package/dist/shared/@outfitter/cli-nkt399zf.d.ts +94 -0
  86. package/dist/shared/@outfitter/cli-pmd04gtv.d.ts +60 -0
  87. package/dist/shared/@outfitter/{cli-xy3gs50c.d.ts → cli-q6csxmeh.d.ts} +19 -12
  88. package/dist/shared/@outfitter/cli-qcskd96y.d.ts +11 -0
  89. package/dist/shared/@outfitter/cli-ry7btmy4.js +118 -0
  90. package/dist/shared/@outfitter/cli-sy99pjyj.js +32 -0
  91. package/dist/shared/@outfitter/cli-tm2fzngs.d.ts +23 -0
  92. package/dist/shared/@outfitter/cli-vvvhjwks.js +106 -0
  93. package/dist/shared/@outfitter/cli-wjv7g1aq.d.ts +16 -0
  94. package/dist/shared/@outfitter/{cli-98aa9104.d.ts → cli-x6qr7bnd.d.ts} +338 -16
  95. package/dist/shared/@outfitter/cli-xde45xcc.d.ts +53 -0
  96. package/dist/shared/@outfitter/cli-xw8ys1je.d.ts +123 -0
  97. package/dist/shared/@outfitter/cli-yfewnyc2.d.ts +43 -0
  98. package/dist/shared/@outfitter/cli-zkzj0q4q.js +99 -0
  99. package/dist/shared/@outfitter/cli-zv3ah6f0.js +3 -0
  100. package/dist/streaming.d.ts +47 -0
  101. package/dist/streaming.js +13 -0
  102. package/dist/terminal/index.js +1 -19
  103. package/dist/truncation.d.ts +104 -0
  104. package/dist/truncation.js +111 -0
  105. package/dist/types.d.ts +2 -2
  106. package/dist/types.js +0 -5
  107. package/dist/verbs.d.ts +1 -1
  108. package/package.json +66 -36
  109. package/dist/shared/@outfitter/cli-n1k0d23k.d.ts +0 -33
  110. /package/dist/{shared/@outfitter/cli-zw75pdk8.js → internal/envelope-types.js} +0 -0
@@ -1,5 +1,9 @@
1
1
  // @bun
2
- // packages/cli/src/schema.ts
2
+ import {
3
+ formatManifestHuman
4
+ } from "../shared/@outfitter/cli-zkzj0q4q.js";
5
+
6
+ // packages/cli/src/internal/schema-commands.ts
3
7
  import { mkdir, writeFile } from "fs/promises";
4
8
  import { dirname, join } from "path";
5
9
  import {
@@ -12,102 +16,6 @@ import {
12
16
  writeSurfaceMap
13
17
  } from "@outfitter/schema";
14
18
  import { Command } from "commander";
15
- import { generateManifest as generateManifest2 } from "@outfitter/schema";
16
- function formatManifestHuman(manifest, programName, actionId) {
17
- if (actionId) {
18
- return formatActionDetail(manifest, actionId);
19
- }
20
- return formatSummary(manifest, programName);
21
- }
22
- function formatSummary(manifest, programName) {
23
- const lines = [];
24
- const name = programName ?? "cli";
25
- const actionCount = manifest.actions.length;
26
- const surfaceCount = manifest.surfaces.length;
27
- const surfaceLabel = surfaceCount === 1 ? `${surfaceCount} surface` : `${surfaceCount} surfaces`;
28
- lines.push(`${name} \u2014 ${actionCount} actions across ${surfaceLabel}`);
29
- lines.push("");
30
- const grouped = new Map;
31
- const ungrouped = [];
32
- for (const action of manifest.actions) {
33
- const group = action.cli?.group;
34
- if (group) {
35
- const existing = grouped.get(group) ?? [];
36
- existing.push(action);
37
- grouped.set(group, existing);
38
- } else {
39
- ungrouped.push(action);
40
- }
41
- }
42
- for (const [groupName, groupActions] of grouped.entries()) {
43
- lines.push(groupName);
44
- for (const action of groupActions) {
45
- const commandPart = action.cli?.command ?? "";
46
- const isBase = !commandPart || commandPart.startsWith("[") || commandPart.startsWith("<");
47
- const displayCommand = isBase ? ` ${groupName} ${commandPart}`.trimEnd() : ` ${groupName} ${commandPart}`;
48
- const desc = action.cli?.description ?? action.description ?? "";
49
- lines.push(padCommand(displayCommand, desc));
50
- }
51
- lines.push("");
52
- }
53
- for (const action of ungrouped) {
54
- const commandPart = action.cli?.command ?? action.id;
55
- const desc = action.cli?.description ?? action.description ?? "";
56
- lines.push(padCommand(`${commandPart}`, desc));
57
- }
58
- lines.push("");
59
- lines.push("Use --output json for machine-readable format.");
60
- lines.push("Use --surface <name> to filter (cli, mcp, api, server).");
61
- return lines.join(`
62
- `);
63
- }
64
- function padCommand(command, description) {
65
- const padding = Math.max(1, 32 - command.length);
66
- return `${command}${" ".repeat(padding)}${description}`;
67
- }
68
- function formatActionDetail(manifest, actionId) {
69
- const entry = manifest.actions.find((a) => a.id === actionId);
70
- if (!entry) {
71
- return `Unknown action: ${actionId}`;
72
- }
73
- const lines = [];
74
- const desc = entry.cli?.description ?? entry.description ?? "";
75
- lines.push(`${entry.id} \u2014 ${desc}`);
76
- lines.push("");
77
- if (entry.cli) {
78
- const group = entry.cli.group;
79
- const commandPart = entry.cli.command ?? (group ? "" : entry.id);
80
- const fullCommand = group ? `${group} ${commandPart}`.trimEnd() : commandPart;
81
- lines.push(` Command: ${fullCommand}`);
82
- }
83
- lines.push(` Surfaces: ${entry.surfaces.join(", ")}`);
84
- if (entry.cli?.group) {
85
- lines.push(` Group: ${entry.cli.group}`);
86
- }
87
- if (entry.cli?.aliases && entry.cli.aliases.length > 0) {
88
- lines.push(` Aliases: ${entry.cli.aliases.join(", ")}`);
89
- }
90
- if (entry.cli?.options && entry.cli.options.length > 0) {
91
- lines.push("");
92
- lines.push(" Options:");
93
- for (const opt of entry.cli.options) {
94
- const defaultStr = opt.defaultValue !== undefined ? ` [${String(opt.defaultValue)}]` : "";
95
- lines.push(padCommand(` ${opt.flags}`, `${opt.description}${defaultStr}`));
96
- }
97
- }
98
- if (entry.mcp) {
99
- lines.push("");
100
- lines.push(" MCP:");
101
- if (entry.mcp.tool) {
102
- lines.push(` Tool: ${entry.mcp.tool}`);
103
- }
104
- if (entry.mcp.description) {
105
- lines.push(` Description: ${entry.mcp.description}`);
106
- }
107
- }
108
- return lines.join(`
109
- `);
110
- }
111
19
  function handleShow(source, programName, parentCmd, actionArg, cmdOptions) {
112
20
  const manifestOptions = {};
113
21
  if (cmdOptions.surface) {
@@ -174,6 +82,7 @@ function createSchemaCommand(source, options) {
174
82
  const diffCmd = new Command("diff").description("Compare runtime schema against committed surface map").option("--output <mode>", "Output mode (human, json)", "human").option("--against <version>", "Compare runtime against a named snapshot").option("--from <version>", "Base snapshot for snapshot-to-snapshot diff").option("--to <version>", "Target snapshot for snapshot-to-snapshot diff").action(async (diffOptions) => {
175
83
  let left;
176
84
  let right;
85
+ let diffMode = "committed-to-runtime";
177
86
  if (diffOptions.from && !diffOptions.to || !diffOptions.from && diffOptions.to) {
178
87
  process.stderr.write(`Both --from and --to are required for snapshot-to-snapshot diff.
179
88
  `);
@@ -181,6 +90,7 @@ function createSchemaCommand(source, options) {
181
90
  return;
182
91
  }
183
92
  if (diffOptions.from && diffOptions.to) {
93
+ diffMode = "snapshot-to-snapshot";
184
94
  const fromPath = resolveSnapshotPath(cwd, outputDir, diffOptions.from);
185
95
  const toPath = resolveSnapshotPath(cwd, outputDir, diffOptions.to);
186
96
  try {
@@ -210,6 +120,7 @@ function createSchemaCommand(source, options) {
210
120
  return;
211
121
  }
212
122
  } else if (diffOptions.against) {
123
+ diffMode = "snapshot-to-runtime";
213
124
  const snapshotPath = resolveSnapshotPath(cwd, outputDir, diffOptions.against);
214
125
  try {
215
126
  left = await readSurfaceMap(snapshotPath);
@@ -244,7 +155,7 @@ function createSchemaCommand(source, options) {
244
155
  }
245
156
  right = generateSurfaceMap(source, { generator: "runtime" });
246
157
  }
247
- const result = diffSurfaceMaps(left, right);
158
+ const result = diffSurfaceMaps(left, right, { mode: diffMode });
248
159
  if (diffOptions.output === "json") {
249
160
  process.stdout.write(`${JSON.stringify(result, null, 2)}
250
161
  `);
@@ -315,5 +226,6 @@ function createSchemaCommand(source, options) {
315
226
  }
316
227
  return cmd;
317
228
  }
318
-
319
- export { formatManifestHuman, createSchemaCommand, generateManifest2 as generateManifest };
229
+ export {
230
+ createSchemaCommand
231
+ };
@@ -0,0 +1,2 @@
1
+ import { formatManifestHuman } from "../shared/@outfitter/cli-qcskd96y.js";
2
+ export { formatManifestHuman };
@@ -0,0 +1,7 @@
1
+ // @bun
2
+ import {
3
+ formatManifestHuman
4
+ } from "../shared/@outfitter/cli-zkzj0q4q.js";
5
+ export {
6
+ formatManifestHuman
7
+ };
@@ -0,0 +1,2 @@
1
+ import { SchemaCommandOptions, SurfaceCommandOptions } from "../shared/@outfitter/cli-wjv7g1aq.js";
2
+ export { SurfaceCommandOptions, SchemaCommandOptions };
@@ -0,0 +1 @@
1
+ // @bun
package/dist/output.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- import { exitWithError, output, resolveVerbose } from "./shared/@outfitter/cli-xy3gs50c.js";
2
- import "./shared/@outfitter/cli-98aa9104.js";
3
- export { resolveVerbose, output, exitWithError };
1
+ import { exitWithError, output, resolveVerbose } from "./shared/@outfitter/cli-q6csxmeh.js";
2
+ import { cliStringify, detectMode, formatHuman } from "./shared/@outfitter/cli-10wxfc78.js";
3
+ import "./shared/@outfitter/cli-x6qr7bnd.js";
4
+ export { resolveVerbose, output, formatHuman, exitWithError, detectMode, cliStringify };
package/dist/output.js CHANGED
@@ -3,9 +3,17 @@ import {
3
3
  exitWithError,
4
4
  output,
5
5
  resolveVerbose
6
- } from "./shared/@outfitter/cli-7wp5nj0s.js";
6
+ } from "./shared/@outfitter/cli-4h85mpth.js";
7
+ import {
8
+ cliStringify,
9
+ detectMode,
10
+ formatHuman
11
+ } from "./shared/@outfitter/cli-dg0cz7rw.js";
7
12
  export {
8
13
  resolveVerbose,
9
14
  output,
10
- exitWithError
15
+ formatHuman,
16
+ exitWithError,
17
+ detectMode,
18
+ cliStringify
11
19
  };
@@ -1,4 +1,4 @@
1
- import { CursorOptions, PaginationState } from "./shared/@outfitter/cli-98aa9104.js";
1
+ import { CursorOptions, PaginationState } from "./shared/@outfitter/cli-x6qr7bnd.js";
2
2
  /**
3
3
  * Load persisted pagination state for a command.
4
4
  *
package/dist/query.d.ts CHANGED
@@ -1,4 +1,66 @@
1
- import { FlagPreset, OutputMode } from "./shared/@outfitter/cli-98aa9104.js";
1
+ import { FlagPreset, OutputMode } from "./shared/@outfitter/cli-x6qr7bnd.js";
2
+ /**
3
+ * Source of the resolved output mode, indicating how the mode was determined.
4
+ *
5
+ * - `"flag"` — User explicitly passed `--output`, `-o`, `--json`, or `--jsonl`
6
+ * - `"env"` — Mode set via `OUTFITTER_JSON=1` or `OUTFITTER_JSONL=1`
7
+ * - `"default"` — No explicit input; using the configured default (typically `"human"`)
8
+ */
9
+ type OutputModeSource = "flag" | "env" | "default";
10
+ /**
11
+ * Result of resolving output mode with source/explicitness tracking.
12
+ */
13
+ interface ResolvedOutputMode {
14
+ /** The resolved output mode */
15
+ readonly mode: "human" | "json" | "jsonl";
16
+ /** How the mode was determined */
17
+ readonly source: OutputModeSource;
18
+ }
19
+ /**
20
+ * Configuration for the centralized output mode resolver.
21
+ */
22
+ interface ResolveOutputModeConfig {
23
+ /** Custom argv for explicit-flag detection (defaults to `process.argv.slice(2)`) */
24
+ readonly argv?: readonly string[];
25
+ /** Default mode when not specified (default: `"human"`) */
26
+ readonly defaultMode?: "human" | "json" | "jsonl";
27
+ /**
28
+ * When `true`, skip env-var fallback and return the default for implicit
29
+ * modes. Useful for orchestrator modes (e.g., `check --pre-commit`) where
30
+ * structured output should require an explicit flag.
31
+ */
32
+ readonly forceHumanWhenImplicit?: boolean;
33
+ }
34
+ /**
35
+ * Centralized output-mode resolver with source/explicitness tracking.
36
+ *
37
+ * Resolves the output mode from CLI flags, environment variables, or defaults.
38
+ * Returns both the resolved mode and its source so callers can make decisions
39
+ * based on how the mode was determined.
40
+ *
41
+ * **Resolution order (highest wins):**
42
+ * 1. Explicit `--output` / `-o` flag (source: `"flag"`)
43
+ * 2. Legacy `--json` / `--jsonl` boolean flags (source: `"flag"`)
44
+ * 3. `OUTFITTER_JSONL=1` / `OUTFITTER_JSON=1` env vars (source: `"env"`)
45
+ * 4. Configured default — typically `"human"` (source: `"default"`)
46
+ *
47
+ * When `forceHumanWhenImplicit` is set, steps 3–4 collapse to `"human"`.
48
+ *
49
+ * @param flags - Raw Commander flags (from `context.flags`)
50
+ * @param config - Optional configuration
51
+ * @returns The resolved mode and its source
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * import { resolveOutputMode } from "@outfitter/cli/query";
56
+ *
57
+ * // In a mapInput function:
58
+ * const { mode, source } = resolveOutputMode(context.flags);
59
+ * // mode: "human" | "json" | "jsonl"
60
+ * // source: "flag" | "env" | "default"
61
+ * ```
62
+ */
63
+ declare function resolveOutputMode(flags: Record<string, unknown>, config?: ResolveOutputModeConfig): ResolvedOutputMode;
2
64
  /**
3
65
  * Configuration for the output mode preset.
4
66
  */
@@ -38,6 +100,26 @@ type JqFlags = {
38
100
  readonly jq: string | undefined;
39
101
  };
40
102
  /**
103
+ * Resolved stream flags from CLI input.
104
+ */
105
+ type StreamFlags = {
106
+ /** Whether NDJSON streaming mode is enabled */
107
+ readonly stream: boolean;
108
+ };
109
+ /**
110
+ * NDJSON streaming flag preset.
111
+ *
112
+ * Adds: `--stream`
113
+ * Resolves: `{ stream: boolean }`
114
+ *
115
+ * When enabled, the CLI writes progress events as newline-delimited JSON
116
+ * (NDJSON) to stdout. The final line is the standard command envelope.
117
+ *
118
+ * `--stream` is orthogonal to output mode — it controls delivery, not
119
+ * serialization. Works alongside `--output human|json|jsonl` and env vars.
120
+ */
121
+ declare function streamPreset(): FlagPreset<StreamFlags>;
122
+ /**
41
123
  * JQ expression flag preset.
42
124
  *
43
125
  * Adds: `--jq <expr>`
@@ -47,4 +129,4 @@ type JqFlags = {
47
129
  * Actual jq execution is a consumer concern.
48
130
  */
49
131
  declare function jqPreset(): FlagPreset<JqFlags>;
50
- export { outputModePreset, jqPreset, OutputModePresetConfig, OutputModeFlags, JqFlags };
132
+ export { streamPreset, resolveOutputMode, outputModePreset, jqPreset, StreamFlags, ResolvedOutputMode, ResolveOutputModeConfig, OutputModeSource, OutputModePresetConfig, OutputModeFlags, JqFlags };
package/dist/query.js CHANGED
@@ -1,51 +1,14 @@
1
1
  // @bun
2
2
  import {
3
- createPreset
4
- } from "./shared/@outfitter/cli-pdb7znbq.js";
5
-
6
- // packages/cli/src/query.ts
7
- function outputModePreset(config) {
8
- const defaultMode = config?.defaultMode ?? "human";
9
- const baseModes = config?.modes ?? ["human", "json"];
10
- const modes = new Set(config?.includeJsonl ? [...baseModes, "jsonl"] : baseModes);
11
- modes.add(defaultMode);
12
- return createPreset({
13
- id: "outputMode",
14
- options: [
15
- {
16
- flags: "-o, --output <mode>",
17
- description: `Output mode (${[...modes].join(", ")})`,
18
- defaultValue: defaultMode
19
- }
20
- ],
21
- resolve: (flags) => {
22
- const raw = flags["output"];
23
- if (typeof raw === "string" && modes.has(raw)) {
24
- return { outputMode: raw };
25
- }
26
- return { outputMode: defaultMode };
27
- }
28
- });
29
- }
30
- function jqPreset() {
31
- return createPreset({
32
- id: "jq",
33
- options: [
34
- {
35
- flags: "--jq <expr>",
36
- description: "Filter JSON output with a jq expression"
37
- }
38
- ],
39
- resolve: (flags) => {
40
- const raw = flags["jq"];
41
- if (typeof raw === "string" && raw.length > 0) {
42
- return { jq: raw };
43
- }
44
- return { jq: undefined };
45
- }
46
- });
47
- }
3
+ jqPreset,
4
+ outputModePreset,
5
+ resolveOutputMode,
6
+ streamPreset
7
+ } from "./shared/@outfitter/cli-vvvhjwks.js";
8
+ import"./shared/@outfitter/cli-8999qjdd.js";
48
9
  export {
10
+ streamPreset,
11
+ resolveOutputMode,
49
12
  outputModePreset,
50
13
  jqPreset
51
14
  };
@@ -0,0 +1,80 @@
1
+ import { Option } from "commander";
2
+ /** Result of unwrapping a Zod field's type chain. */
3
+ interface ZodFieldInfo {
4
+ /** The base Zod type name (string, number, boolean, enum). */
5
+ readonly baseType: string;
6
+ /** Default value if .default() was used. */
7
+ readonly defaultValue: unknown;
8
+ /** Description from .describe(). */
9
+ readonly description: string | undefined;
10
+ /** Enum values if baseType is 'enum'. */
11
+ readonly enumValues: readonly string[] | undefined;
12
+ /** Whether .default() was used. */
13
+ readonly hasDefault: boolean;
14
+ /** Whether the field is optional. */
15
+ readonly isOptional: boolean;
16
+ }
17
+ /** Derived Commander flag definition from a Zod field. */
18
+ interface DerivedFlag {
19
+ /** Commander default value. */
20
+ readonly defaultValue: unknown;
21
+ /** Commander option description. */
22
+ readonly description: string;
23
+ /** Commander flag string (e.g., "--output-dir <value>"). */
24
+ readonly flagString: string;
25
+ /** Whether this is a boolean flag (no value). */
26
+ readonly isBoolean: boolean;
27
+ /** Whether the field is required (no default, not optional). */
28
+ readonly isRequired: boolean;
29
+ /** Long flag name including dashes (e.g., "--output-dir"). */
30
+ readonly longFlag: string;
31
+ /** Original camelCase field name from the Zod schema. */
32
+ readonly name: string;
33
+ }
34
+ /**
35
+ * Convert a camelCase string to kebab-case.
36
+ */
37
+ declare function camelToKebab(str: string): string;
38
+ /**
39
+ * Unwrap a Zod field to extract its base type, description, default, and optionality.
40
+ *
41
+ * Handles chains like: z.string().optional().default('hi').describe('desc')
42
+ */
43
+ declare function unwrapZodField(field: unknown): ZodFieldInfo;
44
+ /**
45
+ * Derive Commander flag definitions from a Zod object schema.
46
+ *
47
+ * Handles:
48
+ * - z.string() → `--name <value>` (string option)
49
+ * - z.number() → `--count <n>` (number option with coercion)
50
+ * - z.boolean() → `--verbose` (boolean flag)
51
+ * - z.enum(['a','b']) → `--format <value>` with choices
52
+ * - .describe() → option description
53
+ * - .default() → option default
54
+ * - .optional() → not required
55
+ */
56
+ declare function deriveFlags(schema: {
57
+ shape: Record<string, unknown>;
58
+ }, explicitLongFlags: ReadonlySet<string>): DerivedFlag[];
59
+ /**
60
+ * Create a Commander Option from a derived flag definition,
61
+ * including choices for enum types and argParser for number types.
62
+ */
63
+ declare function createCommanderOption(flag: DerivedFlag, schema: {
64
+ shape: Record<string, unknown>;
65
+ }): Option;
66
+ /**
67
+ * Extract validated input from parsed Commander flags using a Zod schema.
68
+ *
69
+ * Maps Commander flag values (which use camelCase keys) to the schema
70
+ * field names, then runs Zod validation to apply defaults and coercion.
71
+ */
72
+ declare function validateInput(flags: Record<string, unknown>, schema: {
73
+ shape: Record<string, unknown>;
74
+ safeParse: (data: unknown) => {
75
+ success: boolean;
76
+ data?: unknown;
77
+ error?: unknown;
78
+ };
79
+ }): Record<string, unknown>;
80
+ export { validateInput, unwrapZodField, deriveFlags, createCommanderOption, camelToKebab, ZodFieldInfo, DerivedFlag };
@@ -0,0 +1,15 @@
1
+ // @bun
2
+ import {
3
+ camelToKebab,
4
+ createCommanderOption,
5
+ deriveFlags,
6
+ unwrapZodField,
7
+ validateInput
8
+ } from "./shared/@outfitter/cli-3jta1h1h.js";
9
+ export {
10
+ validateInput,
11
+ unwrapZodField,
12
+ deriveFlags,
13
+ createCommanderOption,
14
+ camelToKebab
15
+ };
package/dist/schema.d.ts CHANGED
@@ -1,2 +1,5 @@
1
- import { ActionManifest, ActionManifestEntry, ActionSource, GenerateManifestOptions, SchemaCommandOptions, SurfaceCommandOptions, createSchemaCommand, formatManifestHuman, generateManifest } from "./shared/@outfitter/cli-n1k0d23k.js";
1
+ import { ActionManifest, ActionManifestEntry, ActionSource, GenerateManifestOptions, generateManifest } from "./shared/@outfitter/cli-cgha038c.js";
2
+ import { createSchemaCommand } from "./shared/@outfitter/cli-nbpgw7z7.js";
3
+ import { SchemaCommandOptions, SurfaceCommandOptions } from "./shared/@outfitter/cli-wjv7g1aq.js";
4
+ import { formatManifestHuman } from "./shared/@outfitter/cli-qcskd96y.js";
2
5
  export { generateManifest, formatManifestHuman, createSchemaCommand, SurfaceCommandOptions, SchemaCommandOptions, GenerateManifestOptions, ActionSource, ActionManifestEntry, ActionManifest };
package/dist/schema.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createSchemaCommand,
4
4
  formatManifestHuman,
5
5
  generateManifest
6
- } from "./shared/@outfitter/cli-0cjts94k.js";
6
+ } from "./shared/@outfitter/cli-zv3ah6f0.js";
7
7
  export {
8
8
  generateManifest,
9
9
  formatManifestHuman,
@@ -0,0 +1,45 @@
1
+ import { OutputMode, OutputOptions } from "./cli-x6qr7bnd.js";
2
+ /**
3
+ * Detects output mode based on explicit format, environment, and options.
4
+ *
5
+ * Priority: explicit format > env var > default (human)
6
+ *
7
+ * Per CLI conventions (clig.dev), human output is the default.
8
+ * Machine-readable output requires explicit opt-in via --json flag
9
+ * or OUTFITTER_JSON=1 environment variable.
10
+ */
11
+ declare function detectMode(format?: OutputMode): OutputMode;
12
+ /**
13
+ * Safe JSON stringify that handles circular references and undefined values.
14
+ * Wraps contracts' safeStringify with undefined -> null conversion for CLI JSON output.
15
+ */
16
+ declare function cliStringify(value: unknown, pretty?: boolean): string;
17
+ /**
18
+ * Formats data for human-readable output.
19
+ */
20
+ declare function formatHuman(data: unknown): string;
21
+ /**
22
+ * Gets the exit code for an error based on its category.
23
+ * Uses exitCodeMap from @outfitter/contracts for known categories.
24
+ */
25
+ declare function getExitCode(error: Error): number;
26
+ /**
27
+ * Serializes an error to JSON format for CLI output.
28
+ * Handles both OutfitterError instances and plain Error objects.
29
+ */
30
+ declare function serializeErrorToJson(error: Error): string;
31
+ /**
32
+ * Formats an error for human-readable output.
33
+ */
34
+ declare function formatErrorHuman(error: Error): string;
35
+ type OutputSliceTruncation = Pick<NonNullable<OutputOptions["truncation"]>, "limit" | "offset">;
36
+ /**
37
+ * Applies array truncation (limit/offset) to output data.
38
+ */
39
+ declare function applyOutputTruncation(data: unknown, truncation: OutputSliceTruncation | undefined): unknown;
40
+ /**
41
+ * Writes to a stream with proper backpressure handling.
42
+ * Returns a promise that resolves when the write is complete.
43
+ */
44
+ declare function writeWithBackpressure(stream: NodeJS.WritableStream, data: string): Promise<void>;
45
+ export { detectMode, cliStringify, formatHuman, getExitCode, serializeErrorToJson, formatErrorHuman, applyOutputTruncation, writeWithBackpressure };
@@ -0,0 +1,71 @@
1
+ import { CommandMetadata } from "./cli-xde45xcc.js";
2
+ /**
3
+ * Option metadata in the command tree.
4
+ */
5
+ interface CommandTreeOption {
6
+ /** Commander flag string (e.g., "--limit <n>") */
7
+ readonly flags: string;
8
+ /** Option description */
9
+ readonly description: string;
10
+ /** Default value (absent when no default) */
11
+ readonly defaultValue?: unknown;
12
+ /** Whether the option is required */
13
+ readonly required?: boolean;
14
+ }
15
+ /**
16
+ * A node in the command tree representing a single command or subcommand.
17
+ */
18
+ interface CommandTreeNode {
19
+ /** Command name */
20
+ readonly name: string;
21
+ /** Command description */
22
+ readonly description?: string;
23
+ /** Safety metadata signals (readOnly, idempotent) */
24
+ readonly metadata?: CommandMetadata;
25
+ /** Available options/flags */
26
+ readonly options?: readonly CommandTreeOption[];
27
+ /** Nested subcommands */
28
+ readonly subcommands?: readonly CommandTreeNode[];
29
+ }
30
+ /**
31
+ * Full command tree for a CLI application.
32
+ *
33
+ * Used for self-documenting root command output in JSON mode.
34
+ */
35
+ interface CommandTree {
36
+ /** CLI name */
37
+ readonly name: string;
38
+ /** CLI version */
39
+ readonly version: string;
40
+ /** CLI description */
41
+ readonly description?: string;
42
+ /** Top-level commands */
43
+ readonly commands: readonly CommandTreeNode[];
44
+ }
45
+ /**
46
+ * An edge in the action graph representing a relationship between commands.
47
+ */
48
+ interface ActionGraphEdge {
49
+ /** Source command name */
50
+ readonly from: string;
51
+ /** Target command name */
52
+ readonly to: string;
53
+ /** Relationship description (if provided) */
54
+ readonly description?: string;
55
+ }
56
+ /**
57
+ * An action graph built from `.relatedTo()` declarations on registered commands.
58
+ *
59
+ * Nodes are command names, edges are relationship declarations.
60
+ * Used for tier-4 hint generation — success hints include next-actions
61
+ * from graph neighbors, error hints include remediation paths.
62
+ */
63
+ interface ActionGraph {
64
+ /** All registered command names */
65
+ readonly nodes: readonly string[];
66
+ /** Relationship edges between commands */
67
+ readonly edges: readonly ActionGraphEdge[];
68
+ /** Warnings for invalid references (e.g., unknown targets) */
69
+ readonly warnings?: readonly string[];
70
+ }
71
+ export { CommandTreeOption, CommandTreeNode, CommandTree, ActionGraphEdge, ActionGraph };