Skip to content
Open
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
4 changes: 2 additions & 2 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ Get the client ID from your Sentry OAuth application settings.
## Running Locally

```bash
bun run --env-file=.env.local src/bin.ts auth login
bun run --env-file=.env.local cli auth login
```

## Testing the Device Flow

1. Run the CLI login command:

```bash
bun run --env-file=.env.local src/bin.ts auth login
bun run --env-file=.env.local cli auth login
```

2. You'll see output like:
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ bun install

```bash
# Run CLI in development mode
bun run dev --help
bun run cli --help

# With environment variables
bun run --env-file=.env.local src/bin.ts --help
bun run --env-file=.env.local cli --help
```

### Scripts
Expand Down
6 changes: 3 additions & 3 deletions docs/src/content/docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ cd cli
bun install

# Run CLI in development mode
bun run --env-file=.env.local src/bin.ts --help
bun run --env-file=.env.local cli --help

# Run tests
bun test
Expand Down Expand Up @@ -53,14 +53,14 @@ cli/
│ ├── commands/ # CLI commands
│ │ ├── auth/ # login, logout, refresh, status, token, whoami
│ │ ├── cli/ # defaults, feedback, fix, setup, upgrade
│ │ ├── dashboard/ # list, view, create, add, edit, delete
│ │ ├── dashboard/ # list, view, create, widget add, widget edit, widget delete
│ │ ├── event/ # view, list
│ │ ├── issue/ # list, events, explain, plan, view, resolve, unresolve, archive, merge
│ │ ├── log/ # list, view
│ │ ├── org/ # list, view
│ │ ├── project/ # create, delete, list, view
│ │ ├── release/ # list, view, create, finalize, delete, deploy, deploys, set-commits, propose-version
│ │ ├── replay/ # list, view
│ │ ├── replay/ # event list, list, summarize, view
│ │ ├── repo/ # list
│ │ ├── sourcemap/ # inject, upload
│ │ ├── span/ # list, view
Expand Down
32 changes: 31 additions & 1 deletion docs/src/fragments/commands/replay.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
sentry replay list my-org/frontend

# Search across all projects in an org
sentry replay list my-org/ --query "environment:production"
sentry replay list my-org/ --search "environment:production"

# Change the time window and sort
sentry replay list my-org/frontend --period 24h --sort errors

# Find recent sessions with replay search syntax
sentry replay list my-org/frontend \
--search "url:*signup* count_errors:>0" --json

# Paginate through results
sentry replay list my-org/frontend -c next
sentry replay list my-org/frontend -c prev
Expand All @@ -36,3 +40,29 @@ sentry replay view my-org/frontend/346789a703f6454384f1de473b8b9fcc
# Open a replay in the browser
sentry replay view my-org/346789a703f6454384f1de473b8b9fcc --web
```

### Summarize behavior

```bash
# Summarize route flow, event counts, timings, and friction signals
sentry replay summarize my-org/346789a703f6454384f1de473b8b9fcc --json

# Focus the summary on a particular route path
sentry replay summarize my-org/346789a703f6454384f1de473b8b9fcc \
--path /signup --json
```

### Inspect replay events

```bash
# List normalized replay events for agent-readable inspection
sentry replay events my-org/346789a703f6454384f1de473b8b9fcc --json

# Focus on user actions and failures on a page
sentry replay events my-org/346789a703f6454384f1de473b8b9fcc \
/signup --kind click,network,console,error --json

# Pull an evidence window around a timestamp
sentry replay events my-org/346789a703f6454384f1de473b8b9fcc \
--around 01:23 --json
```
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"@sentry/core@10.50.0": "patches/@sentry%2Fcore@10.50.0.patch"
},
"scripts": {
"cli": "bun run src/bin.ts",
"dev": "bun run generate:schema && bun run generate:docs && bun run generate:sdk && bun run src/bin.ts",
"build": "bun run generate:schema && bun run generate:docs && bun run generate:sdk && bun run script/build.ts --single",
"build:all": "bun run generate:schema && bun run generate:docs && bun run generate:sdk && bun run script/build.ts",
Expand Down
2 changes: 2 additions & 0 deletions plugins/sentry-cli/skills/sentry-cli/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,9 @@ Manage Sentry dashboards

Search and inspect Session Replays

- `sentry replay event list <replay-target...>` — List normalized events from a Session Replay
- `sentry replay list <org/project>` — List recent Session Replays
- `sentry replay summarize <replay-id-or-url...>` — Summarize Session Replay behavior
- `sentry replay view <replay-id-or-url...>` — View a Session Replay

→ Full flags and examples: `references/replay.md`
Expand Down
90 changes: 87 additions & 3 deletions plugins/sentry-cli/skills/sentry-cli/references/replay.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,51 @@ requires:

Search and inspect Session Replays

### `sentry replay event list <replay-target...>`

List normalized events from a Session Replay

**Flags:**
- `-k, --kind <value>... - Event kind filter (navigation, click, tap, input, focus, blur, scroll, viewport, mutation, dom-snapshot, breadcrumb, network, console, error, span, web-vital, memory, video, mobile, unknown)`
- `--path <value> - Filter events by parsed URL pathname`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can make this an optional positional argument instead as it looks quite common and looks like a natural sub-section?

- `-q, --search <value> - Filter events by text in labels, messages, URLs, selectors, or data`
- `--around <value> - Show an evidence window around this replay offset`
- `-n, --limit <value> - Number of events (1-1000) - (default: "200")`
- `--raw - Include raw source frame payloads in JSON output`
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`

**JSON Fields** (use `--json --fields` to select specific fields):

| Field | Type | Description |
|-------|------|-------------|
| `replayId` | string | Replay ID |
| `segmentIndex` | number | Zero-based recording segment index |
| `frameIndex` | number | Zero-based frame index within segment |
| `offsetMs` | number \| null | Milliseconds from replay start to the event |
| `timestamp` | string \| null | Event timestamp as ISO 8601 when available |
| `kind` | string | Normalized event kind |
| `category` | string | Broad event category |
| `label` | string \| null | Short event label |
| `message` | string \| null | Message or summary |
| `url` | string \| null | Current or target URL |
| `urlPath` | string \| null | Parsed URL pathname when available |
| `urlQuery` | string \| null | Parsed URL query string when available |
| `selector` | string \| null | CSS selector or target selector when available |
| `nodeId` | unknown \| null | rrweb node ID when available |
| `rawType` | string \| null | Source frame type |
| `rawSource` | string \| null | Source frame subtype |
| `data` | unknown | Kind-specific normalized fields |
| `raw` | unknown | Raw source frame, only present when requested |

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

List recent Session Replays

**Flags:**
- `-n, --limit <value> - Number of replays (1-1000) - (default: "25")`
- `-q, --query <value> - Search query (Sentry replay search syntax)`
- `-q, --search <value> - Search query (Sentry replay search syntax)`
- `-e, --environment <value>... - Filter by environment (repeatable, comma-separated)`
- `-s, --sort <value> - Sort by: date, oldest, duration, errors, activity, or a raw replay sort field - (default: "date")`
- `-s, --sort <value> - Sort by: date, oldest, duration, errors, warnings, rage, dead, activity, or a raw replay sort field - (default: "date")`
- `-t, --period <value> - Time range: "7d", "2026-04-01..2026-05-01", ">=2026-04-01" - (default: "7d")`
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`
- `-c, --cursor <value> - Navigate pages: "next", "prev", "first" (or raw cursor string)`
Expand Down Expand Up @@ -67,11 +103,15 @@ List recent Session Replays
sentry replay list my-org/frontend

# Search across all projects in an org
sentry replay list my-org/ --query "environment:production"
sentry replay list my-org/ --search "environment:production"

# Change the time window and sort
sentry replay list my-org/frontend --period 24h --sort errors

# Find recent sessions with replay search syntax
sentry replay list my-org/frontend \
--search "url:*signup* count_errors:>0" --json

# Paginate through results
sentry replay list my-org/frontend -c next
sentry replay list my-org/frontend -c prev
Expand All @@ -80,6 +120,50 @@ sentry replay list my-org/frontend -c prev
sentry replay list my-org/frontend --json
```

### `sentry replay summarize <replay-id-or-url...>`

Summarize Session Replay behavior

**Flags:**
- `--path <value> - Focus summary on events from this URL pathname`
- `--limit-signals <value> - Maximum friction signals to include (0-50) - (default: "10")`
- `--limit-events <value> - Maximum notable events to include (0-50) - (default: "12")`
- `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data`

**JSON Fields** (use `--json --fields` to select specific fields):

| Field | Type | Description |
|-------|------|-------------|
| `replayId` | string | Replay ID |
| `org` | string | Organization slug |
| `project` | string \| null | Project slug |
| `platform` | string \| null | Replay platform |
| `sdkName` | string \| null | Replay SDK name |
| `sdkVersion` | string \| null | Replay SDK version |
| `replayType` | string \| null | Replay type |
| `startedAt` | string \| null | Replay start time |
| `durationSeconds` | number \| null | Replay duration in seconds |
| `entryUrl` | string \| null | First replay URL |
| `exitUrl` | string \| null | Last replay URL |
| `focusPath` | string \| null | Optional route path used to focus the summary |
| `counts` | object | Normalized event counts |
| `recording` | object | Downloaded recording and parser stats |
| `timings` | object | Key timing observations |
| `routes` | array | Route timeline |
| `signals` | array | Detected non-error and error friction signals |
| `notableEvents` | array | Representative events useful for agent narrative |

**Examples:**

```bash
# Summarize route flow, event counts, timings, and friction signals
sentry replay summarize my-org/346789a703f6454384f1de473b8b9fcc --json

# Focus the summary on a particular route path
sentry replay summarize my-org/346789a703f6454384f1de473b8b9fcc \
--path /signup --json
```

### `sentry replay view <replay-id-or-url...>`

View a Session Replay
Expand Down
17 changes: 12 additions & 5 deletions script/generate-docs-sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,20 @@ function isStandaloneCommand(route: RouteInfo): boolean {

/**
* Get subcommand names for a route group (e.g., "list, view, create").
* Extracts the last path segment from each command's path.
* Preserves nested subcommands as "parent child" so route groups do not
* collapse multiple commands to the same final segment.
*/
function getSubcommandNames(route: RouteInfo): string[] {
return route.commands.map((cmd) => {
const parts = cmd.path.split(" ");
return parts.at(-1) ?? route.name;
});
const prefix = `sentry ${route.name} `;
return Array.from(
new Set(
route.commands.map((cmd) =>
cmd.path.startsWith(prefix)
? cmd.path.slice(prefix.length)
: (cmd.path.split(" ").at(-1) ?? route.name)
)
)
);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions src/commands/replay/event/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* sentry replay event
*
* Inspect normalized events from Session Replay recordings.
*/

import { buildRouteMap } from "../../../lib/route-map.js";
import { listCommand } from "./list.js";

export const eventRoute = buildRouteMap({
routes: {
list: listCommand,
},
defaultCommand: "list",
docs: {
brief: "Inspect normalized replay events",
fullDescription:
"Inspect normalized events extracted from Session Replay recordings.\n\n" +
"Commands:\n" +
" list List normalized replay events\n\n" +
"Alias: `sentry replay events` → `sentry replay event list`",
hideRoute: {},
},
});
Loading
Loading