From 5c51a5cec56d21e4856ef54ee14e1009e5217006 Mon Sep 17 00:00:00 2001 From: tmm Date: Wed, 15 Apr 2026 13:07:37 -0400 Subject: [PATCH] feat!: rename global verbose flag to full-output --- .changeset/pretty-ads-fry.md | 5 ++ README.md | 22 ++++---- SKILL.md | 12 ++-- src/Cli.test.ts | 105 +++++++++++++++++++++-------------- src/Cli.ts | 28 +++++----- src/Help.test.ts | 34 ++++++------ src/Help.ts | 2 +- src/Openapi.test.ts | 8 +-- src/e2e.test.ts | 100 +++++++++++++++++++-------------- 9 files changed, 181 insertions(+), 135 deletions(-) create mode 100644 .changeset/pretty-ads-fry.md diff --git a/.changeset/pretty-ads-fry.md b/.changeset/pretty-ads-fry.md new file mode 100644 index 0000000..f09fad3 --- /dev/null +++ b/.changeset/pretty-ads-fry.md @@ -0,0 +1,5 @@ +--- +'incur': minor +--- + +**Breaking:** Renamed the global full-envelope flag from `--verbose` to `--full-output`, allowing `--verbose` to be used as a normal command option. diff --git a/README.md b/README.md index 37e98d2..7655d83 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ - [**`--llms` flag**](#agent-discovery): token-efficient command manifest in Markdown or JSON schema - [**Well-formed I/O**](#well-formed-io): Schemas schemas for arguments, options, environment variables, and output - [**Inferred types**](#inferred-types): generic type flow from schemas to `run` callbacks with zero manual annotations -- [**Global options**](#global-options): `--format`, `--json`, `--verbose`, `--help`, `--version` on every CLI for free +- [**Global options**](#global-options): `--format`, `--full-output`, `--help`, `--json`, `--version` on every CLI for free - [**Light API surface**](#light-api-surface): `Cli.create()`, `.command()`, `.serve()` – that's it - [**Middleware**](#middleware): composable before/after hooks with typed dependency injection via `cli.use()` @@ -116,6 +116,7 @@ $ greet --help # Global Options: # --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) # --format Output format +# --full-output Show full output envelope # --help Show help # --llms Print LLM-readable manifest # --mcp Start as MCP stdio server @@ -123,7 +124,6 @@ $ greet --help # --token-count Print token count of output instead of output # --token-limit Limit output to n tokens # --token-offset Skip first n tokens of output (for pagination) -# --verbose Show full output envelope # --version Show version ``` @@ -186,6 +186,7 @@ $ my-cli --help # Global Options: # --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) # --format Output format +# --full-output Show full output envelope # --help Show help # --llms Print LLM-readable manifest # --mcp Start as MCP stdio server @@ -193,7 +194,6 @@ $ my-cli --help # --token-count Print token count of output instead of output # --token-limit Limit output to n tokens # --token-offset Skip first n tokens of output (for pagination) -# --verbose Show full output envelope # --version Show version ``` @@ -243,6 +243,7 @@ $ my-cli --help # Global Options: # --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) # --format Output format +# --full-output Show full output envelope # --help Show help # --llms Print LLM-readable manifest # --mcp Start as MCP stdio server @@ -250,7 +251,6 @@ $ my-cli --help # --token-count Print token count of output instead of output # --token-limit Limit output to n tokens # --token-offset Skip first n tokens of output (for pagination) -# --verbose Show full output envelope # --version Show version ``` @@ -370,7 +370,7 @@ GET /users/42 → my-cli users 42 POST /users { "name": "Bob" } → my-cli users --name Bob ``` -Responses use the same JSON envelope as `--verbose --format json`: +Responses use the same JSON envelope as `--full-output --format json`: ```json { "ok": true, "data": { "users": [...] }, "meta": { "command": "users", "duration": "3ms" } } @@ -411,7 +411,7 @@ my-cli --llms Most CLIs expose tools via MCP or a single monolithic skill file. incur combines on-demand skill loading with TOON output to cut token usage across the entire session – from discovery through invocation and response. -The table below models a session with a 20-command CLI producing verbose output. +The table below models a session with a 20-command CLI producing full output envelopes. - **Session start** – tokens consumed just by having the tool available. _MCP injects all tool schemas into every turn; skills only load frontmatter (name + description)._ - **Discovery** – tokens to learn what commands exist and how to call them. _MCP gets this at session start; skills load the full skill file on demand; incur splits by command group so only relevant commands are loaded._ @@ -620,7 +620,7 @@ cli.command('greet', { ### Output policy -Control whether output data is displayed to humans. By default, output goes to everyone (`'all'`). Set `outputPolicy: 'agent-only'` to suppress data in TTY mode while still returning it to agents via `--json`, `--format`, or `--verbose`. +Control whether output data is displayed to humans. By default, output goes to everyone (`'all'`). Set `outputPolicy: 'agent-only'` to suppress data in TTY mode while still returning it to agents via `--json`, `--format`, or `--full-output`. ```ts cli.command('deploy', { @@ -803,18 +803,18 @@ Every incur CLI includes these flags automatically: | Flag | Description | | ------------------------ | ------------------------------------------------------ | +| `--filter-output ` | Filter output by key paths (e.g. `foo,bar.baz,a[0,3]`) | +| `--format ` | Output format: `toon`, `json`, `yaml`, `md` | +| `--full-output` | Include full envelope (`ok`, `data`, `meta`) | | `--help`, `-h` | Show help for the CLI or a specific command | -| `--version` | Print CLI version | | `--llms` | Output agent-readable command manifest | | `--mcp` | Start as an MCP stdio server | | `--json` | Shorthand for `--format json` | -| `--format ` | Output format: `toon`, `json`, `yaml`, `md` | -| `--filter-output ` | Filter output by key paths (e.g. `foo,bar.baz,a[0,3]`) | | `--schema` | Show JSON Schema for command's args, options, output | | `--token-count` | Print token count of output instead of output | | `--token-limit ` | Limit output to n tokens (for pagination) | | `--token-offset ` | Skip first n tokens of output (for pagination) | -| `--verbose` | Include full envelope (`ok`, `data`, `meta`) | +| `--version` | Print CLI version | ### Config file diff --git a/SKILL.md b/SKILL.md index 228b396..6bb33bf 100644 --- a/SKILL.md +++ b/SKILL.md @@ -419,10 +419,10 @@ Control with `--format ` or `--json`: ### Envelope -With `--verbose`, the full envelope is emitted: +With `--full-output`, the full envelope is emitted: ```sh -tool info express --verbose +tool info express --full-output ``` ``` @@ -435,7 +435,7 @@ meta: duration: 12ms ``` -Without `--verbose`, only `data` is emitted. On errors, only the `error` block is emitted. +Without `--full-output`, only `data` is emitted. On errors, only the `error` block is emitted. ### Filtering output @@ -482,7 +482,7 @@ tool users --token-limit 20 tool users --token-offset 20 --token-limit 20 ``` -With `--verbose`, truncated output includes `meta.nextOffset` for programmatic pagination. +With `--full-output`, truncated output includes `meta.nextOffset` for programmatic pagination. ### Command schema @@ -725,7 +725,7 @@ Use `--llms --format json` for JSON schema manifest: | `--mcp` | Start as an MCP stdio server | | `--json` | Shorthand for `--format json` | | `--format ` | Output format: `toon`, `json`, `yaml`, `md` | -| `--verbose` | Include full envelope (`ok`, `data`, `meta`) | +| `--full-output` | Include full envelope (`ok`, `data`, `meta`) | ## Examples @@ -760,7 +760,7 @@ Hints are displayed after examples in help output and included in skill files. ### Output policy -Control whether output data is displayed to humans. `'all'` (default) shows output to everyone. `'agent-only'` suppresses data in human/TTY mode while still returning it via `--json`, `--format`, or `--verbose`. +Control whether output data is displayed to humans. `'all'` (default) shows output to everyone. `'agent-only'` suppresses data in human/TTY mode while still returning it via `--json`, `--format`, or `--full-output`. ```ts cli.command('deploy', { diff --git a/src/Cli.test.ts b/src/Cli.test.ts index 1eafd0a..8409a45 100644 --- a/src/Cli.test.ts +++ b/src/Cli.test.ts @@ -630,7 +630,7 @@ describe('serve', () => { `) }) - test('--verbose outputs full envelope', async () => { + test('--full-output outputs full envelope', async () => { const cli = Cli.create('test') cli.command('greet', { args: z.object({ name: z.string() }), @@ -639,7 +639,7 @@ describe('serve', () => { }, }) - const { output } = await serve(cli, ['greet', 'world', '--verbose']) + const { output } = await serve(cli, ['greet', 'world', '--full-output']) expect(output).toMatchInlineSnapshot(` "ok: true data: @@ -714,10 +714,10 @@ describe('serve', () => { `) }) - test('--verbose outputs full error envelope for unknown command', async () => { + test('--full-output outputs full error envelope for unknown command', async () => { const cli = Cli.create('test') - const { output, exitCode } = await serve(cli, ['nonexistent', '--verbose']) + const { output, exitCode } = await serve(cli, ['nonexistent', '--full-output']) expect(exitCode).toBe(1) expect(output).toMatchInlineSnapshot(` "ok: false @@ -787,8 +787,8 @@ describe('serve', () => { const cli = Cli.create('test') cli.command('deploy', { run: () => ({}) }) - const { output } = await serve(cli, ['deplyo', '--verbose']) - expect(output).toContain('test deploy --verbose') + const { output } = await serve(cli, ['deplyo', '--full-output']) + expect(output).toContain('test deploy --full-output') }) test('no suggestion when input is too far from any command', async () => { @@ -990,10 +990,10 @@ describe('serve', () => { expect(JSON.parse(output)).toEqual({ pong: true }) }) - test('--verbose --format json outputs full envelope as JSON', async () => { + test('--full-output --format json outputs full envelope as JSON', async () => { const cli = Cli.create('test') cli.command('ping', { run: () => ({ pong: true }) }) - const { output } = await serve(cli, ['ping', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['ping', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.ok).toBe(true) expect(parsed.data).toEqual({ pong: true }) @@ -1479,14 +1479,14 @@ describe('subcommands', () => { `) }) - test('--verbose shows full command path in meta', async () => { + test('--full-output shows full command path in meta', async () => { const cli = Cli.create('test') const pr = Cli.create('pr', { description: 'PR management' }).command('list', { run: () => ({ count: 0 }), }) cli.command(pr) - const { output } = await serve(cli, ['pr', 'list', '--verbose']) + const { output } = await serve(cli, ['pr', 'list', '--full-output']) expect(output).toMatchInlineSnapshot(` "ok: true data: @@ -1514,7 +1514,7 @@ describe('subcommands', () => { `) }) - test('nested group shows full path in verbose meta', async () => { + test('nested group shows full path in full-output meta', async () => { const cli = Cli.create('test') const review = Cli.create('review', { description: 'Reviews' }).command('approve', { run: () => ({ approved: true }), @@ -1523,7 +1523,7 @@ describe('subcommands', () => { pr.command(review) cli.command(pr) - const { output } = await serve(cli, ['pr', 'review', 'approve', '--verbose']) + const { output } = await serve(cli, ['pr', 'review', 'approve', '--full-output']) expect(output).toMatchInlineSnapshot(` "ok: true data: @@ -1596,13 +1596,13 @@ describe('subcommands', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -1685,7 +1685,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['list', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['list', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta).toEqual({ description: 'Suggested commands:', @@ -1706,7 +1706,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['list', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['list', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta.commands).toEqual([ { command: 'test get 1', description: 'View item 1' }, @@ -1735,7 +1735,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['create', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['create', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta.commands).toEqual([ { command: 'test get 1 --limit 10', description: 'View the item' }, @@ -1755,7 +1755,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['list', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['list', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta.commands).toEqual([{ command: 'test get --format ' }]) }) @@ -1773,7 +1773,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['create', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['create', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta.description).toBe('View the created item:') }) @@ -1782,7 +1782,7 @@ describe('cta', () => { const cli = Cli.create('test') cli.command('ping', { run: () => ({ pong: true }) }) - const { output } = await serve(cli, ['ping', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['ping', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta).toBeUndefined() }) @@ -1795,7 +1795,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['noop', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['noop', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.meta.cta).toBeUndefined() }) @@ -1815,7 +1815,7 @@ describe('cta', () => { }, }) - const { output, exitCode } = await serve(cli, ['fail', '--verbose', '--format', 'json']) + const { output, exitCode } = await serve(cli, ['fail', '--full-output', '--format', 'json']) expect(exitCode).toBe(1) const parsed = JSON.parse(output) expect(parsed.ok).toBe(false) @@ -1833,7 +1833,7 @@ describe('cta', () => { }, }) - const { output, exitCode } = await serve(cli, ['fail', '--verbose', '--format', 'json']) + const { output, exitCode } = await serve(cli, ['fail', '--full-output', '--format', 'json']) expect(exitCode).toBe(1) const parsed = JSON.parse(output) expect(parsed.meta.cta).toBeUndefined() @@ -1847,7 +1847,7 @@ describe('cta', () => { }, }) - const { output } = await serve(cli, ['fail', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['fail', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.ok).toBe(false) expect(parsed.meta.cta).toBeUndefined() @@ -1869,7 +1869,14 @@ describe('cta', () => { }) cli.command(pr) - const { output } = await serve(cli, ['pr', 'create', 'my-pr', '--verbose', '--format', 'json']) + const { output } = await serve(cli, [ + 'pr', + 'create', + 'my-pr', + '--full-output', + '--format', + 'json', + ]) const parsed = JSON.parse(output) expect(parsed.meta.cta).toEqual({ description: 'Suggested command:', @@ -1909,9 +1916,25 @@ describe('leaf cli', () => { `) }) - test('--verbose outputs full envelope', async () => { - const cli = Cli.create('ping', { run: () => ({ pong: true }) }) + test('command option named verbose is parsed by the command', async () => { + const cli = Cli.create('ping', { + options: z.object({ verbose: z.boolean().default(false) }), + run({ options }) { + return options + }, + }) + const { output } = await serve(cli, ['--verbose']) + + expect(output).toMatchInlineSnapshot(` + "verbose: true + " + `) + }) + + test('--full-output outputs full envelope', async () => { + const cli = Cli.create('ping', { run: () => ({ pong: true }) }) + const { output } = await serve(cli, ['--full-output']) expect(output).toMatchInlineSnapshot(` "ok: true data: @@ -2035,6 +2058,7 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --mcp Start as MCP stdio server @@ -2042,7 +2066,6 @@ describe('help', () => { --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope --version Show version " `) @@ -2073,6 +2096,7 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --mcp Start as MCP stdio server @@ -2080,7 +2104,6 @@ describe('help', () => { --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope --version Show version " `) @@ -2107,13 +2130,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -2141,13 +2164,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -2236,6 +2259,7 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --mcp Start as MCP stdio server @@ -2243,7 +2267,6 @@ describe('help', () => { --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope --version Show version " `) @@ -2268,13 +2291,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -2363,13 +2386,13 @@ describe('env', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope Environment Variables: API_TOKEN Auth token @@ -2401,13 +2424,13 @@ describe('env', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope Environment Variables: API_TOKEN Auth token (set: ****cret) @@ -2941,10 +2964,10 @@ describe('outputPolicy', () => { expect(deploy.output).not.toContain('deploy-123') expect(deploy.output).toContain('Check status') - // deploy --verbose: agent mode shows everything - const deployVerbose = await serve(cli, ['deploy', 'staging', '--verbose']) - expect(deployVerbose.output).toContain('deploy-123') - expect(deployVerbose.output).toContain('staging.example.com') + // deploy --full-output: agent mode shows everything + const deployFullOutput = await serve(cli, ['deploy', 'staging', '--full-output']) + expect(deployFullOutput.output).toContain('deploy-123') + expect(deployFullOutput.output).toContain('staging.example.com') // deploy --json: agent mode shows data const deployJson = await serve(cli, ['deploy', 'staging', '--json']) @@ -3700,11 +3723,11 @@ describe('fetch', async () => { expect(JSON.parse(output)).toEqual({ ok: true }) }) - test('--verbose includes request/response meta', async () => { + test('--full-output includes request/response meta', async () => { const cli = Cli.create('test', { description: 'test' }).command('api', { fetch: app.fetch, }) - const { output } = await serve(cli, ['api', 'health', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['api', 'health', '--full-output', '--format', 'json']) const parsed = JSON.parse(output) expect(parsed.ok).toBe(true) expect(parsed.data).toEqual({ ok: true }) @@ -4525,7 +4548,7 @@ describe('displayName', () => { }).command('ping', { run: (c) => c.ok({ ok: true }, { cta: { commands: ['login'] } }), }) - const { output } = await serve(cli, ['ping', '--json', '--verbose']) + const { output } = await serve(cli, ['ping', '--json', '--full-output']) const parsed = JSON.parse(output) expect(parsed.meta.cta.commands[0].command).toBe('mc login') }) diff --git a/src/Cli.ts b/src/Cli.ts index bbac2fa..47bbf20 100644 --- a/src/Cli.ts +++ b/src/Cli.ts @@ -487,7 +487,7 @@ async function serveImpl( } const { - verbose, + fullOutput, format: formatFlag, formatExplicit, filterOutput, @@ -782,9 +782,9 @@ async function serveImpl( lines.push('') lines.push(`Run \`${name} --help\` to see the full command reference.`) writeln(lines.join('\n')) - if (verbose || formatExplicit) { + if (fullOutput || formatExplicit) { const output: Record = { skills: result.paths } - if (verbose && result.agents.length > 0) output.agents = result.agents + if (fullOutput && result.agents.length > 0) output.agents = result.agents writeln(Formatter.format(output, formatExplicit ? formatFlag : 'toon')) } } catch (err) { @@ -865,7 +865,7 @@ async function serveImpl( for (const s of suggestions) lines.push(` "${s}"`) } writeln(lines.join('\n')) - if (verbose || formatExplicit) + if (fullOutput || formatExplicit) writeln( Formatter.format( { name, command: result.command, agents: result.agents }, @@ -1160,7 +1160,7 @@ async function serveImpl( return writeln(String(estimateTokenCount(formatted))) } const cta = output.meta.cta - if (human && !verbose) { + if (human && !fullOutput) { if (output.ok && output.data != null && renderOutput) { const t = truncate(Formatter.format(output.data, format)) writeln(t.text) @@ -1168,7 +1168,7 @@ async function serveImpl( if (cta) writeln(formatHumanCta(cta)) return } - if (verbose) { + if (fullOutput) { if (tokenLimit != null || tokenOffset != null) { // Truncate data separately so meta (including nextOffset) is always visible const dataFormatted = @@ -1219,7 +1219,7 @@ async function serveImpl( description: ctaCommands.length === 1 ? 'Suggested command:' : 'Suggested commands:', commands: ctaCommands, } - if (human && !verbose) { + if (human && !fullOutput) { writeln(formatHumanError({ code: 'COMMAND_NOT_FOUND', message })) const mergedCta = skillsCta ? { ...cta, commands: [...cta.commands, ...skillsCta.commands] } @@ -1266,7 +1266,7 @@ async function serveImpl( formatExplicit, human, renderOutput, - verbose, + fullOutput, truncate, write, writeln, @@ -1448,7 +1448,7 @@ async function serveImpl( formatExplicit, human, renderOutput, - verbose, + fullOutput, truncate, write, writeln, @@ -2028,11 +2028,11 @@ declare namespace serveImpl { } } -/** @internal Extracts built-in flags (--verbose, --format, --json, --llms, --help, --version) from argv. */ +/** @internal Extracts built-in flags (--full-output, --format, --json, --llms, --help, --version) from argv. */ const validFormats = new Set(['toon', 'json', 'yaml', 'md', 'jsonl'] as const) function extractBuiltinFlags(argv: string[], options: extractBuiltinFlags.Options = {}) { - let verbose = false + let fullOutput = false let llms = false let llmsFull = false let mcp = false @@ -2055,7 +2055,7 @@ function extractBuiltinFlags(argv: string[], options: extractBuiltinFlags.Option for (let i = 0; i < argv.length; i++) { const token = argv[i]! - if (token === '--verbose') verbose = true + if (token === '--full-output') fullOutput = true else if (token === '--llms') llms = true else if (token === '--llms-full') llmsFull = true else if (token === '--mcp') mcp = true @@ -2109,7 +2109,7 @@ function extractBuiltinFlags(argv: string[], options: extractBuiltinFlags.Option } return { - verbose, + fullOutput, format, formatExplicit, configPath, @@ -2495,7 +2495,7 @@ async function handleStreaming( formatExplicit: boolean human: boolean renderOutput: boolean - verbose: boolean + fullOutput: boolean truncate: (s: string) => { text: string; truncated: boolean; nextOffset?: number | undefined } write: (output: Output) => void writeln: (s: string) => void diff --git a/src/Help.test.ts b/src/Help.test.ts index 2079674..071bdfa 100644 --- a/src/Help.test.ts +++ b/src/Help.test.ts @@ -65,13 +65,13 @@ describe('formatCommand', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -87,13 +87,13 @@ describe('formatCommand', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -116,13 +116,13 @@ describe('formatCommand', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -248,14 +248,14 @@ describe('formatCommand', () => { --config Load JSON option defaults from a file --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --no-config Disable JSON option defaults for this run --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) }) @@ -283,13 +283,13 @@ describe('formatRoot', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -308,13 +308,13 @@ describe('formatRoot', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -337,13 +337,13 @@ describe('formatRoot', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -366,13 +366,13 @@ describe('formatRoot', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens - --token-offset Skip first n tokens of output - --verbose Show full output envelope" + --token-offset Skip first n tokens of output" `) }) @@ -399,6 +399,7 @@ describe('formatRoot', () => { --config Load JSON option defaults from a file --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --mcp Start as MCP stdio server @@ -407,7 +408,6 @@ describe('formatRoot', () => { --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope --version Show version" `) }) diff --git a/src/Help.ts b/src/Help.ts index cf2c019..d7537d5 100644 --- a/src/Help.ts +++ b/src/Help.ts @@ -380,7 +380,7 @@ function globalOptionsLines(root = false, configFlag?: string): string[] { { flag: '--token-count', desc: 'Print token count of output (instead of output)' }, { flag: '--token-limit ', desc: 'Limit output to n tokens' }, { flag: '--token-offset ', desc: 'Skip first n tokens of output' }, - { flag: '--verbose', desc: 'Show full output envelope' }, + { flag: '--full-output', desc: 'Show full output envelope' }, ...(root ? [{ flag: '--version', desc: 'Show version' }] : []), ].sort((a, b) => a.flag.localeCompare(b.flag)) const maxLen = Math.max(...flags.map((f) => f.flag.length)) diff --git a/src/Openapi.test.ts b/src/Openapi.test.ts index c40de4e..7b9064b 100644 --- a/src/Openapi.test.ts +++ b/src/Openapi.test.ts @@ -142,11 +142,11 @@ describe('cli integration', () => { expect(json(output)).toEqual({ ok: true }) }) - test('--verbose wraps in envelope', async () => { + test('--full-output wraps in envelope', async () => { const { output } = await serve(createCli(), [ 'api', 'healthCheck', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -254,11 +254,11 @@ describe('@hono/zod-openapi integration', () => { expect(json(output)).toEqual({ ok: true }) }) - test('--verbose wraps in envelope', async () => { + test('--full-output wraps in envelope', async () => { const { output } = await serve(createCli(), [ 'api', 'healthCheck', - '--verbose', + '--full-output', '--format', 'json', ]) diff --git a/src/e2e.test.ts b/src/e2e.test.ts index 0871978..750cd5c 100644 --- a/src/e2e.test.ts +++ b/src/e2e.test.ts @@ -173,7 +173,7 @@ describe('args and options', () => { 'read', '--scopes', 'write', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -192,7 +192,7 @@ describe('args and options', () => { 'list', '--limit', '5', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -327,8 +327,8 @@ describe('output formats', () => { `) }) - test('--verbose full envelope', async () => { - const { output } = await serve(createApp(), ['ping', '--verbose']) + test('--full-output full envelope', async () => { + const { output } = await serve(createApp(), ['ping', '--full-output']) expect(output).toMatchInlineSnapshot(` "ok: true data: @@ -340,8 +340,8 @@ describe('output formats', () => { `) }) - test('--verbose --format json full envelope', async () => { - const { output } = await serve(createApp(), ['ping', '--verbose', '--format', 'json']) + test('--full-output --format json full envelope', async () => { + const { output } = await serve(createApp(), ['ping', '--full-output', '--format', 'json']) expect(json(output)).toMatchInlineSnapshot(` { "data": { @@ -356,13 +356,13 @@ describe('output formats', () => { `) }) - test('nested command path in verbose meta', async () => { + test('nested command path in full-output meta', async () => { const { output } = await serve(createApp(), [ 'project', 'deploy', 'status', 'd-1', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -400,8 +400,8 @@ describe('undefined output', () => { expect(output).toBe('') }) - test('void command shows envelope with --verbose', async () => { - const { output } = await serve(createApp(), ['noop', '--verbose', '--format', 'json']) + test('void command shows envelope with --full-output', async () => { + const { output } = await serve(createApp(), ['noop', '--full-output', '--format', 'json']) expect(json(output)).toMatchInlineSnapshot(` { "meta": { @@ -455,10 +455,10 @@ describe('--token-limit and --token-offset', () => { `) }) - test('works with --verbose', async () => { + test('works with --full-output', async () => { const { output } = await serve(createApp(), [ 'ping', - '--verbose', + '--full-output', '--format', 'json', '--token-limit', @@ -479,10 +479,10 @@ describe('--token-limit and --token-offset', () => { `) }) - test('--verbose includes meta.nextOffset when truncated', async () => { + test('--full-output includes meta.nextOffset when truncated', async () => { const { output } = await serve(createApp(), [ 'ping', - '--verbose', + '--full-output', '--format', 'json', '--token-limit', @@ -492,10 +492,10 @@ describe('--token-limit and --token-offset', () => { expect(output).toContain('[truncated:') }) - test('--verbose omits meta.nextOffset when not truncated', async () => { + test('--full-output omits meta.nextOffset when not truncated', async () => { const { output } = await serve(createApp(), [ 'ping', - '--verbose', + '--full-output', '--format', 'json', '--token-limit', @@ -575,7 +575,7 @@ describe('error handling', () => { const { output, exitCode } = await serve(createApp(), [ 'auth', 'status', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -633,7 +633,7 @@ describe('error handling', () => { test('command not found returns error envelope', async () => { const { output, exitCode } = await serve(createApp(), [ 'nonexistent', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -676,7 +676,13 @@ describe('error handling', () => { describe('cta', () => { test('ok() with string CTAs', async () => { - const { output } = await serve(createApp(), ['auth', 'login', '--verbose', '--format', 'json']) + const { output } = await serve(createApp(), [ + 'auth', + 'login', + '--full-output', + '--format', + 'json', + ]) expect(json(output).meta.cta).toMatchInlineSnapshot(` { "commands": [ @@ -694,7 +700,7 @@ describe('cta', () => { 'project', 'create', 'MyProject', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -715,7 +721,13 @@ describe('cta', () => { }) test('error() with CTA', async () => { - const { output } = await serve(createApp(), ['auth', 'status', '--verbose', '--format', 'json']) + const { output } = await serve(createApp(), [ + 'auth', + 'status', + '--full-output', + '--format', + 'json', + ]) expect(json(output).meta.cta).toMatchInlineSnapshot(` { "commands": [ @@ -729,7 +741,7 @@ describe('cta', () => { }) test('plain return omits CTA', async () => { - const { output } = await serve(createApp(), ['ping', '--verbose', '--format', 'json']) + const { output } = await serve(createApp(), ['ping', '--full-output', '--format', 'json']) expect(json(output).meta.cta).toBeUndefined() }) @@ -738,7 +750,7 @@ describe('cta', () => { 'project', 'list', '--archived', - '--verbose', + '--full-output', '--format', 'json', ]) @@ -780,8 +792,8 @@ describe('streaming', () => { `) }) - test('default streams toon per chunk (--verbose)', async () => { - const { output } = await serve(createApp(), ['stream', '--verbose']) + test('default streams toon per chunk (--full-output)', async () => { + const { output } = await serve(createApp(), ['stream', '--full-output']) expect(output).toMatchInlineSnapshot(` "content: hello content: world @@ -803,8 +815,8 @@ describe('streaming', () => { `) }) - test('--format json --verbose buffers with envelope', async () => { - const { output } = await serve(createApp(), ['stream', '--verbose', '--format', 'json']) + test('--format json --full-output buffers with envelope', async () => { + const { output } = await serve(createApp(), ['stream', '--full-output', '--format', 'json']) expect(json(output)).toMatchInlineSnapshot(` { "data": [ @@ -972,6 +984,7 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --mcp Start as MCP stdio server @@ -979,7 +992,6 @@ describe('help', () => { --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope --version Show version " `) @@ -1006,13 +1018,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -1033,13 +1045,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -1059,13 +1071,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -1091,13 +1103,13 @@ describe('help', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope " `) }) @@ -1747,6 +1759,7 @@ describe('root command with subcommands', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --mcp Start as MCP stdio server @@ -1754,7 +1767,6 @@ describe('root command with subcommands', () => { --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope --version Show version " `) @@ -1865,7 +1877,7 @@ describe('edge cases', () => { 'prod', '--branch', 'release', - '--verbose', + '--full-output', ]) expect(json(output)).toMatchInlineSnapshot(` { @@ -1894,7 +1906,7 @@ describe('env', () => { test('env vars passed to handler', async () => { const { output } = await serve( createApp(), - ['auth', 'login', '--verbose', '--format', 'json'], + ['auth', 'login', '--full-output', '--format', 'json'], { env: { AUTH_HOST: 'custom.example.com' } }, ) expect(json(output).data.hostname).toBe('custom.example.com') @@ -1903,7 +1915,7 @@ describe('env', () => { test('env defaults applied when var is unset', async () => { const { output } = await serve( createApp(), - ['auth', 'login', '--verbose', '--format', 'json'], + ['auth', 'login', '--full-output', '--format', 'json'], { env: {} }, ) expect(json(output).data.hostname).toBe('api.example.com') @@ -1924,13 +1936,13 @@ describe('env', () => { Global Options: --filter-output Filter output by key paths (e.g. foo,bar.baz,a[0,3]) --format Output format + --full-output Show full output envelope --help Show help --llms, --llms-full Print LLM-readable manifest --schema Show JSON Schema for command --token-count Print token count of output (instead of output) --token-limit Limit output to n tokens --token-offset Skip first n tokens of output - --verbose Show full output envelope Environment Variables: AUTH_TOKEN Pre-existing auth token @@ -2037,9 +2049,9 @@ describe('middleware', () => { `) }) - test('vars: verbose envelope includes var data', async () => { + test('vars: full-output envelope includes var data', async () => { const { cli } = createMiddlewareApp() - const { output } = await serve(cli, ['whoami', '--verbose', '--format', 'json']) + const { output } = await serve(cli, ['whoami', '--full-output', '--format', 'json']) const parsed = json(output) expect(parsed.data.user).toBe('alice') expect(parsed.data.requestId).toBe('req-default') @@ -2276,8 +2288,14 @@ describe('fetch gateway', () => { expect(json(output)).toEqual({ ok: true }) }) - test('--verbose wraps in envelope', async () => { - const { output } = await serve(createApp(), ['api', 'health', '--verbose', '--format', 'json']) + test('--full-output wraps in envelope', async () => { + const { output } = await serve(createApp(), [ + 'api', + 'health', + '--full-output', + '--format', + 'json', + ]) const parsed = json(output) expect(parsed.ok).toBe(true) expect(parsed.data).toEqual({ ok: true })