Dashboard › cli › Distillation
b4e7dfdf-57b6-4654-ab2c-bd968e9d15bd["lore_tm_v1_qZvFkl-80GvRLapYI81pSgOfiPdpMioKSy3fqBEwklY","lore_tm_v1_TW-bSRVohnQirHFs5Bf_192es8QvjWYdayUZBu9TiUg","lore_tm_v1_Nolo1LqDHhsuyQX3dQqf3mvFKOdnHBmT5mtfZpVBJrs","lore_tm_v1_qtnr_DLo5YSMXR7ACyeIM2WS-ro1byar_guPtL7qcRk"]
renderJsonHelp() in packages/cli/src/lib/help.ts is wired to Stricli’s documentation.renderHelp hook; without --json it returns undefined so Stricli retains built-in text help for sentry --help and sentry <cmd> --help.--json never calls the human formatter formatHelpHuman(), ensuring structured help never triggers printCustomHelp()’s sixel probe or terminal I/O.renderJsonHelp() builds the command path from prefix.slice(1) plus extraPath, calls introspectAllCommands() for an empty path or introspectCommand(commandPath) otherwise, optionally applies filterFields(data, fields), and returns ${formatJson(final)}\n.unprocessedInputs, so an invocation such as sentry issue nope --help --json returns a structured { error } for the unknown command rather than silently rendering the parent group.isVersionRequest() in packages/cli/src/lib/help.ts returns true for a bare --version before a -- escape and ignores tokens after --; -v is intentionally excluded because GLOBAL_FLAGS maps it to --verbose.UnknownCommand before consuming --version, including sentry cli nope --version.isRecoverableUnknownCommand() recognizes exactly three recovery shapes: 1. isVersionRequest(argv); 2. rewriteHelpJsonToHelpCommand(argv) !== undefined; 3. at least two arguments with trailing token help. Recoverable invocations suppress unknown_command telemetry.rewriteHelpJsonToHelpCommand() requires both --help or -h and --json before a -- escape; it rewrites to ["help", "--json", ...extraPath] and appends ["--fields", fields.join(",")] when parsed fields are non-empty.sentry cli nope --help --json by redispatching through the help command, preserving structured { error } JSON behavior for unknown commands.parseHelpJsonFlags() scans only tokens before --, detects --json, supports spaced --fields a,b and inline --fields=a,b, parses fields with parseFieldsList, and collects leftover non-flag tokens into extraPath.--org, --project, and --log-level, preventing values such as acme from becoming command-path segments; boolean and other ---prefixed tokens are ignored.VALUE_FLAG_TOKENS is derived from GLOBAL_FLAGS, selecting flags with kind === "value" except fields, and includes both --${flag.name} and any -${flag.short} alias. isValueFlagToken() also recognizes inline forms by stripping the =<value> suffix.consumeValueFlag() leaves the index unchanged for inline values or when the following token starts with -; otherwise it consumes one following spaced value when present.formatSuggestionList() uses Oxford-comma grammar: one item "issue", two items "issue or trace", and three items "issue, trace, or auth".packages/cli/src/lib/help.ts dispatches full trees to printCustomHelp().trimEnd(), route groups to formatGroupHuman(), commands to formatCommandHuman(), and errors to Error: ${data.error} with optional Did you mean: ${formatSuggestionList(suggestions)}?.formatFlagHuman() renders aliases as -${alias}, --${flag.name}, adds <value> for non-variadic parsed/enum flags or <value>... for variadic flags, includes brief, and includes (default: ${JSON.stringify(flag.default)}) only for defined non-boolean defaults.formatCommandHuman() renders the command signature and brief, excludes hidden flags, and when jsonFields exist adds JSON fields (use --json --fields to select): with each field’s name, type, optional marker, and description.formatGroupHuman() renders sentry ${group.name}, the group brief, and its commands; empty groups show (no commands), while populated groups strip the sentry <group> prefix—including nested names such as widget add—and align command briefs using the longest subcommand name.packages/cli/src/lib/formatters/conversation.ts; truncate() defaults to 60 characters and replaces overflow with a single …, while formatTimestamp() renders epoch 0 as — and otherwise uses local toLocaleString().WIDE_TABLE_MIN_TERM_WIDTH = 100, using process.stdout.columns || 80. Wide output columns are ordered ID, Title, Started, Tokens, Tools, Errs, User, First Input; narrow output retains ID, Title, Started, Tokens, First Input.40 characters, first input to the default 60, prefers user email over username, right-aligns Tokens/Tools/Errs, preserves Title at both widths, and calls formatTable(items, selectConversationColumns(), { truncate: true }).getOperationType() prefers explicit gen_ai.operation.type; otherwise gen_ai.execute_tool maps to tool, gen_ai.invoke_agent and gen_ai.create_agent map to agent, gen_ai.handoff maps to handoff, other gen_ai.* span names map to ai_client, and non-gen_ai.* spans yield undefined.packages/cli/src/lib/formatters/conversation.ts silently falls back to the original string when JSON.parse() fails; stringifyContent() extracts string, text, content, or message values, joins array parts with newlines, returns null for null/unusable arrays, and otherwise uses JSON.stringify(value).gen_ai.input.messages before gen_ai.request.messages, preserves [Filtered], prefers the last message with role user, and otherwise uses the final parsed message. Assistant extraction similarly prefers gen_ai.output.messages, then the last assistant message or final parsed message, and falls back to gen_ai.response.text then gen_ai.response.object.extractTurns() sorts spans by precise.start_ts, creates one turn per ai_client span, and associates each tool span whose start is at or after the current AI span and before the next AI span. Turn numbers are one-based.gen_ai.tool.name ?? "unknown", span_id, start timestamp, rounded millisecond duration from precise.finish_ts - precise.start_ts, and span.status; turns also preserve span/trace IDs, timestamps, rounded duration, extracted content, model preference gen_ai.response.model ?? gen_ai.request.model, agent name, numeric total tokens, and status.1000ms as ${ms}ms; longer durations use seconds with no decimal for exact whole seconds and one decimal otherwise. Invalid, non-finite, or zero epochs render as —; valid epochs use ISO format.**user** or **assistant**, truncate content to 600 characters, split by newline, and apply escapeMarkdownInline() to each line.### Turn ${turn.turn} — ${formatEpoch(turn.started)}; muted metadata is ordered model, agent name, positive token count, duration and joined with |. Tool entries use - ${safeCodeSpan(tc.name)} — ${formatDuration(tc.durationMs)}, adding status only when it exists and is not ok.TranscriptResult contains conversationId, org, nullable title, turns, totalTokens, spanCount, sorted unique projects, startTimestamp, endTimestamp, and optional truncated.No spans found for conversation ${id} in the last 30 days., adding the escaped title in parentheses when present.# Agent Conversation: ${conversationId} and places an optional Title in the metadata table, followed by Org, Projects, Started, Ended, Turns, Spans, and Tokens. A truncated result appends yellow text ⚠Transcript truncated — the conversation exceeds the pagination limit..buildTranscriptResult() sums tokens only from extracted ai_client turns to avoid double-counting parent invoke_agent spans, sets spanCount = spans.length, sorts unique projects, computes minimum start and maximum finish timestamps, and uses 0 for both timestamps when no spans exist.