feat(cli-v2): add --json global flag with structured error envelope#16042
Open
iamnamananand996 wants to merge 2 commits into
Open
feat(cli-v2): add --json global flag with structured error envelope#16042iamnamananand996 wants to merge 2 commits into
iamnamananand996 wants to merge 2 commits into
Conversation
Adds a --json global flag that renders errors as a JSON envelope on stderr for CI pipelines and agents:
{
"ok": false,
"code": "AUTH_ERROR",
"message": "You are not logged in.",
"hint": "Run `fern auth login`.",
"docsLink": "https://buildwithfern.com/learn/cli/auth",
"violations": [...],
"logFile": "~/.fern/v1/logs/...",
"debug": { "stack": "...", "causes": [...] }
}
- Threads json through withContext.handleError + the shared yargs fail handler
- ValidationError and SourcedValidationError serialize each violation with file/line/column
- --debug --json adds stack and cause-chain info under debug.*
- logFile is embedded so CI/agents don't need to parse the dim hint line
- 13 new tests cover every branch (TaskAbortSignal, CliError, ValidationError,
SourcedValidationError, generic Error, non-Error throwables, logFile,
debug=true/false, ANSI-free output)
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
This was referenced May 21, 2026
Import assertNever and change titleForCode to have no fallback, returning explicit titles for all known CliError codes (including a new INTERNAL_ERROR case). Replace previous fallback usages at call sites with the new titleForCode signature and use assertNever in the default branch to enforce exhaustiveness and improve type safety. Update error envelope building so default messages use titleForCode directly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Linear ticket: Refs FER-10016
Wave-2 R13 of the cli-v2 error UX/DX cleanup: a
--jsonglobal flag that renders failures as a structured JSON envelope on stderr, so CI pipelines and agents can parse error details without scraping human output.Stacked on #16040 (wave-1 renderer +
--debug). Re-target tomainafter #16040 merges.Envelope shape
{ "ok": false, "code": "AUTH_ERROR", "message": "You are not logged in.", "hint": "Run `fern auth login`.", "docsLink": "https://buildwithfern.com/learn/cli/auth", "violations": [ { "severity": "error", "message": "...", "file": "fern.yml", "line": 7, "column": 13 } ], "logFile": "~/.fern/v1/logs/2026-05-20T18-58-00.log", "debug": { "stack": "...", "causes": ["..."] } }codeisnullfor non-CliErrorfailures (plainError, unknown throwables).violationsis populated forValidationErrorandSourcedValidationError; the latter includesfile/line/columnfrom the YAML source.logFileis only set when there's something written to the per-run debug log.debugonly appears when--debug(orFERN_DEBUG=1) is also on.TaskAbortSignal(Ctrl+C) still returnsnull— no envelope is emitted on clean shutdowns.Changes Made
ErrorEnvelope/ErrorEnvelopeViolation/ErrorEnvelopeDebugtypes andbuildErrorEnvelope()inpackages/cli/cli-v2/src/errors/renderError.ts.renderError(error, { json: true })short-circuits to the JSON path.packages/cli/cli-v2/src/context/GlobalArgs.ts: addedjson?: boolean.packages/cli/cli-v2/src/cli.ts: registers--jsonas a global yargs option (commands that already declared a local--jsonfor success output continue to work — yargs merges the definitions).packages/cli/cli-v2/src/context/withContext.ts: threadsargs.jsonthrough tohandleError, passes the log-file absolute path into the envelope, and suppresses the dim "Logs written to:" hint in JSON mode so the envelope is the only thing on stderr.packages/cli/cli-v2/src/commands/_internal/yargsFailHandler.ts: yargs.failruns before parsing finishes, so it inspectsprocess.argvfor--json/--no-json/--json=trueand routes through the same renderer. Help block is suppressed in JSON mode.packages/cli/cli/changes/unreleased/cli-v2-json-error-envelope.yml(feat).Testing
renderError --json modecases coveringTaskAbortSignal,CliError,ValidationError,SourcedValidationError, plainError, non-Errorthrowables,logFile,debug=true,debug=false, and ANSI-free output. All 22renderError.test.tstests pass; the full cli-v2 suite (725 tests) is green.pnpm format,pnpm lint:biome,pnpm check,pnpm turbo run compile --filter @fern-api/cli-v2all clean.Link to Devin session: https://app.devin.ai/sessions/c00fe336eaa44387a47db9083451e93c
Requested by: @iamnamananand996