Dashboard › cli › Session 0mZOjHq2tDro
0mZOjHq2tDro6Pli7Read-only exploration in /home/byk/Code/getsentry/cli-pr-1558. Do not modify anything. Inventory every kind: "array" positional under packages/cli/src/commands. For each route, report: file:line, placeholder, optional, minimum, maximum if declared, whether its command function accepts zero positional values and what zero means, and the correct public syntax (required <name...> or optional [<name...>]). Pay special attention to schema, event send, help, project create, issue merge, monitor run, local run, and pass-through commands. Base conclusions on actual code and tests, not assumptions. Also identify any arrays semantically optional but missing optional: true, or semantically required but marked optional. Return a concise table/grouped list and recommended exact source changes. Do not run generators or edit files.
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/AGENTS.md /home/byk/Code/getsentry/cli-pr-1558/AGENTS.md
Found 33 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts: Line 484: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/logs.ts: Line 130: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts: Line 512: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts: Line 730: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts: Line 567: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/find.ts: Line 131: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/local/run.ts: Line 366: kind: "array", /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/view.ts: Line 384: kind: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/AGENTS.md</path> <type>file</type> <content> 1: # Jared (Outpost agent) 2: 3: Autonomous GitHub coding agent. Work in `/workspace/repo`. 4: 5: ## Model tiers 6: 7: The primary model is chosen per event (see `src/agents/models.ts`): heavy for 8: code-producing situations, cheaper for lightweight ones. 9: 10: | Role | Subagent | Model | 11: | --- | --- | --- | 12: | Triage / plan / review (heavy) | (primary Jared) | Claude Opus 4.8 | 13: | Triage / plan / review (light) | (primary Jared) | xAI Grok 4.3 | 14: | Explore | `explore` | OpenAI gpt-5-mini | 15: | Implement | `implement` | Moonshot kimi-k2.7-code | 16: | Ship (commit/push/PR) | `ship` | xAI Grok (`grok-build-0.1`) | 17: 18: Pipeline: triage → explore → plan → implement → review → ship. 19: (`worker` is a deprecated alias of `implement`.) 20: 21: Operators also talk to Jared directly from the Outpost dashboard. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/AGENTS.md</path> <type>file</type> <content> 1: # AGENTS.md 2: 3: Guidelines for AI agents working in this codebase. 4: 5: ## Project Overview 6: 7: **Sentry CLI** is a command-line interface for [Sentry](https://sentry.io), built with Node.js, [pnpm](https://pnpm.io), and [Stricli](https://bloomberg.github.io/stricli/). It lives in `packages/cli` of a pnpm workspace; the docs site lives in `apps/cli-docs`. 8: 9: ### Goals 10: 11: - **Zero-config experience** - Auto-detect project context from DSNs in source code and env files 12: - **AI-powered debugging** - Integrate Seer AI for root cause analysis and fix plans 13: - **Developer-friendly** - Follow `gh` CLI conventions for intuitive UX 14: - **Agent-friendly** - JSON output and predictable behavior for AI coding agents 15: - **Fast** - Native binaries via Node SEA (fossilize), SQLite caching for API responses 16: 17: ### Key Features 18: 19: - **DSN Auto-Detection** - ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/view.ts</path>
<type>file</type>
<content>
430: /**
431: * Fetch per-span details when --full or --json is active.
432: *
433: * Extracted from func() to keep cognitive complexity under the Biome
434: * limit of 15. Logs a warning for large traces and reports progress
435: * on stderr for traces with more than {@link PROGRESS_THRESHOLD} spans.
436: */
437: function fetchTraceSpanDetails(
438: spans: TraceSpan[],
439: totalCount: number,
440: options: {
441: org: string;
442: fallbackProject: string;
443: traceId: string;
444: }
445: ): Promise<Map<string, TraceItemDetail>> {
446: const log = logger.withTag("trace.view");
447: const flat = flattenSpanTree(spans);
448:
449: if (totalCount > LARGE_TRACE_WARN_THRESHOLD) {
450: log.warn(
451: `Trace has ${totalCount} spans \u2014 this may take a moment. ` +
452: "Use 'sentry span view' for specific spans."
453: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/trace/logs.ts</path>
<type>file</type>
<content>
90: const USAGE_HINT = "sentry trace logs [<org>/[<project>/]]<trace-id>";
91:
92: /**
93: * Parse --limit flag, delegating range validation to shared utility.
94: */
95: function parseLimit(value: string): number {
96: return validateLimit(value, 1, LIST_MAX_LIMIT);
97: }
98:
99: export const logsCommand = buildCommand({
100: docs: {
101: brief: "View logs associated with a trace",
102: fullDescription:
103: "View logs associated with a specific distributed trace.\n\n" +
104: "Target specification:\n" +
105: " sentry trace logs <trace-id> # auto-detect org\n" +
106: " sentry trace logs <org>/<trace-id> # explicit org\n" +
107: " sentry trace logs <org>/<project>/<trace-id> # filter to project\n\n" +
108: "When a project is specified, only logs from that project are shown.\n" ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts</path>
<type>file</type>
<content>
470: const parts: string[] = [];
471: for (let i = 0; i < data.logs.length; i++) {
472: if (parts.length > 0) {
473: parts.push("\n---\n");
474: }
475: parts.push(
476: formatLogDetails(
477: // biome-ignore lint/style/noNonNullAssertion: index is bounded by data.logs.length
478: data.logs[i]!,
479: data.orgSlug,
480: data.details?.[i]?.attributes,
481: data.extraFields
482: )
483: );
484: }
485: return parts.join("\n");
486: }
487:
488: export const viewCommand = buildCommand({
489: docs: {
490: brief: "View details of one or more log entries",
491: fullDescription:
492: "View detailed information about Sentry log entries by their IDs.\n\n" +
493: "Target specification:\n" +
494: " sentry log view <log-id> # auto-detect from DSN or ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts</path>
<type>file</type>
<content>
680: fields && fields.length > 0
681: ? logList.logs.map((log) => filterFields(log, fields))
682: : logList.logs;
683: return { data: items, hasMore: logList.hasMore };
684: }
685: // Single item (follow mode): return bare object for JSONL
686: return fields && fields.length > 0 ? filterFields(data, fields) : data;
687: }
688:
689: /** Validate flag combinations that are invalid regardless of mode. */
690: function validateFollowFlags(flags: ListFlags): void {
691: if (flags.follow && flags.sort === "oldest") {
692: throw new ValidationError(
693: '--sort "oldest" cannot be used with --follow. Follow mode streams new logs as they arrive.',
694: "sort"
695: );
696: }
697: }
698:
699: export const listCommand = buildListCommand(
700: "log",
701: {
702: docs: {
703: brief: "List logs from a ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts</path>
<type>file</type>
<content>
515:
516: return {
517: hint: `Uploaded ${results.length} debug file(s) to ${params.org}/${params.project}`,
518: };
519: }
520:
521: export const uploadCommand = buildCommand({
522: // Auth is not required for --no-upload (dry-run). The upload path calls
523: // resolveOrgAndProject which triggers auth resolution.
524: auth: false,
525: docs: {
526: brief: "Upload debug information files to Sentry",
527: fullDescription:
528: "Scan files and directories for native debug information files and " +
529: "upload them to Sentry using the chunk-upload protocol. Supports " +
530: "Mach-O/dSYM, ELF, PE/PDB, Portable PDB, WebAssembly, Breakpad, and " +
531: "source bundles. Directories are scanned recursively.\n\n" +
532: "Org/project are auto-detected from DSN, env vars, or config defaults.\n\n" +
533: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/find.ts</path>
<type>file</type>
<content>
90: cwd: string
91: ): Promise<string[]> {
92: const paths: string[] = [];
93: // dSYMs live in Xcode DerivedData; only search it when dSYMs are wanted.
94: if (!flags["no-well-known"] && types.includes("dsym")) {
95: const derived = join(homedir(), DERIVED_DATA);
96: const info = await stat(derived).catch(() => null);
97: if (info?.isDirectory()) {
98: paths.push(derived);
99: }
100: }
101: if (!flags["no-cwd"]) {
102: paths.push(cwd);
103: }
104: if (flags.path) {
105: paths.push(...flags.path);
106: }
107: return paths;
108: }
109:
110: export const findCommand = buildCommand({
111: docs: {
112: brief: "Locate debug files for given debug identifiers",
113: fullDescription:
114: "Locate debug-information files for one or more debug identifiers.\n\n" +
115: "Searches Xcode's DerivedData ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/local/run.ts</path>
<type>file</type>
<content>
300: " - go.mod (Go)",
301: " - docker-compose.yml / compose.yml (Docker Compose)",
302: ].join("\n");
303:
304: /** Build the env vars for the child process. */
305: function buildChildEnv(
306: spotlightUrl: string,
307: commandSource: string,
308: cwd: string
309: ): Record<string, string | undefined> {
310: const clientSpotlightVars = Object.fromEntries(
311: CLIENT_SPOTLIGHT_PREFIXES.map((prefix) => [
312: `${prefix}SENTRY_SPOTLIGHT`,
313: spotlightUrl,
314: ])
315: );
316: let env: Record<string, string | undefined> = {
317: ...process.env,
318: ...clientSpotlightVars,
319: SENTRY_SPOTLIGHT: spotlightUrl,
320: SENTRY_TRACES_SAMPLE_RATE: process.env.SENTRY_TRACES_SAMPLE_RATE ?? "1",
321: SENTRY_RELEASE: process.env.SENTRY_RELEASE ?? ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/view.ts</path>
<type>file</type>
<content>
340: [result.span],
341: data.spansDepth
342: );
343: if (treeLines.length > 0) {
344: parts.push(`${treeLines.join("\n")}\n`);
345: }
346: }
347: }
348: return parts.join("");
349: }
350:
351: /**
352: * Transform span view data for JSON output.
353: * Applies `--fields` filtering per element.
354: */
355: function jsonTransformSpanView(data: SpanViewData, fields?: string[]): unknown {
356: const mapped = buildJsonResults(data.results, data.traceId, data.details);
357: if (fields && fields.length > 0) {
358: return mapped.map((item) => filterFields(item, fields));
359: }
360: return mapped;
361: }
362:
363: export const viewCommand = buildCommand({
364: docs: {
365: brief: "View details of specific spans",
366: fullDescription:
367: "View detailed information about one or more spans ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/list.ts</path>
<type>file</type>
<content>
525: hasMore,
526: hasPrev,
527: nextCursor,
528: org,
529: project,
530: extraAttributes: extraApiFields,
531: },
532: hint,
533: };
534: }
535:
536: // ---------------------------------------------------------------------------
537: // Command definition
538: // ---------------------------------------------------------------------------
539:
540: export const listCommand = buildListCommand("span", {
541: docs: {
542: brief: "List spans in a project or trace",
543: fullDescription:
544: "List spans from a Sentry project, or within a specific trace.\n\n" +
545: "Project mode (no trace ID):\n" +
546: " sentry span list # auto-detect from DSN or config\n" +
547: " sentry span list <org>/<project> # explicit org and project\n" +
548: " sentry span list ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/issue/merge.ts</path>
<type>file</type>
<content>
220: try {
221: const { issue: resolvedIssue } = await resolveIssue({
222: issueArg: normalized,
223: cwd,
224: command: COMMAND,
225: });
226: resolvedId = resolvedIssue.id;
227: } catch (error) {
228: if (
229: error instanceof ResolutionError ||
230: (error instanceof ApiError && error.status === 404)
231: ) {
232: // Clean not-found — fall through to the "not among provided" error.
233: } else {
234: throw error;
235: }
236: }
237:
238: if (resolvedId) {
239: const match = issues.find((i) => i.id === resolvedId);
240: if (match) {
241: return [match, ...issues.filter((i) => i !== match)];
242: }
243: }
244:
245: throw new ValidationError(
246: `--into '${into}' did not match any of the provided issues.\n\n` +
247: `Provided: ${issues.map((i) => ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/send-envelope.ts</path>
<type>file</type>
<content>
1: /**
2: * `sentry send-envelope` — Deprecated. Suggests `sentry event send --raw`.
3: *
4: * Kept as a hidden backward-compat alias that prints a deprecation notice
5: * and forwards to `sentry event send --raw`.
6: */
7:
8: import type { SentryContext } from "../context.js";
9: import { buildCommand } from "../lib/command.js";
10: import { CliError, EXIT } from "../lib/errors.js";
11:
12: export const sendEnvelopeCommand = buildCommand({
13: docs: {
14: brief: "Send a Sentry envelope file (deprecated)",
15: fullDescription:
16: "This command has been replaced by `sentry event send --raw <file>`.\n\n" +
17: "Use `sentry event send --raw ./captured.envelope` instead.",
18: },
19: auth: false,
20: skipRcUrlCheck: true,
21: output: {
22: human: () => "",
23: },
24: parameters: {
25: positional: {
26: kind: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/help.ts</path>
<type>file</type>
<content>
1: /**
2: * Help Command
3: *
4: * Provides help information for the CLI.
5: * - `sentry help` or `sentry` (no args): Shows branded help with banner
6: * - `sentry help <command>`: Shows detailed help for that command
7: * - `sentry help --json`: Emits full command tree as structured JSON
8: * - `sentry help --json <command>`: Emits specific command/group metadata as JSON
9: */
10:
11: import type { SentryContext } from "../context.js";
12: import { buildCommand } from "../lib/command.js";
13: import { OutputError } from "../lib/errors.js";
14: import { CommandOutput } from "../lib/formatters/output.js";
15: import {
16: formatHelpHuman,
17: introspectAllCommands,
18: introspectCommand,
19: } from "../lib/help.js";
20:
21: export const helpCommand = buildCommand({
22: auth: false,
23: docs: {
24: brief: "Display help for a command",
25: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/edit.ts</path>
<type>file</type>
<content>
170:
171: const raw: Record<string, unknown> = {
172: title: flags["new-title"] ?? existing.title,
173: displayType: flags.display ?? existing.displayType,
174: queries: mergedQueries ?? existing.queries,
175: layout: mergeLayout(flags, existing),
176: };
177: // Only set widgetType if explicitly provided via --dataset or already on the widget.
178: // Avoids parseWidgetInput defaulting to "spans" for widgets without a widgetType.
179: if (flags.dataset) {
180: raw.widgetType = flags.dataset;
181: } else if (existing.widgetType) {
182: raw.widgetType = existing.widgetType;
183: }
184: if (limit !== undefined && limit !== null) {
185: raw.limit = limit;
186: }
187:
188: return prepareWidgetQueries(parseWidgetInput(raw));
189: }
190:
191: export const editCommand = buildCommand({
192: docs: {
193: brief: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/delete.ts</path>
<type>file</type>
<content>
45: dashboard: DashboardDetail;
46: widgetTitle: string;
47: url: string;
48: dryRun?: boolean;
49: };
50:
51: export const deleteCommand = buildDeleteCommand(
52: {
53: docs: {
54: brief: "Delete a widget from a dashboard",
55: fullDescription:
56: "Remove a widget from an existing Sentry dashboard.\n\n" +
57: "The dashboard can be specified by numeric ID or title.\n" +
58: "Identify the widget by --index (0-based) or --title.\n\n" +
59: "Examples:\n" +
60: " sentry dashboard widget delete 12345 --index 0\n" +
61: " sentry dashboard widget delete 'My Dashboard' --title 'Error Rate'\n" +
62: " sentry dashboard widget delete 12345 --index 0 --dry-run",
63: },
64: output: {
65: human: formatWidgetDeleted,
66: jsonTransform: (result: DeleteResult) => ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/add.ts</path>
<type>file</type>
<content>
70: "positional"
71: );
72: }
73:
74: const title = args.at(-1) as string;
75: const dashboardArgs = args.slice(0, -1);
76: return { dashboardArgs, title };
77: }
78:
79: export const addCommand = buildCommand({
80: docs: {
81: brief: "Add a widget to a dashboard",
82: fullDescription:
83: "Add a widget to an existing Sentry dashboard.\n\n" +
84: "The dashboard can be specified by numeric ID or title.\n\n" +
85: "Examples:\n" +
86: " sentry dashboard widget add 'My Dashboard' \"Error Count\" \\\n" +
87: " --display big_number --query count\n\n" +
88: " sentry dashboard widget add 'My Dashboard' \"Errors by Browser\" \\\n" +
89: " --display line --query count --group-by browser.name\n\n" +
90: " sentry dashboard widget add 'My Dashboard' \"Top Endpoints\" \\\n" +
91: " ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts</path>
<type>file</type>
<content>
1040: )
1041: )
1042: );
1043:
1044: const events: SentryEvent[] = [];
1045: for (let i = 0; i < results.length; i++) {
1046: const result = results[i];
1047: if (result?.status === "fulfilled") {
1048: events.push(result.value);
1049: } else if (result?.status === "rejected") {
1050: log.warn(`Failed to fetch event ${eventIds[i]}: ${result.reason}`);
1051: }
1052: }
1053:
1054: if (events.length === 0) {
1055: const firstResult = results[0];
1056: if (firstResult?.status === "rejected") {
1057: throw firstResult.reason;
1058: }
1059: }
1060:
1061: return events;
1062: }
1063:
1064: export const viewCommand = buildCommand({
1065: docs: {
1066: brief: "View details of one or more events",
1067: fullDescription:
1068: "View detailed information about Sentry events by their IDs.\n\n" ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/send.ts</path> <type>file</type> <content> 95: Send a Sentry event to the ingest pipeline using DSN-based authentication. 96: 97: No login required — provide a DSN via --dsn or the SENTRY_DSN environment variable. 98: 99: ## Building an event from flags 100: 101: \`\`\` 102: sentry event send -m "Something went wrong" -l error --tag env:prod 103: \`\`\` 104: 105: ## Sending from a JSON file 106: 107: The JSON file must be a valid serialized Sentry Event object: 108: 109: \`\`\` 110: sentry event send ./event.json 111: \`\`\` 112: 113: Use --raw to skip JSON parsing and send the file bytes directly to the ingest endpoint. 114: This also supports sending pre-built Sentry envelope files. 115: 116: When file arguments are provided, flags like -m/--message are ignored — the event is 117: built entirely from the file contents. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/view.ts</path>
<type>file</type>
<content>
145: }
146:
147: /**
148: * Resolve the effective time range for a dashboard view.
149: *
150: * Priority: explicit --period flag > dashboard's saved period > 24h default.
151: * Dashboard period is a raw string from the API that needs parsing.
152: */
153: function resolveViewTimeRange(
154: flagPeriod: TimeRange | undefined,
155: dashboardPeriod: string | null | undefined
156: ): TimeRange {
157: if (flagPeriod) {
158: return flagPeriod;
159: }
160: return dashboardPeriod ? parsePeriod(dashboardPeriod) : TIME_RANGE_24H;
161: }
162:
163: export const viewCommand = buildCommand({
164: docs: {
165: brief: "View a dashboard",
166: fullDescription:
167: "View a Sentry dashboard with rendered widget data.\n\n" +
168: "Fetches actual data for each widget and displays sparkline charts,\n" +
169: "tables, and big numbers in ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/revisions.ts</path>
<type>file</type>
<content>
95: function jsonTransformRevisions(
96: result: RevisionsResult,
97: fields?: string[]
98: ): unknown {
99: const items =
100: fields && fields.length > 0
101: ? result.revisions.map((r) => filterFields(r, fields))
102: : result.revisions;
103:
104: const envelope: Record<string, unknown> = {
105: data: items,
106: hasMore: result.hasMore,
107: hasPrev: !!result.hasPrev,
108: };
109: if (result.nextCursor) {
110: envelope.nextCursor = result.nextCursor;
111: }
112: return envelope;
113: }
114:
115: export const revisionsCommand = buildCommand({
116: docs: {
117: brief: "List dashboard revisions",
118: fullDescription:
119: "List revision history for a Sentry dashboard.\n\n" +
120: "Shows saved revisions with their IDs, titles, authors, and timestamps.\n" +
121: "Use `sentry ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/restore.ts</path>
<type>file</type>
<content>
35: };
36:
37: function formatRestoreHuman(result: RestoreResult): string {
38: const d = result.dashboard;
39: const url = buildDashboardUrl(result.orgSlug, d.id);
40: const widgetCount = d.widgets?.length ?? 0;
41: const created = formatRelativeTime(d.dateCreated);
42:
43: return (
44: `Restored dashboard **${escapeMarkdownCell(d.title)}** to revision ${result.revisionId}.\n\n` +
45: "| Field | Value |\n" +
46: "|-------|-------|\n" +
47: `| ID | ${d.id} |\n` +
48: `| Title | ${escapeMarkdownCell(d.title)} |\n` +
49: `| Widgets | ${widgetCount} |\n` +
50: `| Created | ${created} |\n` +
51: `| URL | ${colorTag("muted", url)} |`
52: );
53: }
54:
55: export const restoreCommand = buildCommand({
56: docs: {
57: brief: "Restore a dashboard revision",
58: fullDescription:
59: "Restore a Sentry dashboard ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/list.ts</path>
<type>file</type>
<content>
345: ): string | undefined {
346: const filterArg = result.titleFilter ? ` '${result.titleFilter}'` : "";
347: const navRaw = paginationHint({
348: hasPrev: !!result.hasPrev,
349: hasMore: !!result.hasMore,
350: prevHint: `sentry dashboard list ${orgSlug}/${filterArg} -c prev`,
351: nextHint: `sentry dashboard list ${orgSlug}/${filterArg} -c next`,
352: });
353: const nav = navRaw ? ` ${navRaw}` : "";
354: const url = buildDashboardsListUrl(orgSlug);
355:
356: if (result.dashboards.length === 0) {
357: // Empty results — show nav hint if prev/next exist, otherwise nothing
358: return nav ? `No dashboards found.${nav}` : undefined;
359: }
360:
361: return `Showing ${result.dashboards.length} dashboard(s).${nav}\nDashboards: ${url}`;
362: }
363:
364: // Command
365:
366: export const listCommand = ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/docs/query.ts</path>
<type>file</type>
<content>
1: import type { SentryContext } from "../../context.js";
2: import { buildCommand } from "../../lib/command.js";
3: import { detectDocsContext } from "../../lib/docs-context.js";
4: import { queryDocs } from "../../lib/docs-service.js";
5: import { ValidationError } from "../../lib/errors.js";
6: import { CommandOutput } from "../../lib/formatters/output.js";
7: import { withProgress } from "../../lib/polling.js";
8:
9: type QueryFlags = { readonly fields?: string[]; readonly json: boolean };
10: type QueryOutput = {
11: answer: string;
12: detectedContext: Awaited<ReturnType<typeof detectDocsContext>>;
13: sources: string[];
14: };
15:
16: /** Friendly wait messages for a docs-MCP request without measurable stages. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/docs/list.ts</path>
<type>file</type>
<content>
1: import type { SentryContext } from "../../context.js";
2: import { validateLimit } from "../../lib/arg-parsing.js";
3: import { buildCommand } from "../../lib/command.js";
4: import { type DocsListResponse, listDocs } from "../../lib/docs-service.js";
5: import { ValidationError } from "../../lib/errors.js";
6: import { muted } from "../../lib/formatters/colors.js";
7: import { CommandOutput } from "../../lib/formatters/output.js";
8: import { formatTable } from "../../lib/formatters/table.js";
9:
10: type ListFlags = {
11: readonly fields?: string[];
12: readonly json: boolean;
13: readonly limit: number;
14: };
15:
16: function parseLimit(value: string): number {
17: return validateLimit(value, 1, 20);
18: }
19:
20: function formatListHuman(data: DocsListResponse): string {
21: if (data.results.length === 0) {
22: return muted("No documentation ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/create.ts</path>
<type>file</type>
<content>
115: case "auto-detect": {
116: const result = await resolveAllTargets({ cwd });
117: if (result.targets.length === 0) {
118: const resolved = await resolveOrg({ cwd });
119: if (!resolved) {
120: throw new ContextError(
121: "Organization",
122: "sentry dashboard create <org>/ <title>"
123: );
124: }
125: return { orgSlug: resolved.org, projectIds: [] };
126: }
127: const orgSlug = (result.targets[0] as (typeof result.targets)[0]).org;
128: const projectIds = await enrichTargetProjectIds(result.targets);
129: return { orgSlug, projectIds };
130: }
131: default: {
132: const _exhaustive: never = parsed;
133: throw new Error(
134: `Unexpected parsed type: ${(_exhaustive as { type: string }).type}`
135: );
136: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/project/create.ts</path>
<type>file</type>
<content>
580: }
581: log.debug("403 on team-based flow — falling back to org-scoped endpoint");
582: const fallback = await createProjectWithAutoTeamFallback({
583: orgSlug,
584: name,
585: platform,
586: });
587: teamSlug = fallback.teamSlug;
588: teamSource = fallback.teamSource;
589: projectDetails = fallback;
590: }
591:
592: const { project, dsn, url } = projectDetails;
593: return {
594: project,
595: orgSlug,
596: teamSlug,
597: teamSource,
598: requestedPlatform: platform,
599: dsn,
600: url,
601: slugDiverged: project.slug !== expectedSlug,
602: expectedSlug,
603: };
604: }
605:
606: export const createCommand = buildCommand({
607: docs: {
608: brief: "Create one or more projects",
609: customUsage: ["[<org>/]<name>:<platform>..."],
610: fullDescription:
611: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/proguard/upload.ts</path>
<type>file</type>
<content>
125:
126: /**
127: * Deduplicate mappings with identical content (same UUID = same content).
128: * Logs a warning for each skipped duplicate.
129: */
130: function deduplicateMappings(mappings: ProguardMapping[]): ProguardMapping[] {
131: const seen = new Map<string, string>();
132: const unique: ProguardMapping[] = [];
133: for (const m of mappings) {
134: const existing = seen.get(m.uuid);
135: if (existing) {
136: log.warn(
137: `Skipping '${m.path}': identical content as '${existing}' (UUID ${m.uuid})`
138: );
139: continue;
140: }
141: seen.set(m.uuid, m.path);
142: unique.push(m);
143: }
144: return unique;
145: }
146:
147: // ── Command ─────────────────────────────────────────────────────────
148:
149: export const uploadCommand = buildCommand({
150: // Auth is not required for --no-upload ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/cli/feedback.ts</path>
<type>file</type>
<content>
1: /**
2: * Feedback Command
3: *
4: * Allows users to submit feedback about the CLI.
5: * All arguments after 'feedback' are joined into a single message.
6: *
7: * @example sentry cli feedback i love this tool
8: * @example sentry cli feedback the issue view is confusing
9: */
10:
11: import { isatty } from "node:tty";
12: // biome-ignore lint/performance/noNamespaceImport: Sentry SDK recommends namespace import
13: import * as Sentry from "@sentry/node-core/light";
14: import type { SentryContext } from "../../context.js";
15: import { buildCommand } from "../../lib/command.js";
16: import { ConfigError, ValidationError } from "../../lib/errors.js";
17: import { formatFeedbackResult } from "../../lib/formatters/human.js";
18: import { CommandOutput } from "../../lib/formatters/output.js";
19: import { logger } from "../../lib/logger.js";
20:
21: /** ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/cli/defaults.ts</path>
<type>file</type>
<content>
260: };
261:
262: // ---------------------------------------------------------------------------
263: // Command
264: // ---------------------------------------------------------------------------
265:
266: const log = logger.withTag("defaults");
267:
268: export const defaultsCommand = buildCommand({
269: auth: false,
270: docs: {
271: brief: "View and manage default settings",
272: fullDescription:
273: "View and manage persistent CLI default settings.\n\n" +
274: "With no arguments, shows all current defaults. Pass a key and value\n" +
275: "to set a default, or use `--clear` to remove defaults.\n\n" +
276: "## Examples\n\n" +
277: "```\n" +
278: "sentry cli defaults # Show all defaults\n" +
279: "sentry cli defaults org my-org # Set default organization\n" +
280: "sentry cli ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/build/upload.ts</path>
<type>file</type>
<content>
135: if (format === "ipa") {
136: await normalizeIpa(path, outPath, plugin);
137: } else if (format === "apk" || format === "aab") {
138: await normalizeBuildFile(path, outPath, plugin);
139: } else {
140: throw new ValidationError(
141: `Unsupported build format (expected APK, AAB, IPA, or XCArchive): ${path}`,
142: "path"
143: );
144: }
145: }
146: return await uploadBuild({
147: org,
148: project,
149: contentPath: outPath,
150: metadata,
151: });
152: } finally {
153: await rm(workDir, { recursive: true, force: true });
154: }
155: }
156:
157: export const uploadCommand = buildCommand({
158: docs: {
159: brief: "Upload builds to a project",
160: fullDescription:
161: "Upload mobile builds to Sentry for preprod size analysis. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/monitor/run.ts</path>
<type>file</type>
<content>
125: timer = setTimeout(
126: reject,
127: CHECKIN_SEND_TIMEOUT_MS,
128: new Error("Check-in send timed out")
129: );
130: });
131: try {
132: await Promise.race([send, timeout]);
133: } finally {
134: clearTimeout(timer);
135: }
136: } catch (err) {
137: log.warn(
138: `Failed to send ${phase} check-in: ${err instanceof Error ? err.message : String(err)}`
139: );
140: log.debug("Continuing despite check-in failure...");
141: }
142: }
143:
144: export const runCommand = buildCommand({
145: docs: {
146: brief: "Wrap a command with cron monitor check-ins",
147: fullDescription: `\
148: Run a command and report its execution to a Sentry cron monitor. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/replay/view.ts</path>
<type>file</type>
<content>
315: > {
316: const [activity, relatedIssues, relatedTraces] = await Promise.all([
317: fetchReplayActivity(org, replay),
318: fetchRelatedReplayIssues(org, replay),
319: fetchRelatedReplayTraces(org, replay),
320: ]);
321:
322: return { activity, relatedIssues, relatedTraces };
323: }
324:
325: export const viewCommand = buildCommand({
326: docs: {
327: brief: "View a Session Replay",
328: fullDescription:
329: "View detailed information about a Session Replay.\n\n" +
330: "Replay ID formats:\n" +
331: " <replay-id> - auto-detect org from config or DSN\n" +
332: " <org>/<replay-id> - explicit organization\n" +
333: " <org>/<project>/<id> - explicit org/project context\n" +
334: " <replay-url> - parse org and replay ID from a Sentry URL\n\n" +
335: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/react-native/xcode.ts</path>
<type>file</type>
<content>
450: parse: String,
451: brief: `Packager URL to fetch from (default: ${DEFAULT_PACKAGER_URL})`,
452: optional: true,
453: },
454: "build-script": {
455: kind: "parsed",
456: parse: String,
457: brief: "Path to the react-native-xcode.sh build script",
458: optional: true,
459: },
460: dist: {
461: kind: "parsed",
462: parse: String,
463: variadic: true,
464: brief: "Distribution(s) to publish (repeatable)",
465: optional: true,
466: },
467: wait: {
468: kind: "boolean",
469: brief: "Wait for the server to fully process the uploaded files",
470: optional: true,
471: },
472: "wait-for": {
473: kind: "parsed",
474: parse: Number,
475: brief: "Wait for processing, but at most ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/schema.ts</path>
<type>file</type>
<content>
275: if (endpoints.length === 0) {
276: throw noResourceMatchError(resource);
277: }
278: return { kind: "endpoints", endpoints };
279: }
280:
281: // ---------------------------------------------------------------------------
282: // Command definition
283: // ---------------------------------------------------------------------------
284:
285: type SchemaFlags = {
286: readonly all: boolean;
287: readonly search?: string;
288: };
289:
290: export const schemaCommand = buildCommand({
291: auth: false,
292: docs: {
293: brief: "Browse the Sentry API schema",
294: fullDescription:
295: "Browse and search the Sentry API schema. Shows available resources, " +
296: "operations, and endpoint details. Use with --json for machine-readable output.\n\n" +
297: "Examples:\n" +
298: " sentry schema List all ...
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/types/dashboard.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/types/dashboard.property.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/e2e/feedback.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/help-positional.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/trace-log-schema.property.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/send-envelope.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/schema.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/react-native/xcode.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/react-native/xcode-env.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/proguard.property.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/init/feedback.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/help.test....
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trial/start.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trial/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.property.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.func.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/logs.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/team/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/status/show.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/view.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/sourcemap/...
Found 23 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/script/generate-skill-markdown.test.ts:
Line 135: test("generated argument tables distinguish optional, required, and variadic positionals", async () => {
Line 156: "| `<issue...>` | Issue IDs to merge (2 or more required) |"
Line 158: expect(issue).not.toContain("| `[<issue...>]`");
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/introspect.test.ts:
Line 134: expect(result).toBe("<command...>");
Line 142: expect(result).toBe("<args...>");
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/bspatch.test.ts:
Line 166: expect(() => parsePatchHeader(buf)).toThrow("exceeds maximum");
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/list.test.ts:
Line 82: test("throws for value below minimum", () => {
Line 87: test("throws for value above maximum", () => ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/script/generate-skill-markdown.test.ts</path>
<type>file</type>
<content>
100: expect(
101: matchExampleToCommand(
102: "sentry auth login --token TOKEN",
103: ["sentry auth login", "sentry auth status"],
104: "sentry auth",
105: "sentry auth login"
106: )
107: ).toBe("sentry auth login");
108: });
109:
110: test("the generated project reference retains create examples", async () => {
111: const reference = await readFile(
112: "plugins/sentry-cli/skills/sentry-cli/references/project.md",
113: "utf8"
114: );
115:
116: expect(reference).toContain(
117: "### `sentry project create [<org>/]<name>:<platform>...`"
118: );
119: expect(reference).not.toContain('sentry project create "My New App":');
120: // The platform must always be attached with ":" — no space-separated form.
121: expect(reference).not.toContain(
122: ...
Found 91 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/list.test.ts:
Line 82: test("throws for value below minimum", () => {
Line 87: test("throws for value above maximum", () => {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/list.test.ts:
Line 1055: /** Follow flags with 1-second interval (minimum real-world value) */
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/introspect.property.test.ts:
Line 163: parameter.optional ? `[<${placeholder}>]` : `<${placeholder}>`
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/upload.test.ts:
Line 482: detail: "Exceeds server maximum file size",
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/telemetry/zstd-transport.test.ts:
Line 516: // node:zlib.zstdCompress is always available in our minimum Node version.
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/resolve-target.test.ts:
...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/introspect.ts</path>
<type>file</type>
<content>
50: aliases?: Record<string, string>;
51: };
52: /**
53: * JSON output schema attached by `buildCommand` when `output.schema` is set.
54: * Non-standard property — Stricli doesn't know about it, but introspection
55: * reads it to populate {@link CommandInfo.jsonFields}.
56: */
57: __jsonSchema?: import("valibot").GenericSchema;
58: /**
59: * Primary Stricli custom usage line, retained by `buildCommand` for
60: * introspection because Stricli does not expose it on the built command.
61: */
62: __primaryUsage?: string;
63: /** Canonical documentation examples retained by `buildCommand`. */
64: __examples?: readonly CommandExample[];
65: };
66:
67: /** Positional parameter definitions — either fixed-length tuple or variadic array */
68: export type PositionalParams =
69: | { kind: "tuple"; parameters: readonly PositionalParam[] }
70: ...
No files found
No files found
Found 2 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/formatters/numbers.ts: Line 21: * Two fractional digits maximum: 1234.5 → "1,234.5". /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/formatters/chart-core.ts: Line 94: * axis maximum: the largest single value for a single series, or the largest
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core</path> <type>directory</type> <entries> dist/ package.json README.md (3 entries) </entries>
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist</path> <type>directory</type> <entries> index.cjs index.d.cts index.d.ts index.js (4 entries) </entries>
Found 31 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist/index.d.ts:
Line 33: * Simple interface that mirrors NodeJS.Process but only requires the minimum API required by Stricli.
Line 976: interface TypedCommandPositionalParameters_<ARGS extends BaseArgs, CONTEXT extends CommandContext> {
Line 980: readonly positional: TypedPositionalParameters<ARGS, CONTEXT>;
Line 982: type TypedCommandPositionalParameters<ARGS extends BaseArgs, CONTEXT extends CommandContext> = [] extends ARGS ? Partial<TypedCommandPositionalParameters_<ARGS, CONTEXT>> : TypedCommandPositionalParameters_<ARGS, CONTEXT>;
Line 986: type TypedCommandParameters<FLAGS extends BaseFlags, ARGS extends BaseArgs, CONTEXT extends CommandContext> = TypedCommandFlagParameters<FLAGS, CONTEXT> & TypedCommandPositionalParameters<ARGS, CONTEXT>;
Line 995: readonly positional?: PositionalParameters;
Line 998: interface BasePositionalParameter<T, CONTEXT extends ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist/index.d.ts</path>
<type>file</type>
<content>
970: */
971: readonly aliases?: Aliases<keyof FLAGS & string>;
972: }
973: type TypedCommandFlagParameters<FLAGS extends BaseFlags, CONTEXT extends CommandContext> = [
974: keyof FLAGS
975: ] extends [never] ? Partial<TypedCommandFlagParameters_<FLAGS, CONTEXT>> : TypedCommandFlagParameters_<FLAGS, CONTEXT>;
976: interface TypedCommandPositionalParameters_<ARGS extends BaseArgs, CONTEXT extends CommandContext> {
977: /**
978: * Typed definitions for all positional parameters.
979: */
980: readonly positional: TypedPositionalParameters<ARGS, CONTEXT>;
981: }
982: type TypedCommandPositionalParameters<ARGS extends BaseArgs, CONTEXT extends CommandContext> = [] extends ARGS ? ...
Found 5 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist/index.js:
Line 809: if (typeof positional.maximum === "number" && positionalIndex >= positional.maximum) {
Line 810: throw new UnexpectedPositionalError(positional.maximum, input);
Line 821: if (typeof positional.minimum === "number" && positionalIndex < positional.minimum) {
Line 824: positional.minimum,
Line 995: if (typeof positional.maximum !== "number" || positionalIndex < positional.maximum) {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist/index.js</path>
<type>file</type>
<content>
775: }
776: }
777: if (nextFlags.every(isNiladic)) {
778: for (const nextFlag of nextFlags) {
779: if (nextFlag.namedFlag[1].kind === "boolean") {
780: storeInput(
781: flagInputs,
782: config.caseStyle,
783: nextFlag.namedFlag,
784: nextFlag.negated ? "false" : "true"
785: );
786: } else {
787: storeInput(flagInputs, config.caseStyle, nextFlag.namedFlag, "1");
788: }
789: }
790: } else if (nextFlags.length > 1) {
791: const nextFlagExpectingArg = nextFlags.find((nextFlag) => !isNiladic(nextFlag));
792: const externalFlagName = asExternal(nextFlagExpectingArg.namedFlag[0], config.caseStyle);
793: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/introspect.test.ts</path>
<type>file</type>
<content>
95: // ---------------------------------------------------------------------------
96:
97: describe("getPositionalString", () => {
98: test("returns empty string for undefined", () => {
99: expect(getPositionalString(undefined)).toBe("");
100: });
101:
102: test("returns tuple placeholders", () => {
103: const result = getPositionalString({
104: kind: "tuple",
105: parameters: [{ placeholder: "org" }, { placeholder: "project" }],
106: });
107: expect(result).toBe("<org> <project>");
108: });
109:
110: test("wraps optional tuple placeholders in brackets", () => {
111: const result = getPositionalString({
112: kind: "tuple",
113: parameters: [
114: { placeholder: "required" },
115: { placeholder: "optional", optional: true },
116: ],
117: });
118: expect(result).toBe("<required> ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/introspect.test.ts</path>
<type>file</type>
<content>
145:
146: // ---------------------------------------------------------------------------
147: // extractPositionals
148: // ---------------------------------------------------------------------------
149:
150: describe("extractPositionals", () => {
151: test("preserves optional tuple semantics", () => {
152: expect(
153: extractPositionals({
154: kind: "tuple",
155: parameters: [
156: { placeholder: "required" },
157: { placeholder: "optional", optional: true },
158: ],
159: })
160: ).toEqual([
161: {
162: placeholder: "required",
163: brief: "",
164: optional: false,
165: variadic: false,
166: },
167: {
168: placeholder: "optional",
169: brief: "",
170: optional: true,
171: variadic: false,
172: },
173: ...
ac72db51b (HEAD -> fix/agent-conversation-reference-root-cause) fix(docs): preserve public positional semantics c55566af4 fix(docs): derive command references from metadata c0b071f81 fix(docs): correct agent conversation argument syntax ec83887a1 (origin/main, origin/HEAD) fix(event): Prevent immediate retry of rate-limited org in event view fallback (#1566) e7beceb6b feat(telemetry): refresh coding agent detection (#1571)
.../src/fragments/commands/agent-conversation.md | 33 --------- .../plugins/sentry-cli/skills/sentry-cli/SKILL.md | 46 ++++++------ .../sentry-cli/references/agent-conversation.md | 13 ++-- .../skills/sentry-cli/references/alert.md | 6 +- .../sentry-cli/skills/sentry-cli/references/cli.md | 4 +- .../skills/sentry-cli/references/explore.md | 2 +- .../skills/sentry-cli/references/feedback.md | 2 +- .../skills/sentry-cli/references/init.md | 2 +- .../skills/sentry-cli/references/issue.md | 2 +- .../skills/sentry-cli/references/monitor.md | 2 +- .../sentry-cli/skills/sentry-cli/references/org.md | 2 +- .../skills/sentry-cli/references/project.md | 4 +- .../skills/sentry-cli/references/release.md | 4 +- .../skills/sentry-cli/references/replay.md | 2 +- .../skills/sentry-cli/references/repo.md | 2 +- .../skills/sentry-cli/references/team.md | 2 +- ...
diff --git a/packages/cli/script/generate-command-docs.ts b/packages/cli/script/generate-command-docs.ts
index cdc8865be..ac02d200b 100644
--- a/packages/cli/script/generate-command-docs.ts
+++ b/packages/cli/script/generate-command-docs.ts
@@ -8,11 +8,11 @@
* preventing documentation drift.
*
* Each generated page combines:
- * 1. Auto-generated reference — from CLI metadata or env registry
- * 2. Hand-written fragment — examples, guides, tips (from docs/src/fragments/)
+ * 1. Auto-generated reference and examples from CLI metadata or env registry
+ * 2. Hand-written guides and tips from docs/src/fragments/
*
* The generated output is gitignored. Fragment files are the committed
- * source of truth for custom content.
+ * source of truth for content that cannot live in command definitions.
*
* Usage:
* tsx script/generate-command-docs.ts
@@ -25,6 +25,7 @@
import { mkdirSync, rmSync } from "node:fs";
import { access, readFile, writeFile } from ...
Found 11 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/view.ts:
Line 151: export function parsePositionalArgs(args: string[]): SpanViewArgs {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/list.ts:
Line 194: export function parseSpanListArgs(
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/replay/view.ts:
Line 125: export function parsePositionalArgs(args: string[]): ParsedPositionalArgs {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts:
Line 354: export function parsePositionalArgs(args: string[]): ParsedPositionalArgs {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/add.ts:
Line 54: function parseAddPositionalArgs(args: string[]): {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/resolve.ts:
Line 159: export function parseDashboardPositionalArgs(
Line 253: export function parseDashboardListArgs(args: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/view.ts</path>
<type>file</type>
<content>
120: // For single-slash form the prefix must be a hex trace ID.
121: // For multi-slash (org/project/trace-id) always attempt the split.
122: if (!(hasMultipleSlashes || HEX_ID_RE.test(normalizedPrefix))) {
123: return null;
124: }
125:
126: let traceTarget: ReturnType<typeof parseSlashSeparatedTraceTarget>;
127: try {
128: traceTarget = parseSlashSeparatedTraceTarget(tracePrefix, USAGE_HINT);
129: } catch (_error) {
130: // We already confirmed the last segment is a span ID and the prefix
131: // looked like a trace target, so a validation failure here means the
132: // trace-target portion is bad — e.g. `org/project/<span-id>` (missing
133: // the trace ID) or `org/project/<bad-trace>/<span-id>`. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/span/list.ts</path>
<type>file</type>
<content>
165: const TRACE_USAGE_HINT = "sentry span list [<org>/<project>/]<trace-id>";
166:
167: /**
168: * Parse --limit flag, delegating range validation to shared utility.
169: */
170: function parseLimit(value: string): number {
171: return validateLimit(value, 1, LIST_MAX_LIMIT);
172: }
173:
174: /**
175: * Parse and validate sort flag value.
176: *
177: * @throws Error if value is not "date" or "duration"
178: */
179: export function parseSort(value: string): SpanSortValue {
180: if (!VALID_SORT_VALUES.includes(value as SpanSortValue)) {
181: throw new Error(
182: `Invalid sort value. Must be one of: ${VALID_SORT_VALUES.join(", ")}`
183: );
184: }
185: return value as SpanSortValue;
186: }
187:
188: /**
189: * Disambiguate span list positional arguments. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/replay/view.ts</path>
<type>file</type>
<content>
90:
91: // Handle <org>/<replay-id> shorthand — must check before parseSlashSeparatedArg
92: // because replay IDs are 32-char hex strings that look valid to the generic
93: // slash parser's ID extraction, but with only one slash the "project" segment
94: // would be wrongly treated as the ID.
95: const slashIdx = trimmed.indexOf("/");
96: if (slashIdx !== -1 && trimmed.indexOf("/", slashIdx + 1) === -1) {
97: const org = trimmed.slice(0, slashIdx);
98: const replaySegment = trimmed.slice(slashIdx + 1);
99: const normalizedReplayId =
100: replaySegment && tryNormalizeHexId(replaySegment);
101: if (!normalizedReplayId) {
102: throw new ContextError("Replay ID", USAGE_HINT, []);
103: }
104: return { replayId: normalizedReplayId, targetArg: `${org}/` };
105: }
106:
107: const { id: replayId, targetArg } = ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/event/view.ts</path>
<type>file</type>
<content>
315:
316: return null;
317: }
318:
319: /** Return type for parsePositionalArgs */
320: type ParsedPositionalArgs = {
321: eventId: string;
322: targetArg: string | undefined;
323: /** Issue ID from a Sentry issue URL — triggers latest-event fetch */
324: issueId?: string;
325: /** Issue short ID detected from positional args (e.g., "BRUNCHIE-APP-29") */
326: issueShortId?: string;
327: /** Warning message if arguments appear to be in the wrong order */
328: warning?: string;
329: /** Additional event IDs from newline-separated input or extra positional args */
330: extraEventIds?: string[];
331: };
332:
333: /**
334: * Parse positional arguments for event view. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/widget/add.ts</path>
<type>file</type>
<content>
35:
36: type AddFlags = WidgetQueryFlags &
37: WidgetLayoutFlags & {
38: readonly display: string;
39: readonly layout: string;
40: readonly json: boolean;
41: readonly fields?: string[];
42: };
43:
44: type AddResult = {
45: dashboard: DashboardDetail;
46: widget: DashboardWidget;
47: url: string;
48: };
49:
50: /**
51: * Parse positional args for widget add.
52: * Last arg is widget title, rest go to dashboard resolution.
53: */
54: function parseAddPositionalArgs(args: string[]): {
55: dashboardArgs: string[];
56: title: string;
57: } {
58: if (args.length < 2) {
59: throw new ValidationError(
60: "Widget title is required as a positional argument.\n\n" +
61: "Example:\n" +
62: ' sentry dashboard widget add <dashboard> "My Widget" --display line --query count',
63: "title"
64: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/resolve.ts</path>
<type>file</type>
<content>
145: * Parse a dashboard reference and optional target from array positional args.
146: *
147: * Handles:
148: * - `<id-or-title>` — single arg (auto-detect org)
149: * - `<target> <id-or-title>` — explicit target + dashboard ref
150: * - Full Sentry dashboard URL — extracts org + dashboard ID
151: *
152: * When two args are provided and the first is a bare slug (no `/`), it is
153: * normalized to `slug/` so `parseOrgProjectArg` treats it as an org-all
154: * target. Dashboards are org-scoped so the project component is irrelevant.
155: *
156: * @param args - Raw positional arguments
157: * @returns Dashboard reference string and optional target arg
158: */
159: export function parseDashboardPositionalArgs(
160: args: string[]
161: ): DashboardArgResult {
162: if (args.length === 0) {
163: throw new ValidationError(
164: "Dashboard ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/dashboard/create.ts</path>
<type>file</type>
<content>
1: /**
2: * sentry dashboard create
3: *
4: * Create a new dashboard in a Sentry organization.
5: */
6:
7: import type { SentryContext } from "../../context.js";
8: import { createDashboard, getProject } from "../../lib/api-client.js";
9: import {
10: type ParsedOrgProject,
11: parseOrgProjectArg,
12: } from "../../lib/arg-parsing.js";
13: import { buildCommand } from "../../lib/command.js";
14: import { ContextError, ValidationError } from "../../lib/errors.js";
15: import { formatDashboardCreated } from "../../lib/formatters/human.js";
16: import { CommandOutput } from "../../lib/formatters/output.js";
17: import {
18: fetchProjectId,
19: resolveAllTargets,
20: resolveOrg,
21: resolveProjectBySlug,
22: toNumericId,
23: } from "../../lib/resolve-target.js";
24: import { buildDashboardUrl } from "../../lib/sentry-urls.js";
25: import { ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/view.ts</path>
<type>file</type>
<content>
80: */
81: function parseSingleSlashLogArg(
82: beforeSlash: string,
83: afterSlash: string
84: ): { rawLogIds: string[]; targetArg: string | undefined } | null {
85: // "org/LOG-ID" or "project/LOG-ID" → treat beforeSlash as target, afterSlash as log ID.
86: if (afterSlash && HEX_ID_RE.test(normalizeHexId(afterSlash))) {
87: return {
88: rawLogIds: [normalizeHexId(afterSlash)],
89: targetArg: beforeSlash || undefined,
90: };
91: }
92: return null;
93: }
94:
95: /**
96: * Parse positional arguments for log view.
97: * Handles:
98: * - `<log-id>` — single log ID (auto-detect org/project)
99: * - `<target> <log-id> [<log-id>...]` — explicit target + one or more log IDs
100: * - `<org>/<project>/<log-id>` — single slash-separated arg
101: *
102: * When two or more args are provided, the first is always treated as the
103: * target ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/log/list.ts</path>
<type>file</type>
<content>
125: */
126: function parseFollow(value: string): number {
127: if (value === "") {
128: return DEFAULT_POLL_INTERVAL;
129: }
130: const num = Number.parseInt(value, 10);
131: if (Number.isNaN(num) || num < 1) {
132: throw new Error("--follow interval must be a positive integer");
133: }
134: return num;
135: }
136:
137: /**
138: * Extends the base {@link BaseLogLike} from formatters with the
139: * `timestamp_precise` field needed for follow-mode dedup tracking.
140: */
141: type LogLike = BaseLogLike & {
142: /** Nanosecond-precision timestamp used for dedup in follow mode.
143: * Optional because TraceLog may omit it when the API response doesn't include it. */
144: timestamp_precise?: number;
145: };
146:
147: /** Result from a single fetch: logs to yield + hint for the footer. ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/project/create.ts</path>
<type>file</type>
<content>
430: buildPlatformError(rawName, platform),
431: "platform"
432: );
433: }
434: return platform;
435: }
436:
437: /**
438: * Parse one required `<name>:<platform>` pair. The final colon is the
439: * separator so project names may contain earlier colons. There is no
440: * space-separated fallback — the platform must always be attached with `:`,
441: * with or without an explicit org prefix on the name.
442: */
443: function parsePairedProjectSpec(rawSpec: string): ParsedProjectSpec {
444: const separatorIndex = rawSpec.lastIndexOf(":");
445: if (separatorIndex === -1) {
446: throw new ValidationError(
447: `Project '${rawSpec}' must use <name>:<platform> syntax.`,
448: "project"
449: );
450: }
451:
452: const rawName = rawSpec.slice(0, separatorIndex);
453: const platform = parseProjectPlatform(
454: ...
Found 1 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts: Line 604: export function parseDualModeArgs(
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts</path>
<type>file</type>
<content>
570: /**
571: * Result from dual-mode argument disambiguation.
572: *
573: * Used by commands that support both project-scoped listing (no trace ID)
574: * and trace-scoped listing (trace ID provided), like `span list` and
575: * `log list`.
576: *
577: * Discriminated on `mode`:
578: * - `"project"` — no trace ID detected; `target` is the optional org/project arg
579: * - `"trace"` — a 32-char hex trace ID was found; `parsed` contains the full target
580: */
581: export type ParsedDualModeArgs =
582: | { mode: "project"; target?: string }
583: | { mode: "trace"; parsed: ParsedTraceTarget };
584:
585: /**
586: * Disambiguate positional arguments for dual-mode list commands. ...
Found 2 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts: Line 116: export function parseTraceTarget( Line 322: export async function parseTraceTargetWithRecovery(
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts</path>
<type>file</type>
<content>
100: * - `<org>/<trace-id>` → org-scoped
101: * - `<org>/<project>/<trace-id>` → explicit
102: *
103: * **Two arguments (space-separated):**
104: * - `<org>/<project> <trace-id>` → explicit
105: * - `<org> <trace-id>` → project-search (bare slug)
106: *
107: * Extra positional arguments beyond the first two are ignored with a
108: * warning, matching the established pattern across CLI commands.
109: *
110: * @param args - Positional arguments from CLI
111: * @param usageHint - Usage example for error messages
112: * @returns Parsed trace target with type discrimination
113: * @throws {ContextError} If no arguments are provided
114: * @throws {ValidationError} If the trace ID format is invalid
115: */
116: export function parseTraceTarget(
117: args: string[],
118: usageHint: string
119: ): ParsedTraceTarget {
120: if (args.length === 0) {
121: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/trace-target.ts</path>
<type>file</type>
<content>
300: : { rawTraceId: "" };
301: }
302: const second = args[1];
303: const first = args[0];
304: if (second === undefined) {
305: return null;
306: }
307: return { rawTraceId: second, targetArg: first };
308: }
309:
310: /**
311: * Parse trace-target args, falling back to {@link recoverHexId} on an
312: * invalid trace ID. Returns a {@link ParsedTraceTarget} with a validated
313: * or recovered trace ID, or throws the original {@link ValidationError}
314: * when recovery can't proceed.
315: *
316: * The recovery path runs the cheap classifications (sentinel, slug, etc.)
317: * locally regardless of context. ...
Found 68 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.test.ts:
Line 79: test("returns empty args unchanged", () => {
Line 80: const result = preProcessArgs([]);
Line 81: expect(result.correctedArgs).toEqual([]);
Line 100: findProjectsBySlugSpy.mockResolvedValue({ projects: [], orgs: [] });
Line 108: findProjectsBySlugSpy.mockResolvedValue({ projects: [], orgs: [] });
Line 132: ] as ProjectWithOrg[],
Line 133: orgs: [],
Line 156: ] as ProjectWithOrg[],
Line 157: orgs: [],
Line 188: ] as ProjectWithOrg[],
Line 189: orgs: [],
Line 210: ] as ProjectWithOrg[],
Line 211: orgs: [],
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.property.test.ts:
Line 115: test("empty args always throws ContextError", () => {
Line 116: expect(() => parseTraceTarget([], HINT)).toThrow(ContextError);
Line ...
Found 26 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/view.test.ts:
Line 77: test("throws for empty string", () => {
Line 241: test("throws ContextError for empty args", () => {
Line 242: expect(() => parsePositionalArgs([])).toThrow(ContextError);
Line 247: parsePositionalArgs([]);
Line 326: ...args: string[]
Line 330: function makeTraceSpan(spanId: string, children: unknown[] = []): unknown {
Line 352: const stdoutChunks: string[] = [];
Line 379: attributes: [],
Line 418: getDetailedTraceSpy.mockResolvedValue([]);
Line 535: expect(parsed[0].ancestors).toEqual([]);
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts:
Line 90: test("throws for empty string", () => {
Line 100: test("no args → project mode", () => {
Line 101: const result = parseSpanListArgs([]);
Line 163: ...args: string[]
Line 175: const stdoutChunks: ...
Found 62 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/view.test.ts:
Line 184: test("ignores empty lines in newline-separated IDs", () => {
Line 198: test("throws ContextError for empty args", () => {
Line 199: expect(() => parsePositionalArgs([])).toThrow(ContextError);
Line 204: parsePositionalArgs([]);
Line 235: test("throws ContextError for empty log ID after target", () => {
Line 332: findProjectsBySlugSpy.mockResolvedValue({ projects: [], orgs: [] });
Line 340: findProjectsBySlugSpy.mockResolvedValue({ projects: [], orgs: [] });
Line 365: ] as ProjectWithOrg[],
Line 366: orgs: [],
Line 379: ] as ProjectWithOrg[],
Line 380: orgs: [],
Line 406: ] as ProjectWithOrg[],
Line 407: orgs: [],
Line 430: ] as ProjectWithOrg[],
Line 431: orgs: [],
Line 452: ] as ProjectWithOrg[],
Line 453: orgs: ...
Found 71 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/event/list.func.test.ts:
Line 90: message: "TypeError: Cannot read property 'foo' of undefined",
Line 104: const sampleEvents: IssueEvent[] = [
Line 268: listIssueEventsSpy.mockResolvedValue({ data: [] });
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/event/view.test.ts:
Line 233: test("throws ContextError for empty args", () => {
Line 234: expect(() => parsePositionalArgs([])).toThrow(ContextError);
Line 239: parsePositionalArgs([]);
Line 243: expect((error as ContextError).message).toContain("Event ID");
Line 287: expect((error as ContextError).message).toContain("Issue ID");
Line 331: expect((error as ContextError).message).toContain("Event ID");
Line 348: test("handles empty string event ID in two-arg case", () => {
Line 504: findProjectsBySlugSpy.mockResolvedValue({ projects: [], orgs: [] ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/event/send.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry event send` command func().
3: */
4:
5: import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
6: import { sendCommand } from "../../../src/commands/event/send.js";
7: // biome-ignore lint/performance/noNamespaceImport: needed for spyOn
8: import * as transport from "../../../src/lib/envelope/transport.js";
9: import { ValidationError } from "../../../src/lib/errors.js";
10: import { useTestConfigDir } from "../../helpers.js";
11:
12: useTestConfigDir("send-event-");
13:
14: const SAAS_DSN = "https://abc123@o1.ingest.us.sentry.io/999";
15:
16: function makeContext() {
17: const writes: string[] = [];
18: return {
19: ctx: {
20: stdout: {
21: write: (s: string) => {
22: writes.push(s);
23: return true;
24: },
25: },
26: stderr: { write: vi.fn(() ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/help.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for the Help Command
3: *
4: * Tests `sentry help --json` output for full tree, specific groups,
5: * specific commands, and not-found cases.
6: */
7:
8: import { run } from "@stricli/core";
9: import { describe, expect, test } from "vitest";
10: import { app } from "../../src/app.js";
11: import type { SentryContext } from "../../src/context.js";
12:
13: /**
14: * Run a help command and capture stdout output.
15: */
16: async function runHelp(args: string[]): Promise<string> {
17: let output = "";
18: const mockContext: SentryContext = {
19: process,
20: env: process.env,
21: cwd: process.cwd(),
22: homeDir: "/tmp",
23: configDir: "/tmp",
24: stdout: {
25: write(data: string | Uint8Array) {
26: output +=
27: typeof data === "string" ? data : new TextDecoder().decode(data);
28: ...
Found 100 matches (more matches available)
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trial/start.test.ts:
Line 182: getProductTrialsSpy.mockResolvedValue([]);
Line 194: getProductTrialsSpy.mockResolvedValue([]);
Line 253: productTrials: [],
Line 299: productTrials: [],
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trial/list.test.ts:
Line 74: productTrials?: ProductTrial[] | null;
Line 78: productTrials: [],
Line 202: makeCustomerInfo({ productTrials: [], canTrial: false })
Line 216: makeCustomerInfo({ productTrials: [], canTrial: false })
Line 224: expect(JSON.parse(output)).toEqual([]);
Line 276: productTrials: [],
Line 298: productTrials: [],
Line 316: productTrials: [],
Line 362: productTrials: [],
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/view.test.ts:
Line 80: const result = ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/schema.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Schema Command Tests
3: *
4: * Covers resolveResourceQuery — in particular the no-match paths that used to
5: * dump the full resource list (byte-identical to a successful browse) instead
6: * of reporting that nothing matched. See getsentry/cli#1424.
7: */
8:
9: import { describe, expect, test } from "vitest";
10: import { resolveResourceQuery } from "../../src/commands/schema.js";
11: import { OutputError, ResolutionError } from "../../src/lib/errors.js";
12:
13: describe("resolveResourceQuery", () => {
14: test("returns endpoints for a known resource", () => {
15: const result = resolveResourceQuery("issues");
16: expect(result.kind).toBe("endpoints");
17: if (result.kind === "endpoints") {
18: expect(result.endpoints.length).toBeGreaterThan(0);
19: for (const ep of result.endpoints) {
20: ...
Found 7 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/local/run.test.ts:
Line 5: * exit code propagation, auto-detection, --verify, --timeout, and error cases.
Line 103: test("throws ValidationError when no command and no auto-detect", async () => {
Line 117: "No command provided and could not auto-detect"
Line 137: test("auto-detects dev command from package.json", async () => {
Line 146: // No args provided — should auto-detect and run "echo hello"
Line 153: // If we get here without throwing, auto-detection worked and
Line 578: await func.call(ctx, { port, host, verify: false, timeout: 0 }, "printenv");
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/local/run.test.ts</path>
<type>file</type>
<content>
80: afterEach(async () => {
81: try {
82: await rm(tmpDir, { recursive: true, force: true });
83: } catch {
84: // ignore cleanup errors
85: }
86: });
87:
88: function makeContext(cwd?: string) {
89: return {
90: stdout: { write: vi.fn(() => true) },
91: stderr: { write: vi.fn(() => true) },
92: cwd: cwd ?? tmpDir,
93: };
94: }
95:
96: describe("sentry local run", () => {
97: beforeEach(() => {
98: spawnCapture.args = undefined;
99: spawnCapture.env = undefined;
100: spawnCapture.stdio = undefined;
101: });
102:
103: test("throws ValidationError when no command and no auto-detect", async () => {
104: const func = (await runCommand.loader()) as unknown as RunFunc;
105: const ctx = makeContext();
106: try {
107: await func.call(ctx, {
108: port: 0,
109: host: "localhost",
110: ...
Found 9 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/monitor/run.test.ts:
Line 49: await func.call(
Line 72: func.call(
Line 90: await func.call(
Line 108: func.call(
Line 122: await func.call(
Line 146: func.call(ctx, { dsn: SAAS_DSN, environment: "production" }, "my-job")
Line 153: func.call(ctx, { dsn: SAAS_DSN, environment: "production" })
Line 160: func.call(
Line 176: func.call(
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/monitor/run.test.ts</path>
<type>file</type>
<content>
125: dsn: SAAS_DSN,
126: environment: "production",
127: schedule: "0 * * * *",
128: "max-runtime": 30,
129: },
130: "scheduled-job",
131: NODE,
132: "-e",
133: "process.exit(0)"
134: );
135:
136: const openBody = sendSpy.mock.calls[0]?.[1] as string;
137: const closeBody = sendSpy.mock.calls[1]?.[1] as string;
138: expect(openBody).toContain('"monitor_config"');
139: expect(openBody).toContain('"0 * * * *"');
140: expect(closeBody).not.toContain('"monitor_config"');
141: });
142:
143: test("missing command throws ValidationError", async () => {
144: const { ctx } = makeContext();
145: await expect(
146: func.call(ctx, { dsn: SAAS_DSN, environment: "production" }, "my-job")
147: ).rejects.toBeInstanceOf(ValidationError);
148: });
149:
150: ...
Found 35 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/create.test.ts:
Line 165: await func.call(context, { json: false }, "my-app:node");
Line 186: await func.call(context, { json: false }, "my-org/my-app:python");
Line 198: await func.call(context, { json: false }, "my-app:python-flask");
Line 260: await func.call(context, { json: false }, "my-org/api:europe:node");
Line 281: await func.call(context, { team: "mobile", json: false }, "my-app:go");
Line 301: await func.call(context, { json: false }, "my-app:node");
Line 380: await func.call(context, { json: false }, "my-app:node");
Line 404: func.call(context, { json: false }, "my-app:node")
Line 588: await func.call(context, { json: false }, "my-app:node");
Line 682: await func.call(context, { json: true }, "my-app:node");
Line 701: await func.call(context, { json: false }, "my-app:node");
Line 715: ...
Found 4 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/list.test.ts:
Line 579: test("empty page without hasMore shows no projects", async () => {
Line 993: test("returns empty array when org has no projects", async () => {
Line 1158: test("empty results returns hint with no projects message", async () => {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/create.test.ts:
Line 774: expect(err.message).toContain("Project specification is required");
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/project/create.test.ts</path>
<type>file</type>
<content>
750:
751: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
752: // Plain mode renders code spans as plain text without padding
753: expect(output).toContain("Slug my-app-0g was assigned");
754: expect(output).toContain("my-app is already taken");
755: });
756:
757: test("does not show slug note when slug matches name", async () => {
758: const { context, stdoutWrite } = createMockContext();
759: const func = await createCommand.loader();
760: await func.call(context, { json: false }, "my-app:node");
761:
762: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
763: expect(output).not.toContain("was assigned");
764: });
765:
766: test("shows helpful error when name is missing", async () => {
767: const { context } = createMockContext();
768: const func = await ...
Found 12 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/issue/merge.func.test.ts:
Line 99: expect(err.message).toContain("needs at least 2 issue IDs");
Line 111: expect(err.message).toContain("needs at least 2 issue IDs");
Line 116: test("rejects when 0 positionals + --into (still needs at least 1 positional)", async () => {
Line 124: expect(err.message).toContain("needs at least 2 issue IDs");
Line 145: await func.call(context, { json: false, into: "CLI-B" }, "CLI-A");
Line 170: expect(err.message).toContain("at least 2 distinct issues");
Line 234: await func.call(context, { json: false }, "CLI-A", "CLI-B", "CLI-C");
Line 298: await func.call(context, { json: false, into: "f-g" }, "CLI-A", "CLI-B");
Line 352: await func.call(context, { json: false, into: "CLI-C" }, "CLI-A", "CLI-B");
Line 376: await func.call(context, { json: true }, "CLI-A", "CLI-B");
Line 475: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/issue/merge.func.test.ts</path>
<type>file</type>
<content>
80:
81: beforeEach(() => {
82: resolveIssueSpy = vi.spyOn(issueUtils, "resolveIssue");
83: mergeSpy = vi.spyOn(apiClient, "mergeIssues");
84: });
85:
86: afterEach(() => {
87: resolveIssueSpy.mockRestore();
88: mergeSpy.mockRestore();
89: });
90:
91: test("rejects when fewer than 2 issues are provided (0 positionals, no --into)", async () => {
92: const { context } = createMockContext();
93: const func = await mergeCommand.loader();
94: const err = await func
95: .call(context, { json: false })
96: .catch((e: Error) => e);
97:
98: expect(err).toBeInstanceOf(Error);
99: expect(err.message).toContain("needs at least 2 issue IDs");
100: expect(mergeSpy).not.toHaveBeenCalled();
101: });
102:
103: test("rejects when 1 positional is given without --into (shows --into hint)", async () => {
104: ...
Found 25 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist/index.js:
Line 805: if (positionalIndex >= positional.parameters.length) {
Line 806: throw new UnexpectedPositionalError(positional.parameters.length, input);
Line 823: new UnsatisfiedPositionalError(getPlaceholder(positional.parameter), [
Line 831: const placeholder = getPlaceholder(positional.parameter, i + 1);
Line 832: return parseInput(placeholder, positional.parameter, input, context);
Line 837: positional.parameters.map(async (param, i) => {
Line 994: if (positional.parameter.proposeCompletions) {
Line 996: const positionalCompletions = await positional.parameter.proposeCompletions.call(
Line 1005: brief: positional.parameter.brief
Line 1012: const nextPositional = positional.parameters[positionalIndex];
Line 1798: function ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/node_modules/@stricli/core/dist/index.js</path>
<type>file</type>
<content>
1780: function wrapRequiredFlag(text) {
1781: return `(${text})`;
1782: }
1783: function wrapOptionalFlag(text) {
1784: return `[${text}]`;
1785: }
1786: function wrapVariadicFlag(text) {
1787: return `${text}...`;
1788: }
1789: function wrapRequiredParameter(text) {
1790: return `<${text}>`;
1791: }
1792: function wrapOptionalParameter(text) {
1793: return `[<${text}>]`;
1794: }
1795: function wrapVariadicParameter(text) {
1796: return `<${text}>...`;
1797: }
1798: function formatUsageLineForParameters(parameters, args) {
1799: const flagsUsage = Object.entries(parameters.flags ?? {}).filter(([, flag]) => {
1800: if (flag.hidden) {
1801: return false;
1802: }
1803: if (args.config.onlyRequiredInUsageLine && isOptionalAtRuntime(flag)) {
1804: return false;
1805: }
1806: return true;
1807: }).map(([name, ...
ac72db51b fix(docs): preserve public positional semantics
packages/cli/script/generate-command-docs.ts | 3 +-
.../cli/src/commands/agent-conversation/view.ts | 12 ++++-
packages/cli/src/lib/command.ts | 8 ++-
packages/cli/src/lib/introspect.ts | 11 +++-
packages/cli/test/lib/help-positional.test.ts | 50 ++++++++++--------
packages/cli/test/lib/introspect.property.test.ts | 16 ++++++
packages/cli/test/lib/introspect.test.ts | 48 +++++++++++++++++
.../cli/test/lib/scanner-flags.integration.test.ts | 61 ++++++++++++++++------
.../test/script/generate-skill-markdown.test.ts | 26 +++++++++
9 files changed, 191 insertions(+), 44 deletions(-)
commit ac72db51b18bb3e23999483233c9ad02d72ea531
Author: Burak Yigit Kaya <byk@sentry.io>
AuthorDate: Thu Sep 10 12:55:54 2026 +0000
Commit: Burak Yigit Kaya <byk@sentry.io>
CommitDate: Thu Sep 10 12:56:39 2026 +0000
fix(docs): preserve public positional ...
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 140) parameters: {
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 141) positional: {
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 142) kind: "array",
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 143) parameter: {
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 144) brief: "Path(s) to JSON event file(s) to send",
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 145) parse: String,
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 146) optional: true,
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 147) },
1a883b9e89 src/commands/event/send.ts (Burak Yigit Kaya 2026-06-02 19:11:14 +0100 148) },
1a883b9e89 ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/e2e/feedback.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Feedback command E2E tests.
3: *
4: * Exercises the real command router and generated API client against a mock
5: * Sentry API, including the mandatory issue-category and status filters.
6: */
7:
8: import {
9: afterAll,
10: afterEach,
11: beforeAll,
12: beforeEach,
13: describe,
14: expect,
15: test,
16: } from "vitest";
17: import { EXIT } from "../../src/lib/errors.js";
18: import { createE2EContext, type E2EContext } from "../fixture.js";
19: import { cleanupTestDir, createTestConfigDir } from "../helpers.js";
20: import {
21: createSentryMockServer,
22: TEST_FEEDBACK_ID,
23: TEST_FEEDBACK_LATEST_ORG,
24: TEST_FEEDBACK_SHORT_ID,
25: TEST_ORG,
26: TEST_PROJECT,
27: TEST_TOKEN,
28: } from "../mocks/routes.js";
29: import type { MockServer } from "../mocks/server.js";
30:
31: let testConfigDir: string;
32: let mockServer: ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli/defaults.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry cli defaults` command.
3: *
4: * Verifies show/set/clear/clear-all modes, validation, formatter output,
5: * and the telemetry/URL integration points.
6: */
7:
8: import chalk from "chalk";
9: import { describe, expect, test } from "vitest";
10: import {
11: clearAllDefaults,
12: getAgentSkillsPreference,
13: getAllDefaults,
14: getDefaultHeaders,
15: getDefaultOrganization,
16: getDefaultProject,
17: getDefaultUrl,
18: getTelemetryPreference,
19: setAgentSkillsPreference,
20: setDefaultOrganization,
21: setDefaultProject,
22: setDefaultUrl,
23: setTelemetryPreference,
24: } from "../../../src/lib/db/defaults.js";
25: import { getDatabase } from "../../../src/lib/db/index.js";
26: import { formatDefaultsResult } from "../../../src/lib/formatters/human.js";
27: import { stripAnsi } from ...
Found 13 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli/fix.test.ts:
Line 113: const func = await fixCommand.loader();
Line 485: const func = await fixCommand.loader();
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/cli/defaults.test.ts:
Line 4: * Verifies show/set/clear/clear-all modes, validation, formatter output,
Line 395: action: "show",
Line 414: action: "show",
Line 432: test("show action with env var override shows note", () => {
Line 434: action: "show",
Line 451: test("show action with DO_NOT_TRACK override shows note", () => {
Line 453: action: "show",
Line 467: test("show action without env override shows no note", () => {
Line 469: action: "show",
Line 519: test("clear-all action formats correctly", () => {
Line 521: action: "clear-all",
Found 1 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/find.test.ts:
Line 87: test("exits successfully when there is nothing to find (no ids)", async () => {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/find.test.ts</path>
<type>file</type>
<content>
55: stderr: { write: () => true },
56: stdin: process.stdin,
57: };
58: await run(app, ["debug-files", "find", ...args], mockContext);
59: return { output, exitCode: mockContext.process.exitCode };
60: }
61:
62: describe("sentry debug-files find", () => {
63: test("finds a breakpad file but still reports the id as missing (exit 1)", async () => {
64: await writeFile(join(tempDir, "example.sym"), BREAKPAD_FIXTURE);
65:
66: const { output, exitCode } = await runFind([
67: BREAKPAD_ID,
68: "--no-well-known",
69: "--no-cwd",
70: "--path",
71: tempDir,
72: "--json",
73: ]);
74: const parsed = JSON.parse(output);
75: expect(parsed.matches).toHaveLength(1);
76: expect(parsed.matches[0]).toMatchObject({
77: type: "breakpad",
78: id: BREAKPAD_ID,
79: });
80: // A ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/react-native/xcode.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry react-native xcode` mode selection.
3: *
4: * The build-script spawn, sourcemap upload, org/project resolution, and debug-id
5: * injection are mocked so the three modes (need-Xcode error, debug passthrough,
6: * release wrap+upload) can be exercised off-device.
7: */
8:
9: import { spawnSync } from "node:child_process";
10: import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
11: import { tmpdir } from "node:os";
12: import { join } from "node:path";
13: import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
14: import { xcodeCommand } from "../../../src/commands/react-native/xcode.js";
15: // biome-ignore lint/performance/noNamespaceImport: needed for spyOn mocking
16: import * as sourcemaps from "../../../src/lib/api/sourcemaps.js";
17: // biome-ignore ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/send-envelope.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for `sentry send-envelope` deprecation shim.
3: */
4:
5: import { beforeEach, describe, expect, test, vi } from "vitest";
6: import { sendEnvelopeCommand } from "../../src/commands/send-envelope.js";
7: import { CliError } from "../../src/lib/errors.js";
8: import { useTestConfigDir } from "../helpers.js";
9:
10: useTestConfigDir("send-envelope-");
11:
12: function makeContext() {
13: return {
14: stdout: { write: vi.fn(() => true) },
15: stderr: { write: vi.fn(() => true) },
16: cwd: "/tmp",
17: };
18: }
19:
20: describe("sendEnvelopeCommand (deprecation shim)", () => {
21: let func: Awaited<ReturnType<typeof sendEnvelopeCommand.loader>>;
22:
23: beforeEach(async () => {
24: func = await sendEnvelopeCommand.loader();
25: });
26:
27: test("throws CliError suggesting event send --raw", async () => {
28: ...
Found 14 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/list.test.ts:
Line 211: await func.call(context, defaultFlags({ json: true }));
Line 232: await func.call(context, defaultFlags({ json: true }));
Line 286: await func.call(context, defaultFlags({ web: true }));
Line 305: await func.call(context, defaultFlags({ json: true, limit: 10 }));
Line 329: await func.call(context, defaultFlags({ json: true, limit: 2 }));
Line 346: await func.call(context, defaultFlags({ limit: 2 }));
Line 361: await func.call(context, defaultFlags({ json: true }));
Line 386: await func.call(context, defaultFlags({ json: true, limit: 3 }));
Line 411: await func.call(context, defaultFlags({ json: true }), "Error*");
Line 429: await func.call(context, defaultFlags({ json: true }), "my-org/", "*API*");
Line 447: await func.call(context, defaultFlags({ json: true }), "error*");
Line 501: await ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/list.test.ts</path>
<type>file</type>
<content>
190: resolveOrgSpy.mockReset();
191: openInBrowserSpy.mockReset();
192: withProgressSpy.mockReset();
193: resolveCursorSpy.mockReset();
194: advancePaginationStateSpy.mockReset();
195: hasPreviousPageSpy.mockReset();
196: });
197:
198: // -------------------------------------------------------------------------
199: // JSON output
200: // -------------------------------------------------------------------------
201:
202: test("outputs JSON envelope with { data, hasMore } when --json", async () => {
203: resolveOrgSpy.mockResolvedValue({ org: "test-org" });
204: listDashboardsPaginatedSpy.mockResolvedValue({
205: data: [DASHBOARD_A, DASHBOARD_B],
206: nextCursor: undefined,
207: });
208:
209: const { context, stdoutWrite } = createMockContext();
210: const func = await ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/list.test.ts</path>
<type>file</type>
<content>
360: resolveOrgProjectSpy.mockRestore();
361: withProgressSpy.mockRestore();
362: });
363:
364: test("outputs JSON envelope with data and hasMore for --json", async () => {
365: listLogsSpy.mockResolvedValue(sampleLogs);
366: resolveOrgProjectSpy.mockResolvedValue({ org: ORG, project: PROJECT });
367:
368: const { context, stdoutWrite } = createMockContext();
369: const func = await listCommand.loader();
370: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
371:
372: const output = stdoutWrite.mock.calls.map((c) => c[0]).join("");
373: const parsed = JSON.parse(output);
374: expect(parsed).toHaveProperty("data");
375: expect(parsed).toHaveProperty("hasMore");
376: expect(Array.isArray(parsed.data)).toBe(true);
377: expect(parsed.data).toHaveLength(3);
378: });
379:
380: test("outputs JSON in ...
No files found
Found 6 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/upload.test.ts:
Line 154: test("no paths exits non-zero", async () => {
Line 182: // ── --derived-data ───────────────────────────────────────────────
Line 184: test("--derived-data is additive: explicit paths still scan", async () => {
Line 188: "--derived-data",
Line 199: "--derived-data alone on non-macOS exits non-zero (no scan targets)",
Line 201: const { exitCode } = await runUpload(["--derived-data", "--no-upload"]);
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/debug-files/upload.test.ts</path>
<type>file</type>
<content>
135: },
136: },
137: stderr: {
138: write(data: string | Uint8Array) {
139: error +=
140: typeof data === "string" ? data : new TextDecoder().decode(data);
141: return true;
142: },
143: },
144: stdin: process.stdin,
145: };
146:
147: await run(app, ["debug-files", "upload", ...args], mockContext);
148: return { output, error, exitCode: mockContext.process.exitCode };
149: }
150:
151: describe("sentry debug-files upload", () => {
152: // ── Input validation ─────────────────────────────────────────────
153:
154: test("no paths exits non-zero", async () => {
155: const { exitCode } = await runUpload([]);
156: expect(exitCode).not.toBe(0);
157: });
158:
159: test("--wait and --wait-for together exits non-zero", async () => {
160: const path = await ...
Found 2 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts:
Line 81: function collectScanPaths(paths: string[], derivedData: boolean): string[] {
Line 664: const scanTargets = collectScanPaths(paths, Boolean(flags["derived-data"]));
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/debug-files/upload.ts</path>
<type>file</type>
<content>
60:
61: const log = logger.withTag("debug-files.upload");
62:
63: const USAGE_HINT = "sentry debug-files upload <path>...";
64:
65: /** Relative path to Xcode's DerivedData folder under the user's home dir. */
66: const DERIVED_DATA_SUBPATH = "Library/Developer/Xcode/DerivedData";
67:
68: /**
69: * Resolve the effective scan paths, optionally appending Xcode's DerivedData
70: * folder when `--derived-data` is set.
71: *
72: * DerivedData only exists on macOS; on other platforms the flag is a no-op
73: * (with a warning). The folder is appended only when it actually exists, so the
74: * stricter `scanPaths` existence check (which throws on a missing explicit
75: * path) is never tripped by an absent DerivedData directory.
76: *
77: * @param paths - Positional paths supplied on the command line. ...
Found 20 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/trace/logs.test.ts:
Line 38: import { ContextError } from "../../../src/lib/errors.js";
Line 170: await func.call(
Line 199: await func.call(
Line 224: await func.call(
Line 247: await func.call(
Line 269: await func.call(
Line 293: await func.call(
Line 316: await func.call(
Line 339: await func.call(
Line 362: await func.call(
Line 386: await func.call(
Line 411: await func.call(
Line 429: test("throws ContextError when org cannot be resolved", async () => {
Line 436: func.call(
Line 447: ).rejects.toThrow(ContextError);
Line 458: await func.call(
Line 485: await func.call(
Line 514: await func.call(
Line 540: await func.call(
Line 565: await func.call(
Found 3 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/scanner-flags.integration.test.ts: Line 218: // After `--`, tokens are positional/pass-through. `bash-hook` takes no Line 219: // positionals, so Stricli reports too-many-arguments — proving `--verbose` Line 260: // bash-hook takes no positionals, so a `--version` past `--` triggers a
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/lib/help-positional.test.ts</path>
<type>file</type>
<content>
1: /**
2: * Tests for help-as-positional-arg error recovery in buildCommand.
3: *
4: * When a command throws a CliError and a positional arg was `"help"`,
5: * the buildCommand wrapper recovers by showing the command's help
6: * instead of the confusing error.
7: *
8: * This only fires as error recovery — if a command successfully resolves
9: * a legitimate value like a project named "help", the recovery never runs.
10: *
11: * Tests run commands through Stricli's `run()` with `help` as a positional
12: * and verify help output is shown when resolution fails.
13: */
14:
15: import { generateHelpTextForAllCommands, run } from "@stricli/core";
16: import { afterEach, beforeEach, describe, expect, test } from "vitest";
17: import { app } from "../../src/app.js";
18: import type { SentryContext } from "../../src/context.js";
19: import { mockFetch, ...
Found 8 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/introspect.ts:
Line 296: export function buildCommandInfo(
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/command.ts:
Line 88: * that Stricli's `CommandBuilderArguments` enforces via `NoInfer`.
Line 95: import("@stricli/core").CommandBuilderArguments<BaseFlags, BaseArgs, CONTEXT>;
Line 146: * This is the subset of Stricli's CommandBuilderArguments that we support.
Line 148: type LocalCommandBuilderArguments<
Line 542: export function buildCommand<
Line 547: builderArgs: LocalCommandBuilderArguments<FLAGS, ARGS, CONTEXT>
Line 886: // `CommandBuilderArguments` enforces via `NoInfer`.
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/command.ts</path> <type>file</type> <content> 70: /** 71: * Parse a string input as a number. 72: * Re-exported from Stricli for convenience. 73: */ 74: export const numberParser = stricliNumberParser; 75: 76: /** Base flags type from Stricli */ 77: type BaseFlags = Readonly<Partial<Record<string, unknown>>>; 78: 79: /** Base args type from Stricli */ 80: type BaseArgs = readonly unknown[]; 81: 82: /** 83: * Type-erased Stricli builder arguments. 84: * 85: * At the `stricliCommand()` call site we've modified both `parameters` 86: * (injected hidden flags) and `func` (wrapped with telemetry/output 87: * logic), which breaks the original `FLAGS`/`ARGS` generic alignment 88: * that Stricli's `CommandBuilderArguments` enforces via `NoInfer`. ...
Found 76 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md: Line 14: ### `sentry schema <resource...>` Line 26: sentry schema Line 29: sentry schema issues Line 32: sentry schema issues list Line 35: sentry schema --search monitor Line 38: sentry schema --all /home/byk/Code/getsentry/cli-pr-1558/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/local.md: Line 27: ### `sentry local run <command...>` Line 48: sentry local run -- npm run dev Line 49: sentry local run -- python manage.py runserver Line 67: sentry local run --format json \ /home/byk/Code/getsentry/cli-pr-1558/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/span.md: Line 14: ### `sentry span list <org/project/trace-id...>` Line 44: sentry span list Line 47: sentry span list -q "op:db" Line 50: sentry span list -q "duration:>100ms" --period 24h Line 53: sentry span list ...
No files found
Found 6 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/e2e/bundle.test.ts:
Line 166: // `cli defaults` (no args) reads all defaults from SQLite — exercises
Line 183: // Should succeed — cli defaults with no args just shows current state
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts:
Line 100: test("no args → project mode", () => {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/release/deploy.test.ts:
Line 144: test("throws when no args provided", async () => {
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/agent-conversation/view.test.ts:
Line 7: * - Throwing error when no args provided
Line 268: test("throws error when no args provided", async () => {
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/e2e/bundle.test.ts</path>
<type>file</type>
<content>
150: }
151: );
152:
153: const output = stdout + stderr;
154:
155: // Must exit 10 (AUTH_NOT_AUTHENTICATED), not crash
156: expect(exitCode).toBe(10);
157: expect(output.toLowerCase()).toContain("not authenticated");
158:
159: // Must not contain Node.js module resolution errors
160: expect(output).not.toContain("Cannot find module");
161: expect(output).not.toContain("MODULE_NOT_FOUND");
162: expect(output).not.toContain("ERR_MODULE_NOT_FOUND");
163: }, 15_000);
164:
165: test("bundle exercises SQLite with cli defaults", async () => {
166: // `cli defaults` (no args) reads all defaults from SQLite — exercises
167: // DB init and the metadata KV store without requiring auth. ...
No files found
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/event.md</path> <type>file</type> <content> 84: sentry event list PROJ-ABC -c prev 85: 86: # Output as JSON 87: sentry event list PROJ-ABC --json 88: ``` 89: 90: ### `sentry event send <args...>` 91: 92: Send a Sentry event 93: 94: **Flags:** 95: - `--dsn <value> - DSN to send events to (overrides SENTRY_DSN env var)` 96: - `-m, --message <value>... - Event message (repeat for multi-line)` 97: - `-a, --message-arg <value>... - Arguments for message template (repeat for multiple)` 98: - `-l, --level <value> - Event severity level - (default: "error")` 99: - `-r, --release <value> - Release version` 100: - `-d, --dist <value> - Distribution identifier` 101: - `-E, --env <value> - Environment name (e.g. production, staging)` (Showing lines 84-101 of 148. Use offset=102 to continue.) </content>
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/plugins/sentry-cli/skills/sentry-cli/references/schema.md</path> <type>file</type> <content> 10: # Schema Commands 11: 12: Browse the Sentry API schema 13: 14: ### `sentry schema <resource...>` 15: 16: Browse the Sentry API schema 17: 18: **Flags:** 19: - `--all - Show all endpoints in a flat list` 20: - `-q, --search <value> - Search endpoints by keyword` 21: 22: **Examples:** 23: 24: ```bash 25: # List all API resources 26: sentry schema 27: 28: # Browse issue endpoints 29: sentry schema issues 30: 31: # View details for a specific operation 32: sentry schema issues list 33: 34: # Search for monitoring-related endpoints (Showing lines 10-34 of 41. Use offset=35 to continue.) </content>
File not found: /home/byk/Code/getsentry/cli-pr-1558/.cursor/rules/ultracite.mdc
No files found
Found 42 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/log/list.test.ts:
Line 370: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
Line 388: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
Line 423: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 435: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 449: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 462: await func.call(context, { json: false, limit: 3 }, `${ORG}/${PROJECT}`);
Line 474: await func.call(context, HUMAN_FLAGS, `${ORG}/${PROJECT}`);
Line 540: await func.call(context, { json: true, limit: 3 }, `${ORG}/${PROJECT}`);
Line 553: await func.call(context, BATCH_FLAGS, `${ORG}/${PROJECT}`);
Line 595: await func.call(context, BATCH_FLAGS, TRACE_ID);
Line 616: func.call(context, { ...BATCH_FLAGS, query: "bad:::query" }, TRACE_ID)
Line 629: ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/span/list.test.ts</path>
<type>file</type>
<content>
80: });
81:
82: test("rejects 'time' (use 'date' instead)", () => {
83: expect(() => parseSort("time")).toThrow("Invalid sort value");
84: });
85:
86: test("throws for invalid value", () => {
87: expect(() => parseSort("name")).toThrow("Invalid sort value");
88: });
89:
90: test("throws for empty string", () => {
91: expect(() => parseSort("")).toThrow("Invalid sort value");
92: });
93: });
94:
95: // ============================================================================
96: // parseSpanListArgs — positional argument disambiguation
97: // ============================================================================
98:
99: describe("parseSpanListArgs", () => {
100: test("no args → project mode", () => {
101: const result = parseSpanListArgs([]);
102: expect(result).toEqual({ mode: "project" });
103: });
104:
105: ...
Found 3 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/resolve.test.ts:
Line 77: test("throws ValidationError for empty args", () => {
Line 156: test("empty args returns undefined for both", () => {
Line 157: const result = parseDashboardListArgs([]);
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/dashboard/resolve.test.ts</path>
<type>file</type>
<content>
65: ])
66: );
67: });
68:
69: // biome-ignore lint/performance/noNamespaceImport: needed for spyOn mocking
70: import * as resolveTarget from "../../../src/lib/resolve-target.js";
71:
72: // ---------------------------------------------------------------------------
73: // parseDashboardPositionalArgs
74: // ---------------------------------------------------------------------------
75:
76: describe("parseDashboardPositionalArgs", () => {
77: test("throws ValidationError for empty args", () => {
78: expect(() => parseDashboardPositionalArgs([])).toThrow(ValidationError);
79: });
80:
81: test("error message contains 'Dashboard ID or title'", () => {
82: try {
83: parseDashboardPositionalArgs([]);
84: expect.unreachable("Should have thrown");
85: } catch (error) {
86: ...
Found 2 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/docs.test.ts:
Line 83: await func.call(context, { json: true }, "How", "do", "I", "trace?");
Line 139: await func.call(context, { json: false, limit: 5 }, "nextjs", "tracing");
Found 8 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/build/upload.test.ts:
Line 114: await func.call(harness.context, {}, apk);
Line 129: await func.call(
Line 151: await func.call(
Line 174: await func.call(harness.context, {}, bad);
Line 197: await func.call(harness.context, {}, dir);
Line 211: await func.call(harness.context, {}, dir);
Line 230: await func.call(harness.context, {}, ipa);
Line 243: await func.call(harness.context, {}, apk, bad);
Found 15 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/proguard/upload.test.ts:
Line 22: "require-one"?: boolean;
Line 69: test("no paths: throws ContextError", async () => {
Line 72: await func.call(ctx, {});
Line 79: test("no paths with --require-one: throws ValidationError", async () => {
Line 82: await func.call(ctx, { "require-one": true });
Line 86: expect((err as Error).message).toContain("--require-one");
Line 98: await func.call(
Line 117: await func.call(ctx, { uuid: "not-a-uuid" }, f);
Line 129: await func.call(ctx, {}, missing);
Line 140: await func.call(ctx, {}, dir);
Line 155: await func.call(ctx, { "no-upload": true }, f);
Line 171: func.call(ctx, { "no-upload": true }, f)
Line 186: await func.call(ctx, {}, f);
Line 213: await func.call(ctx, {}, f1, f2);
Line 235: await func.call(ctx, { uuid: forcedUuid }, f);
Found 3 matches
/home/byk/Code/getsentry/cli-pr-1558/packages/cli/test/commands/replay/view.test.ts:
Line 40: ContextError,
Line 131: test("throws ContextError for org/project with no replay ID", () => {
Line 132: expect(() => parsePositionalArgs(["test-org/cli"])).toThrow(ContextError);
Found 2 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/agent-conversation/view.ts: Line 75: customUsage: [USAGE], /home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/commands/project/create.ts: Line 609: customUsage: ["[<org>/]<name>:<platform>..."],
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/script/generate-command-docs.ts</path>
<type>file</type>
<content>
140: /** Format flags as a markdown options table */
141: function formatFlagsTable(
142: flags: FlagInfo[],
143: aliases: Record<string, string>
144: ): string {
145: if (flags.length === 0) {
146: return "";
147: }
148:
149: const lines: string[] = [];
150: lines.push("**Options:**");
151: lines.push("");
152: lines.push("| Option | Description |");
153: lines.push("|--------|-------------|");
154: for (const flag of flags) {
155: lines.push(formatFlagRow(flag, aliases));
156: }
157: return lines.join("\n");
158: }
159:
160: // ---------------------------------------------------------------------------
161: // Page Generation
162: // ---------------------------------------------------------------------------
163:
164: /** Generate the auto-generated reference section for a single command */
165: function ...
Found 3 matches /home/byk/Code/getsentry/cli-pr-1558/packages/cli/script/generate-command-docs.ts: Line 29: formatCommandArguments, Line 177: lines.push(formatCommandArguments(cmd.positionals)); /home/byk/Code/getsentry/cli-pr-1558/packages/cli/script/generate-skill-markdown.ts: Line 53: export function formatCommandArguments(
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/script/generate-skill-markdown.ts</path>
<type>file</type>
<content>
40:
41: /** Format canonical command examples as a Markdown section. */
42: export function formatCommandExamples(examples: readonly string[]): string {
43: if (examples.length === 0) {
44: return "";
45: }
46:
47: return ["**Examples:**", "", "```bash", examples.join("\n\n"), "```"].join(
48: "\n"
49: );
50: }
51:
52: /** Format positional arguments as a Markdown table. */
53: export function formatCommandArguments(
54: positionals: readonly PositionalInfo[]
55: ): string {
56: if (positionals.length === 0) {
57: return "";
58: }
59:
60: const lines = [
61: "**Arguments:**",
62: "",
63: "| Argument | Description |",
64: "|----------|-------------|",
65: ];
66: for (const positional of positionals) {
67: const value = `<${positional.placeholder}${positional.variadic ? "..." : ""}>`;
68: const syntax ...
<path>/home/byk/Code/getsentry/cli-pr-1558/packages/cli/src/lib/introspect.ts</path>
<type>file</type>
<content>
67: /** Positional parameter definitions — either fixed-length tuple or variadic array */
68: export type PositionalParams =
69: | { kind: "tuple"; parameters: readonly PositionalParam[] }
70: | {
71: kind: "array";
72: parameter: PositionalParam;
73: minimum?: number;
74: maximum?: number;
75: };
76:
77: /** A single positional parameter with optional brief and placeholder */
78: export type PositionalParam = {
79: brief?: string;
80: placeholder?: string;
81: optional?: boolean;
82: };
83:
84: /** Extracted metadata for a single positional argument */
85: export type PositionalInfo = {
86: /** Placeholder text without angle brackets or a variadic ellipsis. */
87: placeholder: string;
88: /** Human-readable explanation, or an empty string when none is defined. ...
M packages/cli/script/generate-command-docs.ts
M packages/cli/script/generate-skill-markdown.ts
M packages/cli/src/lib/introspect.ts
M packages/cli/test/lib/introspect.property.test.ts
M packages/cli/test/lib/introspect.test.ts
M packages/cli/test/script/generate-skill-markdown.test.ts
ac72db51b (HEAD -> fix/agent-conversation-reference-root-cause) fix(docs): preserve public positional semantics
diff --git a/packages/cli/script/generate-skill-markdown.ts b/packages/cli/script/generate-skill-markdown.ts
index 847f6a7bd..a2caa4311 100644
--- a/packages/cli/script/generate-skill-markdown.ts
+++ b/packages/cli/script/generate-skill-markdown.ts
@@ -2,6 +2,8 @@
* Markdown parsing helpers shared by the skill generator and its tests.
*/
+import type { PositionalInfo } from "../src/lib/introspect.js";
+
/** Matches a generated command heading and stops before positional usage. */
const COMMAND_HEADING_RE =
/^`sentry\s+([^<[`\s]+(?:\s+[^<[`\s]+)*)(?:\s*(?:<|\[)[^`]*)?`$/;
@@ ...
diff --git a/packages/cli/script/generate-command-docs.ts b/packages/cli/script/generate-command-docs.ts
index ac02d200b..291b4efa0 100644
--- a/packages/cli/script/generate-command-docs.ts
+++ b/packages/cli/script/generate-command-docs.ts
@@ -25,7 +25,10 @@
import { mkdirSync, rmSync } from "node:fs";
import { access, readFile, writeFile } from "node:fs/promises";
-import { formatCommandExamples } from "./generate-skill-markdown.js";
+import {
+ formatCommandArguments,
+ formatCommandExamples,
+} from "./generate-skill-markdown.js";
import { DOCS_CONTENT, DOCS_FRAGMENTS } from "./paths.js";
// Ensure src/generated/skill-content.ts exists before importing the route tree.
@@ -50,7 +53,6 @@ import type { EnvVarEntry } from "../src/lib/env-registry.js";
import type {
CommandInfo,
FlagInfo,
- PositionalInfo,
RouteInfo,
RouteMap,
} from "../src/lib/introspect.js";
@@ -135,34 +137,6 @@ function formatFlagRow(
return `| \`${syntax}\` | ${desc} |`;
}
-/**
- * ...
No files found