Skip to content

Commit 45903a8

Browse files
feat: add --fields flag for context-window-friendly JSON output (#373)
## Summary Add a `--fields` flag to all 14 commands that support `--json` output, allowing agents (and humans) to request only specific fields. This reduces token consumption and keeps agent context windows focused. Fixes #347 ## Motivation From [You Need to Rewrite Your CLI for AI Agents](https://justin.poehnelt.com/posts/rewrite-your-cli-for-ai-agents/): > "APIs return massive blobs. A single Gmail message can consume a meaningful fraction of an agent's context window. Humans don't care — humans scroll. **Agents pay per token and lose reasoning capacity with every irrelevant field.**" A full `sentry issue view --json` dumps the entire issue object, latest event, and span tree. An agent that just needs `id`, `title`, and `status` is forced to ingest thousands of tokens of irrelevant data. ## Usage ```bash # Select specific top-level fields sentry issue list --json --fields id,shortId,title,status # Dot-notation for nested fields sentry issue view --json --fields id,title,metadata.value # Works with all --json commands sentry event view --json --fields eventID,dateCreated,contexts.trace sentry project list --json --fields slug,platform ``` ## Design **Option A from the issue**: Simple `--fields` flag with comma-separated field paths. Covers the 90% case for agents, trivial to implement, no external dependencies. ### Core implementation (`src/lib/formatters/json.ts`) - `filterFields(data, fields)` — picks specified fields from objects/arrays, supports dot-notation for nested access, silently skips missing fields - `parseFieldsList(input)` — parses comma-separated input with dedup, whitespace trimming, empty segment filtering - `writeJson(stream, data, fields?)` — optional `fields` param filters output before serialization ### Shared flag (`src/lib/list-command.ts`) - `FIELDS_FLAG` — Stricli flag constant shared by all commands with `--json` ### Commands updated (14 total) `auth whoami`, `event view`, `issue explain`, `issue list`, `issue plan`, `issue view`, `log list`, `log view`, `org list`, `project create`, `project list`, `project view`, `trace list`, `trace view` ## Edge cases - Empty fields array → outputs full object (no filtering) - Missing fields → silently ignored (no errors) - Dot-notation with null/primitive intermediaries → skipped - Array data → each element filtered independently - Primitive data (string, number) → passed through unchanged - Keys containing dots → inherent dot-notation ambiguity (documented limitation) - `--fields` without `--json` → silently ignored ## Testing - **12 property-based tests** — identity, subset invariant, idempotency, array mapping, deduplication, whitespace tolerance, round-trip - **36 unit tests** — specific edge cases, dot-notation, integration with writeJson - All 3088 existing tests continue to pass (1 pre-existing failure in log formatter) --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 0f00d4d commit 45903a8

File tree

28 files changed

+1665
-241
lines changed

28 files changed

+1665
-241
lines changed

AGENTS.md

Lines changed: 20 additions & 41 deletions
Large diffs are not rendered by default.

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

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ sentry auth logout
7474
Refresh your authentication token
7575

7676
**Flags:**
77-
- `--json - Output result as JSON`
7877
- `--force - Force refresh even if token is still valid`
78+
- `--json - Output as JSON`
79+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
7980

8081
**Examples:**
8182

@@ -106,8 +107,9 @@ Print the stored authentication token
106107
Show the currently authenticated user
107108

108109
**Flags:**
109-
- `--json - Output as JSON`
110110
- `-f, --fresh - Bypass cache and fetch fresh data`
111+
- `--json - Output as JSON`
112+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
111113

112114
### Org
113115

@@ -119,8 +121,9 @@ List organizations
119121

120122
**Flags:**
121123
- `-n, --limit <value> - Maximum number of organizations to list - (default: "30")`
122-
- `--json - Output JSON`
123124
- `-f, --fresh - Bypass cache and fetch fresh data`
125+
- `--json - Output as JSON`
126+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
124127

125128
**Examples:**
126129

@@ -135,9 +138,10 @@ sentry org list --json
135138
View details of an organization
136139

137140
**Flags:**
138-
- `--json - Output as JSON`
139141
- `-w, --web - Open in browser`
140142
- `-f, --fresh - Bypass cache and fetch fresh data`
143+
- `--json - Output as JSON`
144+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
141145

142146
**Examples:**
143147

@@ -160,17 +164,19 @@ Create a new project
160164
**Flags:**
161165
- `-t, --team <value> - Team to create the project under`
162166
- `--json - Output as JSON`
167+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
163168

164169
#### `sentry project list <org/project>`
165170

166171
List projects
167172

168173
**Flags:**
169174
- `-n, --limit <value> - Maximum number of projects to list - (default: "30")`
170-
- `--json - Output JSON`
171175
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
172176
- `-p, --platform <value> - Filter by platform (e.g., javascript, python)`
173177
- `-f, --fresh - Bypass cache and fetch fresh data`
178+
- `--json - Output as JSON`
179+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
174180

175181
**Examples:**
176182

@@ -190,9 +196,10 @@ sentry project list --platform javascript
190196
View details of a project
191197

192198
**Flags:**
193-
- `--json - Output as JSON`
194199
- `-w, --web - Open in browser`
195200
- `-f, --fresh - Bypass cache and fetch fresh data`
201+
- `--json - Output as JSON`
202+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
196203

197204
**Examples:**
198205

@@ -224,10 +231,11 @@ List issues in a project
224231
- `-n, --limit <value> - Maximum number of issues to list - (default: "25")`
225232
- `-s, --sort <value> - Sort by: date, new, freq, user - (default: "date")`
226233
- `-t, --period <value> - Time period for issue activity (e.g. 24h, 14d, 90d) - (default: "90d")`
227-
- `--json - Output JSON`
228234
- `-c, --cursor <value> - Pagination cursor for <org>/ or multi-target modes (use "last" to continue)`
229235
- `-f, --fresh - Bypass cache and fetch fresh data`
230236
- `--compact - Single-line rows for compact output`
237+
- `--json - Output as JSON`
238+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
231239

232240
**Examples:**
233241

@@ -270,9 +278,10 @@ sentry issue list my-org/frontend --query "is:unresolved TypeError"
270278
Analyze an issue's root cause using Seer AI
271279

272280
**Flags:**
273-
- `--json - Output as JSON`
274281
- `--force - Force new analysis even if one exists`
275282
- `-f, --fresh - Bypass cache and fetch fresh data`
283+
- `--json - Output as JSON`
284+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
276285

277286
**Examples:**
278287

@@ -298,9 +307,10 @@ Generate a solution plan using Seer AI
298307

299308
**Flags:**
300309
- `--cause <value> - Root cause ID to plan (required if multiple causes exist)`
301-
- `--json - Output as JSON`
302310
- `--force - Force new plan even if one exists`
303311
- `-f, --fresh - Bypass cache and fetch fresh data`
312+
- `--json - Output as JSON`
313+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
304314

305315
**Examples:**
306316

@@ -325,10 +335,11 @@ sentry issue plan myproject-G --cause 0
325335
View details of a specific issue
326336

327337
**Flags:**
328-
- `--json - Output as JSON`
329338
- `-w, --web - Open in browser`
330339
- `--spans <value> - Span tree depth limit (number, "all" for unlimited, "no" to disable) - (default: "3")`
331340
- `-f, --fresh - Bypass cache and fetch fresh data`
341+
- `--json - Output as JSON`
342+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
332343

333344
**Examples:**
334345

@@ -353,10 +364,11 @@ View Sentry events
353364
View details of a specific event
354365

355366
**Flags:**
356-
- `--json - Output as JSON`
357367
- `-w, --web - Open in browser`
358368
- `--spans <value> - Span tree depth limit (number, "all" for unlimited, "no" to disable) - (default: "3")`
359369
- `-f, --fresh - Bypass cache and fetch fresh data`
370+
- `--json - Output as JSON`
371+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
360372

361373
**Examples:**
362374

@@ -477,9 +489,10 @@ List repositories
477489

478490
**Flags:**
479491
- `-n, --limit <value> - Maximum number of repositories to list - (default: "30")`
480-
- `--json - Output JSON`
481492
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
482493
- `-f, --fresh - Bypass cache and fetch fresh data`
494+
- `--json - Output as JSON`
495+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
483496

484497
### Team
485498

@@ -491,9 +504,10 @@ List teams
491504

492505
**Flags:**
493506
- `-n, --limit <value> - Maximum number of teams to list - (default: "30")`
494-
- `--json - Output JSON`
495507
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
496508
- `-f, --fresh - Bypass cache and fetch fresh data`
509+
- `--json - Output as JSON`
510+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
497511

498512
**Examples:**
499513

@@ -523,8 +537,9 @@ List logs from a project
523537
- `-q, --query <value> - Filter query (Sentry search syntax)`
524538
- `-f, --follow <value> - Stream logs (optionally specify poll interval in seconds)`
525539
- `--trace <value> - Filter logs by trace ID (32-character hex string)`
526-
- `--json - Output as JSON`
527540
- `--fresh - Bypass cache and fetch fresh data`
541+
- `--json - Output as JSON`
542+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
528543

529544
**Examples:**
530545

@@ -568,9 +583,10 @@ sentry log list my-org/backend -f -q 'level:error'
568583
View details of one or more log entries
569584

570585
**Flags:**
571-
- `--json - Output as JSON`
572586
- `-w, --web - Open in browser`
573587
- `-f, --fresh - Bypass cache and fetch fresh data`
588+
- `--json - Output as JSON`
589+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
574590

575591
**Examples:**
576592

@@ -606,30 +622,33 @@ List recent traces in a project
606622
- `-q, --query <value> - Search query (Sentry search syntax)`
607623
- `-s, --sort <value> - Sort by: date, duration - (default: "date")`
608624
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
609-
- `--json - Output as JSON`
610625
- `-f, --fresh - Bypass cache and fetch fresh data`
626+
- `--json - Output as JSON`
627+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
611628

612629
#### `sentry trace view <args...>`
613630

614631
View details of a specific trace
615632

616633
**Flags:**
617-
- `--json - Output as JSON`
618634
- `-w, --web - Open in browser`
619635
- `--spans <value> - Span tree depth limit (number, "all" for unlimited, "no" to disable) - (default: "3")`
620636
- `-f, --fresh - Bypass cache and fetch fresh data`
637+
- `--json - Output as JSON`
638+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
621639

622640
#### `sentry trace logs <args...>`
623641

624642
View logs associated with a trace
625643

626644
**Flags:**
627-
- `--json - Output as JSON`
628645
- `-w, --web - Open trace in browser`
629646
- `-t, --period <value> - Time period to search (e.g., "14d", "7d", "24h"). Default: 14d - (default: "14d")`
630647
- `-n, --limit <value> - Number of log entries (1-1000) - (default: "100")`
631648
- `-q, --query <value> - Additional filter query (Sentry search syntax)`
632649
- `-f, --fresh - Bypass cache and fetch fresh data`
650+
- `--json - Output as JSON`
651+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
633652

634653
### Init
635654

@@ -658,10 +677,11 @@ List issues in a project
658677
- `-n, --limit <value> - Maximum number of issues to list - (default: "25")`
659678
- `-s, --sort <value> - Sort by: date, new, freq, user - (default: "date")`
660679
- `-t, --period <value> - Time period for issue activity (e.g. 24h, 14d, 90d) - (default: "90d")`
661-
- `--json - Output JSON`
662680
- `-c, --cursor <value> - Pagination cursor for <org>/ or multi-target modes (use "last" to continue)`
663681
- `-f, --fresh - Bypass cache and fetch fresh data`
664682
- `--compact - Single-line rows for compact output`
683+
- `--json - Output as JSON`
684+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
665685

666686
### Orgs
667687

@@ -673,8 +693,9 @@ List organizations
673693

674694
**Flags:**
675695
- `-n, --limit <value> - Maximum number of organizations to list - (default: "30")`
676-
- `--json - Output JSON`
677696
- `-f, --fresh - Bypass cache and fetch fresh data`
697+
- `--json - Output as JSON`
698+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
678699

679700
### Projects
680701

@@ -686,10 +707,11 @@ List projects
686707

687708
**Flags:**
688709
- `-n, --limit <value> - Maximum number of projects to list - (default: "30")`
689-
- `--json - Output JSON`
690710
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
691711
- `-p, --platform <value> - Filter by platform (e.g., javascript, python)`
692712
- `-f, --fresh - Bypass cache and fetch fresh data`
713+
- `--json - Output as JSON`
714+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
693715

694716
### Repos
695717

@@ -701,9 +723,10 @@ List repositories
701723

702724
**Flags:**
703725
- `-n, --limit <value> - Maximum number of repositories to list - (default: "30")`
704-
- `--json - Output JSON`
705726
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
706727
- `-f, --fresh - Bypass cache and fetch fresh data`
728+
- `--json - Output as JSON`
729+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
707730

708731
### Teams
709732

@@ -715,9 +738,10 @@ List teams
715738

716739
**Flags:**
717740
- `-n, --limit <value> - Maximum number of teams to list - (default: "30")`
718-
- `--json - Output JSON`
719741
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
720742
- `-f, --fresh - Bypass cache and fetch fresh data`
743+
- `--json - Output as JSON`
744+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
721745

722746
### Logs
723747

@@ -732,8 +756,9 @@ List logs from a project
732756
- `-q, --query <value> - Filter query (Sentry search syntax)`
733757
- `-f, --follow <value> - Stream logs (optionally specify poll interval in seconds)`
734758
- `--trace <value> - Filter logs by trace ID (32-character hex string)`
735-
- `--json - Output as JSON`
736759
- `--fresh - Bypass cache and fetch fresh data`
760+
- `--json - Output as JSON`
761+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
737762

738763
### Traces
739764

@@ -748,8 +773,9 @@ List recent traces in a project
748773
- `-q, --query <value> - Search query (Sentry search syntax)`
749774
- `-s, --sort <value> - Sort by: date, duration - (default: "date")`
750775
- `-c, --cursor <value> - Pagination cursor (use "last" to continue from previous page)`
751-
- `--json - Output as JSON`
752776
- `-f, --fresh - Bypass cache and fetch fresh data`
777+
- `--json - Output as JSON`
778+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
753779

754780
### Whoami
755781

@@ -760,8 +786,9 @@ Show the currently authenticated user
760786
Show the currently authenticated user
761787

762788
**Flags:**
763-
- `--json - Output as JSON`
764789
- `-f, --fresh - Bypass cache and fetch fresh data`
790+
- `--json - Output as JSON`
791+
- `--fields <value> - Comma-separated fields to include in JSON output (dot.notation supported)`
765792

766793
## Global Options
767794

src/commands/auth/refresh.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ import {
1515
import { AuthError } from "../../lib/errors.js";
1616
import { success } from "../../lib/formatters/colors.js";
1717
import { formatDuration } from "../../lib/formatters/human.js";
18+
import { writeJson } from "../../lib/formatters/index.js";
1819

1920
type RefreshFlags = {
2021
readonly json: boolean;
2122
readonly force: boolean;
23+
readonly fields?: string[];
2224
};
2325

2426
type RefreshOutput = {
@@ -50,13 +52,9 @@ Examples:
5052
{"success":true,"refreshed":true,"expiresIn":3600,"expiresAt":"..."}
5153
`.trim(),
5254
},
55+
output: "json",
5356
parameters: {
5457
flags: {
55-
json: {
56-
kind: "boolean",
57-
brief: "Output result as JSON",
58-
default: false,
59-
},
6058
force: {
6159
kind: "boolean",
6260
brief: "Force refresh even if token is still valid",
@@ -103,7 +101,7 @@ Examples:
103101
};
104102

105103
if (flags.json) {
106-
stdout.write(`${JSON.stringify(output)}\n`);
104+
writeJson(stdout, output, flags.fields);
107105
} else if (result.refreshed) {
108106
stdout.write(
109107
`${success("✓")} Token refreshed successfully. Expires in ${formatDuration(result.expiresIn ?? 0)}.\n`

0 commit comments

Comments
 (0)