Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions plugins/sentry-cli/skills/sentry-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ sentry org view my-org -w

Work with Sentry projects

#### `sentry project list <target>`
#### `sentry project list <org/project>`

List projects

Expand All @@ -166,7 +166,7 @@ sentry project list <org-slug>
sentry project list --platform javascript
```

#### `sentry project view <target>`
#### `sentry project view <org/project>`

View details of a project

Expand Down Expand Up @@ -195,7 +195,7 @@ sentry project view my-org/frontend -w

Manage Sentry issues

#### `sentry issue list <target>`
#### `sentry issue list <org/project>`

List issues in a project

Expand Down Expand Up @@ -441,7 +441,7 @@ Update the Sentry CLI to the latest version

Work with Sentry repositories

#### `sentry repo list <target>`
#### `sentry repo list <org/project>`

List repositories

Expand All @@ -454,7 +454,7 @@ List repositories

Work with Sentry teams

#### `sentry team list <target>`
#### `sentry team list <org/project>`

List teams

Expand Down Expand Up @@ -482,7 +482,7 @@ sentry team list --json

View Sentry logs

#### `sentry log list <target>`
#### `sentry log list <org/project>`

List logs from a project

Expand Down Expand Up @@ -562,7 +562,7 @@ sentry log list --json | jq '.[] | select(.level == "error")'

View distributed traces

#### `sentry trace list <target>`
#### `sentry trace list <org/project>`

List recent traces in a project

Expand All @@ -585,7 +585,7 @@ View details of a specific trace

List issues in a project

#### `sentry issues <target>`
#### `sentry issues <org/project>`

List issues in a project

Expand All @@ -612,7 +612,7 @@ List organizations

List projects

#### `sentry projects <target>`
#### `sentry projects <org/project>`

List projects

Expand All @@ -626,7 +626,7 @@ List projects

List repositories

#### `sentry repos <target>`
#### `sentry repos <org/project>`

List repositories

Expand All @@ -639,7 +639,7 @@ List repositories

List teams

#### `sentry teams <target>`
#### `sentry teams <org/project>`

List teams

Expand All @@ -652,7 +652,7 @@ List teams

List logs from a project

#### `sentry logs <target>`
#### `sentry logs <org/project>`

List logs from a project

Expand All @@ -666,7 +666,7 @@ List logs from a project

List recent traces in a project

#### `sentry traces <target>`
#### `sentry traces <org/project>`

List recent traces in a project

Expand Down
6 changes: 4 additions & 2 deletions src/commands/issue/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
LIST_BASE_ALIASES,
LIST_JSON_FLAG,
LIST_TARGET_POSITIONAL,
targetPatternExplanation,
} from "../../lib/list-command.js";
import {
dispatchOrgScopedList,
Expand Down Expand Up @@ -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 <org>/<proj> # explicit org and project\n" +
" sentry issue list <org>/ # all projects in org\n" +
" sentry issue list <org>/ # all projects in org (trailing / required)\n" +
" sentry issue list <project> # find project across all orgs\n\n" +
`${targetPatternExplanation()}\n\n` +
"In monorepos with multiple Sentry projects, shows issues from all detected projects.",
},
parameters: {
Expand Down
8 changes: 5 additions & 3 deletions src/commands/log/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 <org>/<proj> # explicit org and project\n" +
" sentry log list <project> # 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" +
Expand All @@ -248,8 +250,8 @@ export const listCommand = buildCommand({
kind: "tuple",
parameters: [
{
placeholder: "target",
brief: "Target: <org>/<project> or <project>",
placeholder: "org/project",
brief: "<org>/<project> or <project> (search)",
parse: String,
optional: true,
},
Expand Down
8 changes: 5 additions & 3 deletions src/commands/project/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import {
LIST_CURSOR_FLAG,
LIST_JSON_FLAG,
LIST_TARGET_POSITIONAL,
targetPatternExplanation,
} from "../../lib/list-command.js";
import {
dispatchOrgScopedList,
Expand Down Expand Up @@ -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 <org>/ # list all projects in org (paginated)\n" +
" sentry project list <org>/ # all projects in org (paginated)\n" +
" sentry project list <org>/<proj> # show specific project\n" +
" sentry project list <project> # find project across all orgs\n\n" +
`${targetPatternExplanation("Cursor pagination (--cursor) requires the <org>/ form.")}\n\n` +
"Pagination:\n" +
" sentry project list <org>/ -c last # continue from last page\n" +
" sentry project list <org>/ -c last # continue from last page\n" +
" sentry project list <org>/ -c <cursor> # resume at specific cursor\n\n" +
"Filtering and output:\n" +
" sentry project list --platform javascript # filter by platform\n" +
Expand Down
8 changes: 5 additions & 3 deletions src/commands/project/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -201,19 +202,20 @@ 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 <org>/<project> # explicit org and project\n" +
" sentry project view <project> # 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: {
positional: {
kind: "tuple",
parameters: [
{
placeholder: "target",
brief: "Target: <org>/<project>, <project>, or omit for auto-detect",
placeholder: "org/project",
brief: "<org>/<project>, <project> (search), or omit for auto-detect",
parse: String,
optional: true,
},
Expand Down
8 changes: 5 additions & 3 deletions src/commands/trace/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -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 <org>/<proj> # explicit org and project\n" +
" sentry trace list <project> # 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" +
Expand All @@ -82,8 +84,8 @@ export const listCommand = buildCommand({
kind: "tuple",
parameters: [
{
placeholder: "target",
brief: "Target: <org>/<project> or <project>",
placeholder: "org/project",
brief: "<org>/<project> or <project> (search)",
parse: String,
optional: true,
},
Expand Down
34 changes: 30 additions & 4 deletions src/lib/list-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 `<org>/`, `<org>/<project>`, or bare `<org>` / `<project>`.
* Accepts `<org>/`, `<org>/<project>`, or bare `<project>` (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: <org>/, <org>/<project>, or <org>",
placeholder: "org/project",
brief: "<org>/ (all projects), <org>/<project>, or <project> (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 <org>/<project> 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 <org>/ form.").
*/
export function targetPatternExplanation(cursorNote?: string): string {
const base =
"The trailing slash on <org>/ 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.
Expand Down
11 changes: 8 additions & 3 deletions src/lib/org-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -739,10 +739,15 @@ export async function dispatchOrgScopedList<TEntity, TWithOrg>(

// 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} <org>/). ` +
`Use '${config.commandPrefix} <org>/' for paginated results.`,
"The --cursor flag requires the <org>/ pattern " +
`(e.g., ${config.commandPrefix} my-org/).` +
hint,
"cursor"
);
}
Expand Down
2 changes: 1 addition & 1 deletion test/lib/list-command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
Expand Down
2 changes: 1 addition & 1 deletion test/lib/org-list.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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("<org>/");
}
});

Expand Down
Loading