Skip to content

Commit 57c0a11

Browse files
authored
feat(output): add Zod schema registration to OutputConfig for self-documenting JSON fields (#582)
## Summary - Adds optional `schema` field to `OutputConfig<T>` accepting a Zod schema that describes the JSON output shape - When registered, the schema automatically enriches `--help` output and the `--fields` flag with available field names and types - Exposes structured `jsonFields` on `CommandInfo` for `sentry help` and SKILL.md generation - Creates `SentryIssueSchema` with 19 documented fields (id, shortId, title, count, userCount, firstSeen, lastSeen, status, priority, etc.) - Registers schemas on all 7 list commands: issue, team, repo, trace, span, log, trial - Updates agent guidance docs to mention available fields and warn against unnecessary `sentry api` fallbacks ## Motivation Agents fall back to raw `sentry api` calls when they need fields like `count`, `userCount`, `firstSeen`, or `lastSeen` because the CLI doesn't document what `--json` returns. This makes the JSON output self-documenting through `--help`, `sentry help <cmd>`, and SKILL.md field tables. Closes #566
1 parent 9a70b24 commit 57c0a11

File tree

23 files changed

+520
-56
lines changed

23 files changed

+520
-56
lines changed

docs/src/content/docs/agent-guidance.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ The `sentry` CLI follows conventions from well-known tools — if you're familia
2222

2323
## Context Window Tips
2424

25-
- Use `--fields id,title,status` on list commands to reduce output size
25+
- Use `--json --fields` to select specific fields and reduce output size. Run `<command> --help` to see available fields. Example: `sentry issue list --json --fields shortId,title,count,userCount,lastSeen`
2626
- Use `--json` when piping output between commands or processing programmatically
2727
- Use `--limit` to cap the number of results (default is usually 10–100)
2828
- Prefer `sentry issue view PROJECT-123` over listing and filtering manually
@@ -158,3 +158,4 @@ sentry dashboard widget add <dashboard> "Top Endpoints" --display table \
158158
- **Confusing `--query` syntax**: The `--query` flag uses Sentry search syntax (e.g., `is:unresolved`, `assigned:me`), not free text search.
159159
- **Not using `--web`**: View commands support `-w`/`--web` to open the resource in the browser — useful for sharing links.
160160
- **Fetching API schemas instead of using the CLI**: Prefer `sentry schema` to browse the API and `sentry api` to make requests — the CLI handles authentication and endpoint resolution, so there's rarely a need to download OpenAPI specs separately.
161+
- **Using `sentry api` when CLI commands suffice**: `sentry issue list --json` already includes `count`, `userCount`, `firstSeen`, `lastSeen`, `priority`, and other fields at the top level. Use `--fields` to select specific fields. Run `--help` to see all available fields. Only fall back to `sentry api` for data the CLI doesn't expose.

plugins/sentry-cli/skills/sentry-cli/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The `sentry` CLI follows conventions from well-known tools — if you're familia
3232

3333
### Context Window Tips
3434

35-
- Use `--fields id,title,status` on list commands to reduce output size
35+
- Use `--json --fields` to select specific fields and reduce output size. Run `<command> --help` to see available fields. Example: `sentry issue list --json --fields shortId,title,count,userCount,lastSeen`
3636
- Use `--json` when piping output between commands or processing programmatically
3737
- Use `--limit` to cap the number of results (default is usually 10–100)
3838
- Prefer `sentry issue view PROJECT-123` over listing and filtering manually
@@ -168,6 +168,7 @@ sentry dashboard widget add <dashboard> "Top Endpoints" --display table \
168168
- **Confusing `--query` syntax**: The `--query` flag uses Sentry search syntax (e.g., `is:unresolved`, `assigned:me`), not free text search.
169169
- **Not using `--web`**: View commands support `-w`/`--web` to open the resource in the browser — useful for sharing links.
170170
- **Fetching API schemas instead of using the CLI**: Prefer `sentry schema` to browse the API and `sentry api` to make requests — the CLI handles authentication and endpoint resolution, so there's rarely a need to download OpenAPI specs separately.
171+
- **Using `sentry api` when CLI commands suffice**: `sentry issue list --json` already includes `count`, `userCount`, `firstSeen`, `lastSeen`, `priority`, and other fields at the top level. Use `--fields` to select specific fields. Run `--help` to see all available fields. Only fall back to `sentry api` for data the CLI doesn't expose.
171172

172173
## Prerequisites
173174

plugins/sentry-cli/skills/sentry-cli/references/issues.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,30 @@ List issues in a project
2424
- `--compact - Single-line rows for compact output (auto-detects if omitted)`
2525
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
2626

27+
**JSON Fields** (use `--json --fields` to select specific fields):
28+
29+
| Field | Type | Description |
30+
|-------|------|-------------|
31+
| `id` | string | Numeric issue ID |
32+
| `shortId` | string | Human-readable short ID (e.g. PROJ-ABC) |
33+
| `title` | string | Issue title |
34+
| `culprit` | string | Culprit string |
35+
| `count` | string | Total event count |
36+
| `userCount` | number | Number of affected users |
37+
| `firstSeen` | string \| null | First occurrence (ISO 8601) |
38+
| `lastSeen` | string \| null | Most recent occurrence (ISO 8601) |
39+
| `level` | string | Severity level |
40+
| `status` | string | Issue status |
41+
| `priority` | string | Triage priority |
42+
| `platform` | string | Platform |
43+
| `permalink` | string | URL to the issue in Sentry |
44+
| `project` | object | Project info |
45+
| `metadata` | object | Issue metadata |
46+
| `assignedTo` | unknown \| null | Assigned user or team |
47+
| `substatus` | string \| null | Issue substatus |
48+
| `isUnhandled` | boolean | Whether the issue is unhandled |
49+
| `seerFixabilityScore` | number \| null | Seer AI fixability score (0-1) |
50+
2751
**Examples:**
2852

2953
```bash

plugins/sentry-cli/skills/sentry-cli/references/logs.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,17 @@ List logs from a project
2222
- `-t, --period <value> - Time period (e.g., "90d", "14d", "24h"). Default: 90d (project mode), 14d (trace mode)`
2323
- `--fresh - Bypass cache, re-detect projects, and fetch fresh data`
2424

25+
**JSON Fields** (use `--json --fields` to select specific fields):
26+
27+
| Field | Type | Description |
28+
|-------|------|-------------|
29+
| `sentry.item_id` | string | Unique log entry ID |
30+
| `timestamp` | string | Log timestamp (ISO 8601) |
31+
| `timestamp_precise` | number | Nanosecond-precision timestamp |
32+
| `message` | string \| null | Log message |
33+
| `severity` | string \| null | Severity level (error, warning, info, debug) |
34+
| `trace` | string \| null | Trace ID for correlation |
35+
2536
**Examples:**
2637

2738
```bash

plugins/sentry-cli/skills/sentry-cli/references/teams.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ List repositories
2222
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
2323
- `-c, --cursor <value> - Navigate pages: "next", "prev", "first" (or raw cursor string)`
2424

25+
**JSON Fields** (use `--json --fields` to select specific fields):
26+
27+
| Field | Type | Description |
28+
|-------|------|-------------|
29+
| `id` | string | Repository ID |
30+
| `name` | string | Repository name |
31+
| `url` | string \| null | Repository URL |
32+
| `provider` | object | Version control provider |
33+
| `status` | string | Integration status |
34+
| `dateCreated` | string | Creation date (ISO 8601) |
35+
| `integrationId` | string | Integration ID |
36+
| `externalSlug` | string \| null | External slug (e.g. org/repo) |
37+
| `externalId` | string \| null | External ID |
38+
2539
### `sentry team list <org/project>`
2640

2741
List teams
@@ -31,6 +45,18 @@ List teams
3145
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
3246
- `-c, --cursor <value> - Navigate pages: "next", "prev", "first" (or raw cursor string)`
3347

48+
**JSON Fields** (use `--json --fields` to select specific fields):
49+
50+
| Field | Type | Description |
51+
|-------|------|-------------|
52+
| `id` | string | Team ID |
53+
| `slug` | string | Team slug |
54+
| `name` | string | Team name |
55+
| `dateCreated` | string | Creation date (ISO 8601) |
56+
| `isMember` | boolean | Whether you are a member |
57+
| `teamRole` | string \| null | Your role in the team |
58+
| `memberCount` | number | Number of members |
59+
3460
**Examples:**
3561

3662
```bash

plugins/sentry-cli/skills/sentry-cli/references/traces.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@ List spans in a project or trace
2525
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
2626
- `-c, --cursor <value> - Navigate pages: "next", "prev", "first" (or raw cursor string)`
2727

28+
**JSON Fields** (use `--json --fields` to select specific fields):
29+
30+
| Field | Type | Description |
31+
|-------|------|-------------|
32+
| `id` | string | Span ID |
33+
| `parent_span` | string \| null | Parent span ID |
34+
| `span.op` | string \| null | Span operation (e.g. http.client, db) |
35+
| `description` | string \| null | Span description |
36+
| `span.duration` | number \| null | Duration (ms) |
37+
| `timestamp` | string | Timestamp (ISO 8601) |
38+
| `project` | string | Project slug |
39+
| `transaction` | string \| null | Transaction name |
40+
| `trace` | string | Trace ID |
41+
2842
### `sentry span view <trace-id/span-id...>`
2943

3044
View details of specific spans
@@ -45,6 +59,17 @@ List recent traces in a project
4559
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
4660
- `-c, --cursor <value> - Navigate pages: "next", "prev", "first" (or raw cursor string)`
4761

62+
**JSON Fields** (use `--json --fields` to select specific fields):
63+
64+
| Field | Type | Description |
65+
|-------|------|-------------|
66+
| `trace` | string | Trace ID |
67+
| `id` | string | Event ID |
68+
| `transaction` | string | Transaction name |
69+
| `timestamp` | string | Timestamp (ISO 8601) |
70+
| `transaction.duration` | number | Duration (ms) |
71+
| `project` | string | Project slug |
72+
4873
### `sentry trace view <org/project/trace-id...>`
4974

5075
View details of a specific trace

plugins/sentry-cli/skills/sentry-cli/references/trials.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ Manage product trials
1515

1616
List product trials
1717

18+
**JSON Fields** (use `--json --fields` to select specific fields):
19+
20+
| Field | Type | Description |
21+
|-------|------|-------------|
22+
| `category` | string | Trial category (e.g. seerUsers, seerAutofix) |
23+
| `startDate` | string \| null | Start date (ISO 8601) |
24+
| `endDate` | string \| null | End date (ISO 8601) |
25+
| `reasonCode` | number | Reason code |
26+
| `isStarted` | boolean | Whether the trial has started |
27+
| `lengthDays` | number \| null | Trial duration in days |
28+
1829
### `sentry trial start <name> <org>`
1930

2031
Start a product trial

script/generate-skill.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,22 @@ function generateFullCommandDoc(cmd: CommandInfo): string {
496496
}
497497
}
498498

499+
if (cmd.jsonFields && cmd.jsonFields.length > 0) {
500+
lines.push("");
501+
lines.push(
502+
"**JSON Fields** (use `--json --fields` to select specific fields):"
503+
);
504+
lines.push("");
505+
lines.push("| Field | Type | Description |");
506+
lines.push("|-------|------|-------------|");
507+
for (const field of cmd.jsonFields) {
508+
// Escape pipe characters to avoid breaking the markdown table structure
509+
const safeType = field.type.replaceAll("|", "\\|");
510+
const safeDesc = (field.description ?? "").replaceAll("|", "\\|");
511+
lines.push(`| \`${field.name}\` | ${safeType} | ${safeDesc} |`);
512+
}
513+
}
514+
499515
if (cmd.examples.length > 0) {
500516
lines.push("");
501517
lines.push("**Examples:**");

src/commands/issue/list.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ import {
7979
} from "../../lib/resolve-target.js";
8080
import { getApiBaseUrl } from "../../lib/sentry-client.js";
8181
import { setOrgProjectContext } from "../../lib/telemetry.js";
82-
import type {
83-
ProjectAliasEntry,
84-
SentryIssue,
85-
Writer,
82+
import {
83+
type ProjectAliasEntry,
84+
type SentryIssue,
85+
SentryIssueSchema,
86+
type Writer,
8687
} from "../../types/index.js";
8788

8889
/** Command key for pagination cursor storage */
@@ -1502,6 +1503,7 @@ const jsonTransformIssueList = jsonTransformListResult;
15021503
const issueListOutput: OutputConfig<IssueListResult> = {
15031504
human: formatIssueListHuman,
15041505
jsonTransform: jsonTransformIssueList,
1506+
schema: SentryIssueSchema,
15051507
};
15061508

15071509
// ---------------------------------------------------------------------------

src/commands/log/list.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
warnIfNormalized,
4141
} from "../../lib/trace-target.js";
4242
import { getUpdateNotification } from "../../lib/version-check.js";
43+
import { SentryLogSchema } from "../../types/index.js";
4344

4445
type ListFlags = {
4546
readonly limit: number;
@@ -598,6 +599,7 @@ export const listCommand = buildListCommand(
598599
output: {
599600
human: createLogRenderer,
600601
jsonTransform: jsonTransformLogOutput,
602+
schema: SentryLogSchema,
601603
},
602604
parameters: {
603605
positional: {

0 commit comments

Comments
 (0)