From 5584a1d7e97376ff41d9cc6487099be6d602597c Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Mon, 23 Feb 2026 10:52:23 +0000 Subject: [PATCH 1/2] fix(help): document target patterns and trailing-slash significance (#267) Renames the positional placeholder from `` to `` so the usage line is self-documenting. Adds a prose explanation of trailing-slash semantics to the fullDescription of every command that uses parseOrgProjectArg, and improves the --cursor rejection error in dispatchOrgScopedList to include a contextual suggestion when a bare slug was given. --- src/commands/issue/list.ts | 6 ++++-- src/commands/log/list.ts | 8 +++++--- src/commands/project/list.ts | 8 +++++--- src/commands/project/view.ts | 8 +++++--- src/commands/trace/list.ts | 8 +++++--- src/lib/list-command.ts | 34 ++++++++++++++++++++++++++++++---- src/lib/org-list.ts | 11 ++++++++--- test/lib/list-command.test.ts | 2 +- test/lib/org-list.test.ts | 2 +- 9 files changed, 64 insertions(+), 23 deletions(-) diff --git a/src/commands/issue/list.ts b/src/commands/issue/list.ts index 858bca16a6..6ef72429bc 100644 --- a/src/commands/issue/list.ts +++ b/src/commands/issue/list.ts @@ -40,6 +40,7 @@ import { LIST_BASE_ALIASES, LIST_JSON_FLAG, LIST_TARGET_POSITIONAL, + targetPatternExplanation, } from "../../lib/list-command.js"; import { dispatchOrgScopedList, @@ -657,11 +658,12 @@ export const listCommand = buildCommand({ brief: "List issues in a project", fullDescription: "List issues from Sentry projects.\n\n" + - "Target specification:\n" + + "Target patterns:\n" + " sentry issue list # auto-detect from DSN or config\n" + " sentry issue list / # explicit org and project\n" + - " sentry issue list / # all projects in org\n" + + " sentry issue list / # all projects in org (trailing / required)\n" + " sentry issue list # find project across all orgs\n\n" + + `${targetPatternExplanation()}\n\n` + "In monorepos with multiple Sentry projects, shows issues from all detected projects.", }, parameters: { diff --git a/src/commands/log/list.ts b/src/commands/log/list.ts index 0aacec2c8c..42743347f0 100644 --- a/src/commands/log/list.ts +++ b/src/commands/log/list.ts @@ -18,6 +18,7 @@ import { writeFooter, writeJson, } from "../../lib/formatters/index.js"; +import { TARGET_PATTERN_NOTE } from "../../lib/list-command.js"; import { resolveOrgProjectFromArg } from "../../lib/resolve-target.js"; import { getUpdateNotification } from "../../lib/version-check.js"; import type { SentryLog, Writer } from "../../types/index.js"; @@ -232,10 +233,11 @@ export const listCommand = buildCommand({ brief: "List logs from a project", fullDescription: "List and stream logs from Sentry projects.\n\n" + - "Target specification:\n" + + "Target patterns:\n" + " sentry log list # auto-detect from DSN or config\n" + " sentry log list / # explicit org and project\n" + " sentry log list # find project across all orgs\n\n" + + `${TARGET_PATTERN_NOTE}\n\n` + "Examples:\n" + " sentry log list # List last 100 logs\n" + " sentry log list -f # Stream logs (2s poll interval)\n" + @@ -248,8 +250,8 @@ export const listCommand = buildCommand({ kind: "tuple", parameters: [ { - placeholder: "target", - brief: "Target: / or ", + placeholder: "org/project", + brief: "/ or (search)", parse: String, optional: true, }, diff --git a/src/commands/project/list.ts b/src/commands/project/list.ts index 4223a3465e..78d3ef85ba 100644 --- a/src/commands/project/list.ts +++ b/src/commands/project/list.ts @@ -44,6 +44,7 @@ import { LIST_CURSOR_FLAG, LIST_JSON_FLAG, LIST_TARGET_POSITIONAL, + targetPatternExplanation, } from "../../lib/list-command.js"; import { dispatchOrgScopedList, @@ -607,13 +608,14 @@ export const listCommand = buildCommand({ brief: "List projects", fullDescription: "List projects in an organization.\n\n" + - "Target specification:\n" + + "Target patterns:\n" + " sentry project list # auto-detect from DSN or config\n" + - " sentry project list / # list all projects in org (paginated)\n" + + " sentry project list / # all projects in org (paginated)\n" + " sentry project list / # show specific project\n" + " sentry project list # find project across all orgs\n\n" + + `${targetPatternExplanation("Cursor pagination (--cursor) requires the / form.")}\n\n` + "Pagination:\n" + - " sentry project list / -c last # continue from last page\n" + + " sentry project list / -c last # continue from last page\n" + " sentry project list / -c # resume at specific cursor\n\n" + "Filtering and output:\n" + " sentry project list --platform javascript # filter by platform\n" + diff --git a/src/commands/project/view.ts b/src/commands/project/view.ts index 8d24db38f8..f350d062d2 100644 --- a/src/commands/project/view.ts +++ b/src/commands/project/view.ts @@ -20,6 +20,7 @@ import { writeJson, writeOutput, } from "../../lib/formatters/index.js"; +import { TARGET_PATTERN_NOTE } from "../../lib/list-command.js"; import { type ResolvedTarget, resolveAllTargets, @@ -201,10 +202,11 @@ export const viewCommand = buildCommand({ brief: "View details of a project", fullDescription: "View detailed information about Sentry projects.\n\n" + - "Target specification:\n" + + "Target patterns:\n" + " sentry project view # auto-detect from DSN or config\n" + " sentry project view / # explicit org and project\n" + " sentry project view # find project across all orgs\n\n" + + `${TARGET_PATTERN_NOTE}\n\n` + "In monorepos with multiple Sentry projects, shows details for all detected projects.", }, parameters: { @@ -212,8 +214,8 @@ export const viewCommand = buildCommand({ kind: "tuple", parameters: [ { - placeholder: "target", - brief: "Target: /, , or omit for auto-detect", + placeholder: "org/project", + brief: "/, (search), or omit for auto-detect", parse: String, optional: true, }, diff --git a/src/commands/trace/list.ts b/src/commands/trace/list.ts index d3cf2b66c6..65fea21e2e 100644 --- a/src/commands/trace/list.ts +++ b/src/commands/trace/list.ts @@ -14,6 +14,7 @@ import { writeFooter, writeJson, } from "../../lib/formatters/index.js"; +import { TARGET_PATTERN_NOTE } from "../../lib/list-command.js"; import { resolveOrgProjectFromArg } from "../../lib/resolve-target.js"; type ListFlags = { @@ -67,10 +68,11 @@ export const listCommand = buildCommand({ brief: "List recent traces in a project", fullDescription: "List recent traces from Sentry projects.\n\n" + - "Target specification:\n" + + "Target patterns:\n" + " sentry trace list # auto-detect from DSN or config\n" + " sentry trace list / # explicit org and project\n" + " sentry trace list # find project across all orgs\n\n" + + `${TARGET_PATTERN_NOTE}\n\n` + "Examples:\n" + " sentry trace list # List last 10 traces\n" + " sentry trace list --limit 50 # Show more traces\n" + @@ -82,8 +84,8 @@ export const listCommand = buildCommand({ kind: "tuple", parameters: [ { - placeholder: "target", - brief: "Target: / or ", + placeholder: "org/project", + brief: "/ or (search)", parse: String, optional: true, }, diff --git a/src/lib/list-command.ts b/src/lib/list-command.ts index dbc06d12c6..7527480585 100644 --- a/src/lib/list-command.ts +++ b/src/lib/list-command.ts @@ -24,23 +24,49 @@ import { dispatchOrgScopedList, type OrgListConfig } from "./org-list.js"; // --------------------------------------------------------------------------- /** - * Positional `target` parameter shared by all list commands. + * Positional `org/project` parameter shared by all list commands. * - * Accepts `/`, `/`, or bare `` / ``. + * Accepts `/`, `/`, or bare `` (search). * Marked optional so the command falls back to auto-detection when omitted. */ export const LIST_TARGET_POSITIONAL = { kind: "tuple" as const, parameters: [ { - placeholder: "target", - brief: "Target: /, /, or ", + placeholder: "org/project", + brief: "/ (all projects), /, or (search)", parse: String, optional: true as const, }, ], }; +/** + * Short note for commands that accept a bare project name but do not support + * org-all mode (e.g. trace list, log list, project view). + * + * Explains that a bare name triggers project-search, not org-scoped listing. + */ +export const TARGET_PATTERN_NOTE = + "A bare name (no slash) is treated as a project search. " + + "Use / for an explicit target."; + +/** + * Full explanation of trailing-slash semantics for commands that support all + * four target modes including org-all (e.g. issue list, project list). + * + * @param cursorNote - Optional sentence appended when the command supports + * cursor pagination (e.g. "Cursor pagination (--cursor) requires the / form."). + */ +export function targetPatternExplanation(cursorNote?: string): string { + const base = + "The trailing slash on / is significant — without it, the argument " + + "is treated as a project name search (e.g., 'sentry' searches for a " + + "project named 'sentry', while 'sentry/' lists all projects in the " + + "'sentry' org)."; + return cursorNote ? `${base} ${cursorNote}` : base; +} + /** * The `--json` flag shared by all list commands. * Outputs machine-readable JSON instead of a human-readable table. diff --git a/src/lib/org-list.ts b/src/lib/org-list.ts index 316e8a9b35..2c8b50f03d 100644 --- a/src/lib/org-list.ts +++ b/src/lib/org-list.ts @@ -739,10 +739,15 @@ export async function dispatchOrgScopedList( // Cursor pagination is only supported in org-all mode if (flags.cursor && parsed.type !== "org-all") { + const hint = + parsed.type === "project-search" + ? `\n\nDid you mean '${config.commandPrefix} ${parsed.projectSlug}/'? ` + + `A bare name searches for a project — add a trailing slash to list an org's ${config.entityPlural}.` + : ""; throw new ValidationError( - `The --cursor flag is only supported when listing ${config.entityPlural} for a specific organization ` + - `(e.g., ${config.commandPrefix} /). ` + - `Use '${config.commandPrefix} /' for paginated results.`, + "The --cursor flag requires the / pattern " + + `(e.g., ${config.commandPrefix} my-org/).` + + hint, "cursor" ); } diff --git a/test/lib/list-command.test.ts b/test/lib/list-command.test.ts index 6bd4f44526..9d00121495 100644 --- a/test/lib/list-command.test.ts +++ b/test/lib/list-command.test.ts @@ -29,7 +29,7 @@ describe("LIST_TARGET_POSITIONAL", () => { expect(LIST_TARGET_POSITIONAL.kind).toBe("tuple"); expect(LIST_TARGET_POSITIONAL.parameters).toHaveLength(1); const param = LIST_TARGET_POSITIONAL.parameters[0]; - expect(param.placeholder).toBe("target"); + expect(param.placeholder).toBe("org/project"); expect(param.optional).toBe(true); expect(param.parse).toBe(String); }); diff --git a/test/lib/org-list.test.ts b/test/lib/org-list.test.ts index e2cb67295a..112d386fb9 100644 --- a/test/lib/org-list.test.ts +++ b/test/lib/org-list.test.ts @@ -686,7 +686,7 @@ describe("dispatchOrgScopedList", () => { expect.unreachable("should have thrown"); } catch (e) { expect(e).toBeInstanceOf(ValidationError); - expect((e as ValidationError).message).toContain("widgets"); + expect((e as ValidationError).message).toContain("/"); } }); From ead17b0c73260ede2209dbf043f4c1e4ecf13d88 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 11:10:22 +0000 Subject: [PATCH 2/2] chore: regenerate SKILL.md --- plugins/sentry-cli/skills/sentry-cli/SKILL.md | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/sentry-cli/skills/sentry-cli/SKILL.md b/plugins/sentry-cli/skills/sentry-cli/SKILL.md index fecf72ae55..829cf250bd 100644 --- a/plugins/sentry-cli/skills/sentry-cli/SKILL.md +++ b/plugins/sentry-cli/skills/sentry-cli/SKILL.md @@ -143,7 +143,7 @@ sentry org view my-org -w Work with Sentry projects -#### `sentry project list ` +#### `sentry project list ` List projects @@ -166,7 +166,7 @@ sentry project list sentry project list --platform javascript ``` -#### `sentry project view ` +#### `sentry project view ` View details of a project @@ -195,7 +195,7 @@ sentry project view my-org/frontend -w Manage Sentry issues -#### `sentry issue list ` +#### `sentry issue list ` List issues in a project @@ -441,7 +441,7 @@ Update the Sentry CLI to the latest version Work with Sentry repositories -#### `sentry repo list ` +#### `sentry repo list ` List repositories @@ -454,7 +454,7 @@ List repositories Work with Sentry teams -#### `sentry team list ` +#### `sentry team list ` List teams @@ -482,7 +482,7 @@ sentry team list --json View Sentry logs -#### `sentry log list ` +#### `sentry log list ` List logs from a project @@ -562,7 +562,7 @@ sentry log list --json | jq '.[] | select(.level == "error")' View distributed traces -#### `sentry trace list ` +#### `sentry trace list ` List recent traces in a project @@ -585,7 +585,7 @@ View details of a specific trace List issues in a project -#### `sentry issues ` +#### `sentry issues ` List issues in a project @@ -612,7 +612,7 @@ List organizations List projects -#### `sentry projects ` +#### `sentry projects ` List projects @@ -626,7 +626,7 @@ List projects List repositories -#### `sentry repos ` +#### `sentry repos ` List repositories @@ -639,7 +639,7 @@ List repositories List teams -#### `sentry teams ` +#### `sentry teams ` List teams @@ -652,7 +652,7 @@ List teams List logs from a project -#### `sentry logs ` +#### `sentry logs ` List logs from a project @@ -666,7 +666,7 @@ List logs from a project List recent traces in a project -#### `sentry traces ` +#### `sentry traces ` List recent traces in a project