From d7591111277c4e035e49a49985159a4f1c994887 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Thu, 9 Apr 2026 08:30:13 +0000 Subject: [PATCH 1/2] refactor(docs): gitignore generated command docs, extract fragments Command docs (docs/src/content/docs/commands/*.md) were a mix of auto-generated flag tables and hand-written examples. Both halves changed on every CI run due to dynamic PERIOD_BRIEF dates, creating daily noise in PRs via auto-commit. Split hand-written content into fragment files (docs/src/fragments/ commands/) and gitignore the generated output. The docs build and CI now run generate:docs before astro build. Skill files (plugins/sentry-cli/skills/sentry-cli/) remain committed since they are consumed directly by external plugin systems. PERIOD_BRIEF dates are snapped to the 1st of the month to reduce churn from daily to ~monthly. - Add generate:docs composite script (generate:command-docs + generate:skill) - Replace generate:skill with generate:docs in all dependent scripts - Extract 19 command doc fragments from below the GENERATED:END marker - Update generate-command-docs.ts to read from fragments directory - Add check:fragments validation script, remove check:skill/check:command-docs - Update CI: generation before docs build, slimmed auto-commit for skill files only - Delete generate-skill.yml workflow (superseded by CI check-generated job) - Snap PERIOD_BRIEF example dates to 1st of month --- .github/workflows/ci.yml | 57 ++-- .github/workflows/docs-preview.yml | 15 + .github/workflows/generate-skill.yml | 55 ---- .gitignore | 6 + AGENTS.md | 13 +- docs/public/.well-known/skills/index.json | 29 -- docs/src/content/docs/commands/dashboard.md | 261 ------------------ docs/src/content/docs/commands/event.md | 92 ------ docs/src/content/docs/commands/index.md | 56 ---- docs/src/content/docs/commands/issue.md | 194 ------------- docs/src/content/docs/commands/org.md | 75 ----- docs/src/content/docs/commands/project.md | 142 ---------- docs/src/content/docs/commands/release.md | 205 -------------- docs/src/content/docs/commands/repo.md | 43 --- docs/src/content/docs/commands/schema.md | 48 ---- docs/src/content/docs/commands/sourcemap.md | 74 ----- docs/src/content/docs/commands/span.md | 84 ------ docs/src/content/docs/commands/team.md | 43 --- docs/src/content/docs/commands/trace.md | 116 -------- docs/src/content/docs/commands/trial.md | 52 ---- .../docs => fragments}/commands/api.md | 35 --- .../docs => fragments}/commands/auth.md | 62 ----- .../docs => fragments}/commands/cli.md | 66 ----- docs/src/fragments/commands/dashboard.md | 127 +++++++++ docs/src/fragments/commands/event.md | 42 +++ docs/src/fragments/commands/index.md | 26 ++ .../docs => fragments}/commands/init.md | 31 --- docs/src/fragments/commands/issue.md | 87 ++++++ .../docs => fragments}/commands/log.md | 49 ---- docs/src/fragments/commands/org.md | 36 +++ docs/src/fragments/commands/project.md | 59 ++++ docs/src/fragments/commands/release.md | 50 ++++ docs/src/fragments/commands/repo.md | 14 + docs/src/fragments/commands/schema.md | 20 ++ docs/src/fragments/commands/sourcemap.md | 29 ++ docs/src/fragments/commands/span.md | 35 +++ docs/src/fragments/commands/team.md | 14 + docs/src/fragments/commands/trace.md | 45 +++ docs/src/fragments/commands/trial.md | 20 ++ package.json | 20 +- plugins/README.md | 4 +- .../skills/sentry-cli/references/dashboard.md | 2 +- .../skills/sentry-cli/references/event.md | 2 +- .../skills/sentry-cli/references/issue.md | 4 +- .../skills/sentry-cli/references/log.md | 2 +- .../skills/sentry-cli/references/span.md | 2 +- .../skills/sentry-cli/references/trace.md | 4 +- script/check-command-docs.ts | 93 ------- script/check-fragments.ts | 99 +++++++ script/check-skill.ts | 130 --------- script/generate-command-docs.ts | 36 +-- src/lib/time-range.ts | 12 +- 52 files changed, 818 insertions(+), 2099 deletions(-) delete mode 100644 .github/workflows/generate-skill.yml delete mode 100644 docs/public/.well-known/skills/index.json delete mode 100644 docs/src/content/docs/commands/dashboard.md delete mode 100644 docs/src/content/docs/commands/event.md delete mode 100644 docs/src/content/docs/commands/index.md delete mode 100644 docs/src/content/docs/commands/issue.md delete mode 100644 docs/src/content/docs/commands/org.md delete mode 100644 docs/src/content/docs/commands/project.md delete mode 100644 docs/src/content/docs/commands/release.md delete mode 100644 docs/src/content/docs/commands/repo.md delete mode 100644 docs/src/content/docs/commands/schema.md delete mode 100644 docs/src/content/docs/commands/sourcemap.md delete mode 100644 docs/src/content/docs/commands/span.md delete mode 100644 docs/src/content/docs/commands/team.md delete mode 100644 docs/src/content/docs/commands/trace.md delete mode 100644 docs/src/content/docs/commands/trial.md rename docs/src/{content/docs => fragments}/commands/api.md (52%) rename docs/src/{content/docs => fragments}/commands/auth.md (53%) rename docs/src/{content/docs => fragments}/commands/cli.md (52%) create mode 100644 docs/src/fragments/commands/dashboard.md create mode 100644 docs/src/fragments/commands/event.md create mode 100644 docs/src/fragments/commands/index.md rename docs/src/{content/docs => fragments}/commands/init.md (68%) create mode 100644 docs/src/fragments/commands/issue.md rename docs/src/{content/docs => fragments}/commands/log.md (58%) create mode 100644 docs/src/fragments/commands/org.md create mode 100644 docs/src/fragments/commands/project.md create mode 100644 docs/src/fragments/commands/release.md create mode 100644 docs/src/fragments/commands/repo.md create mode 100644 docs/src/fragments/commands/schema.md create mode 100644 docs/src/fragments/commands/sourcemap.md create mode 100644 docs/src/fragments/commands/span.md create mode 100644 docs/src/fragments/commands/team.md create mode 100644 docs/src/fragments/commands/trace.md create mode 100644 docs/src/fragments/commands/trial.md delete mode 100644 script/check-command-docs.ts create mode 100644 script/check-fragments.ts delete mode 100644 script/check-skill.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 84f47f62a..3ec3874a5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: skill: - 'src/**' - 'docs/**' - - 'plugins/**' - 'script/generate-skill.ts' + - 'script/generate-command-docs.ts' - 'script/eval-skill.ts' - 'test/skill-eval/**' code: @@ -88,8 +88,8 @@ jobs: echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Nightly version: ${VERSION}" - check-skill: - name: Check skill files + check-generated: + name: Validate generated files needs: [changes] if: needs.changes.outputs.skill == 'true' runs-on: ubuntu-latest @@ -116,25 +116,30 @@ jobs: run: bun install --frozen-lockfile - name: Generate API Schema run: bun run generate:schema + - name: Generate docs and skill files + run: bun run generate:docs + - name: Validate fragments + run: bun run check:fragments - name: Check skill files id: check-skill - run: bun run check:skill - continue-on-error: true - - name: Check command docs - id: check-docs - run: bun run check:command-docs - continue-on-error: true - - name: Auto-commit regenerated files - if: (steps.check-skill.outcome == 'failure' || steps.check-docs.outcome == 'failure') && steps.token.outcome == 'success' + run: | + if git diff --quiet plugins/sentry-cli/skills/sentry-cli/; then + echo "Skill files are up to date" + else + echo "stale=true" >> "$GITHUB_OUTPUT" + echo "Skill files are out of date" + fi + - name: Auto-commit regenerated skill files + if: steps.check-skill.outputs.stale == 'true' && steps.token.outcome == 'success' run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - git add plugins/sentry-cli/skills/sentry-cli/ docs/public/.well-known/skills/index.json docs/src/content/docs/commands/ - git diff --cached --quiet || (git commit -m "chore: regenerate skill files and command docs" && git push) - - name: Fail for fork PRs with stale generated files - if: (steps.check-skill.outcome == 'failure' || steps.check-docs.outcome == 'failure') && steps.token.outcome != 'success' + git add plugins/sentry-cli/skills/sentry-cli/ + git diff --cached --quiet || (git commit -m "chore: regenerate skill files" && git push) + - name: Fail for fork PRs with stale skill files + if: steps.check-skill.outputs.stale == 'true' && steps.token.outcome != 'success' run: | - echo "::error::Generated files are out of date. Run 'bun run generate:skill' and 'bun run generate:command-docs' locally and commit the result." + echo "::error::Skill files are out of date. Run 'bun run generate:docs' locally and commit the result." exit 1 eval-skill: @@ -177,6 +182,9 @@ jobs: key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }} - if: steps.detect-fork.outputs.is_fork != 'true' && steps.cache.outputs.cache-hit != 'true' run: bun install --frozen-lockfile + - name: Generate docs and skill files + if: steps.detect-fork.outputs.is_fork != 'true' + run: bun run generate:schema && bun run generate:docs - name: Eval SKILL.md if: steps.detect-fork.outputs.is_fork != 'true' run: bun run eval:skill @@ -659,6 +667,15 @@ jobs: steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 + - uses: actions/cache@v5 + id: cache + with: + path: node_modules + key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }} + - if: steps.cache.outputs.cache-hit != 'true' + run: bun install --frozen-lockfile + - name: Generate docs content + run: bun run generate:schema && bun run generate:docs - name: Build Docs working-directory: docs run: | @@ -677,7 +694,7 @@ jobs: ci-status: name: CI Status if: always() - needs: [changes, check-skill, eval-skill, build-binary, build-npm, build-docs, test-e2e, generate-patches, publish-nightly] + needs: [changes, check-generated, eval-skill, build-binary, build-npm, build-docs, test-e2e, generate-patches, publish-nightly] runs-on: ubuntu-latest permissions: {} steps: @@ -685,7 +702,7 @@ jobs: run: | # Check for explicit failures or cancellations in all jobs # generate-patches and publish-nightly are skipped on PRs — that's expected - results="${{ needs.check-skill.result }} ${{ needs.eval-skill.result }} ${{ needs.build-binary.result }} ${{ needs.build-npm.result }} ${{ needs.build-docs.result }} ${{ needs.test-e2e.result }} ${{ needs.generate-patches.result }} ${{ needs.publish-nightly.result }}" + results="${{ needs.check-generated.result }} ${{ needs.eval-skill.result }} ${{ needs.build-binary.result }} ${{ needs.build-npm.result }} ${{ needs.build-docs.result }} ${{ needs.test-e2e.result }} ${{ needs.generate-patches.result }} ${{ needs.publish-nightly.result }}" for result in $results; do if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then echo "::error::CI failed" @@ -699,8 +716,8 @@ jobs: echo "::error::CI failed - upstream job failed causing test-e2e to be skipped" exit 1 fi - if [[ "${{ needs.changes.outputs.skill }}" == "true" && "${{ needs.check-skill.result }}" == "skipped" ]]; then - echo "::error::CI failed - upstream job failed causing check-skill to be skipped" + if [[ "${{ needs.changes.outputs.skill }}" == "true" && "${{ needs.check-generated.result }}" == "skipped" ]]; then + echo "::error::CI failed - upstream job failed causing check-generated to be skipped" exit 1 fi if [[ "${{ needs.changes.outputs.skill }}" == "true" && "${{ needs.eval-skill.result }}" == "skipped" ]]; then diff --git a/.github/workflows/docs-preview.yml b/.github/workflows/docs-preview.yml index 1baec9eb8..0d8836263 100644 --- a/.github/workflows/docs-preview.yml +++ b/.github/workflows/docs-preview.yml @@ -4,6 +4,9 @@ on: pull_request: paths: - 'docs/**' + - 'src/**' + - 'script/generate-command-docs.ts' + - 'script/generate-skill.ts' - '.github/workflows/docs-preview.yml' permissions: @@ -18,6 +21,18 @@ jobs: - uses: oven-sh/setup-bun@v2 + - uses: actions/cache@v5 + id: cache + with: + path: node_modules + key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }} + + - if: steps.cache.outputs.cache-hit != 'true' + run: bun install --frozen-lockfile + + - name: Generate docs content + run: bun run generate:schema && bun run generate:docs + - name: Build Docs for Preview working-directory: docs env: diff --git a/.github/workflows/generate-skill.yml b/.github/workflows/generate-skill.yml deleted file mode 100644 index ab20e0a6f..000000000 --- a/.github/workflows/generate-skill.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Generate SKILL.md - -on: - workflow_dispatch: - inputs: - branch: - description: 'Branch to regenerate SKILL.md on' - required: true - type: string - -permissions: - contents: write - -jobs: - generate: - name: Generate and Commit - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - with: - ref: ${{ inputs.branch }} - - - uses: oven-sh/setup-bun@v2 - - - uses: actions/cache@v5 - id: cache - with: - path: node_modules - key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }} - - - if: steps.cache.outputs.cache-hit != 'true' - run: bun install --frozen-lockfile - - - name: Generate SKILL.md - run: bun run generate:skill - - - name: Check for changes - id: diff - run: | - if git diff --quiet plugins/sentry-cli/skills/sentry-cli/SKILL.md; then - echo "changed=false" >> $GITHUB_OUTPUT - echo "SKILL.md is already up to date" - else - echo "changed=true" >> $GITHUB_OUTPUT - echo "SKILL.md has changes" - fi - - - name: Commit and push - if: steps.diff.outputs.changed == 'true' - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - git add plugins/sentry-cli/skills/sentry-cli/SKILL.md - git commit -m "chore: Regenerate SKILL.md" - git push diff --git a/.gitignore b/.gitignore index 2a8bd491e..b29ae9dad 100644 --- a/.gitignore +++ b/.gitignore @@ -58,6 +58,12 @@ src/generated/ src/sdk.generated.ts src/sdk.generated.d.cts +# Generated command docs (rebuilt from fragments + CLI introspection) +docs/src/content/docs/commands/ + +# Generated discovery manifest (rebuilt by generate:skill, served via symlinked skill files) +docs/public/.well-known/skills/index.json + # OpenCode .opencode/ opencode.json* diff --git a/AGENTS.md b/AGENTS.md index c62bcae8f..386800c22 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -455,10 +455,14 @@ All normalize to lowercase. Throw `ValidationError` on invalid input. Use `"date"` for timestamp-based sort (not `"time"`). Export sort types from the API layer (e.g., `SpanSortValue` from `api/traces.ts`), import in commands. This matches `issue list`, `trace list`, and `span list`. -### SKILL.md +### Generated Docs & Skills -- Run `bun run generate:skill` after changing any command parameters, flags, or docs. -- CI check `bun run check:skill` will fail if SKILL.md is stale. +All command docs and skill files are generated via `bun run generate:docs` (which runs `generate:command-docs` then `generate:skill`). This runs automatically as part of `dev`, `build`, `typecheck`, and `test` scripts. + +- **Command docs** (`docs/src/content/docs/commands/*.md`) are **gitignored** and generated from CLI metadata + hand-written fragments in `docs/src/fragments/commands/`. +- **Skill files** (`plugins/sentry-cli/skills/sentry-cli/`) are **committed** (consumed by external plugin systems) and auto-committed by CI when stale. +- Edit fragments in `docs/src/fragments/commands/` for custom examples and guides. +- `bun run check:fragments` validates fragment ↔ route consistency. - Positional `placeholder` values must be descriptive: `"org/project/trace-id"` not `"args"`. ### Zod Schemas for Validation @@ -939,6 +943,7 @@ mock.module("./some-module", () => ({ | Add E2E tests | `test/e2e/` | | Test helpers | `test/model-based/helpers.ts` | | Add documentation | `docs/src/content/docs/` | +| Hand-written command doc content | `docs/src/fragments/commands/` | ## Long-term Knowledge @@ -982,7 +987,7 @@ mock.module("./some-module", () => ({ * **Sentry trace-logs API is org-scoped, not project-scoped**: The Sentry trace-logs endpoint (\`/organizations/{org}/trace-logs/\`) is org-scoped, so \`trace logs\` uses \`resolveOrg()\` not \`resolveOrgAndProject()\`. The endpoint is PRIVATE in Sentry source, excluded from the public OpenAPI schema — \`@sentry/api\` has no generated types. The hand-written \`TraceLogSchema\` in \`src/types/sentry.ts\` is required until Sentry makes it public. -* **SKILL.md is fully generated — edit source files, not output**: The skill files under \`plugins/sentry-cli/skills/sentry-cli/\` (SKILL.md + references/\*.md) are fully generated by \`bun run generate:skill\` (script/generate-skill.ts). CI runs this after every push via a \`github-actions\[bot]\` commit, overwriting any manual edits. To change skill content, edit the \*\*sources\*\*: (1) \`docs/src/content/docs/agent-guidance.md\` — embedded into SKILL.md's Agent Guidance section with heading levels bumped. (2) \`src/commands/\*/\` flag \`brief\` strings — generate the reference file flag descriptions. (3) \`docs/src/content/docs/commands/\*.md\` — examples extracted per command via marked AST parsing. After editing sources, run \`bun run generate:skill\` locally and commit both source and generated files. CI's \`bun run check:skill\` fails if generated files are stale. +* **SKILL.md is fully generated — edit fragment files for custom content, not output**: The skill files under \`plugins/sentry-cli/skills/sentry-cli/\` (SKILL.md + references/\*.md) are fully generated by \`bun run generate:skill\` (script/generate-skill.ts). They are rebuilt automatically by \`bun run generate:docs\` which runs as part of \`dev\`, \`build\`, \`typecheck\`, and \`test\` scripts. To change skill content, edit the \*\*sources\*\*: (1) \`docs/src/content/docs/agent-guidance.md\` — embedded into SKILL.md's Agent Guidance section with heading levels bumped. (2) \`src/commands/\*/\` flag \`brief\` strings — generate the reference file flag descriptions. (3) \`docs/src/fragments/commands/\*.md\` — hand-written examples and guides appended to generated command docs. Command docs (\`docs/src/content/docs/commands/\*.md\`) are also gitignored and rebuilt from fragments + CLI metadata by \`generate:command-docs\`. \`bun run check:fragments\` validates fragment ↔ route consistency. * **Stricli route errors are uninterceptable — only post-run detection works**: Stricli route errors, exit codes, and OutputError — error propagation gaps: (1) Route failures are uninterceptable — Stricli writes to stderr and returns \`ExitCode.UnknownCommand\` internally. Only post-\`run()\` \`process.exitCode\` check works. \`exceptionWhileRunningCommand\` only fires for errors in command \`func()\`. (2) \`ExitCode.UnknownCommand\` is \`-5\`. Bun reads \`251\` (unsigned byte), Node reads \`-5\` — compare both. (3) \`OutputError\` in \`handleOutputError\` calls \`process.exit()\` immediately, bypassing telemetry and \`exceptionWhileRunningCommand\`. Top-level typos via \`defaultCommand:help\` → \`OutputError\` → \`process.exit(1)\` skip all error reporting. diff --git a/docs/public/.well-known/skills/index.json b/docs/public/.well-known/skills/index.json deleted file mode 100644 index 51bd5ce26..000000000 --- a/docs/public/.well-known/skills/index.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "skills": [ - { - "name": "sentry-cli", - "description": "Guide for using the Sentry CLI to interact with Sentry from the command line. Use when the user asks about viewing issues, events, projects, organizations, making API calls, or authenticating with Sentry via CLI.", - "files": [ - "SKILL.md", - "references/api.md", - "references/auth.md", - "references/cli.md", - "references/dashboard.md", - "references/event.md", - "references/init.md", - "references/issue.md", - "references/log.md", - "references/org.md", - "references/project.md", - "references/release.md", - "references/repo.md", - "references/schema.md", - "references/sourcemap.md", - "references/span.md", - "references/team.md", - "references/trace.md", - "references/trial.md" - ] - } - ] -} diff --git a/docs/src/content/docs/commands/dashboard.md b/docs/src/content/docs/commands/dashboard.md deleted file mode 100644 index 51ce630e0..000000000 --- a/docs/src/content/docs/commands/dashboard.md +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: dashboard -description: Dashboard commands for the Sentry CLI ---- - -Manage Sentry dashboards - -## Commands - -### `sentry dashboard list ` - -List dashboards - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `` | [<org/project>] [<name-glob>] | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `-n, --limit ` | Maximum number of dashboards to list (default: "25") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor ` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -### `sentry dashboard view ` - -View a dashboard - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `` | [<org/project>] <dashboard-id-or-title> | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-r, --refresh ` | Auto-refresh interval in seconds (default: 60, min: 10) | -| `-t, --period ` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" | - -### `sentry dashboard create ` - -Create a dashboard - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `` | [<org/project>] <title> | - -### `sentry dashboard widget add ` - -Add a widget to a dashboard - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `` | [<org/project>] <dashboard> <title> | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-d, --display ` | Display type (big_number, line, area, bar, table, stacked_area, top_n, text, categorical_bar, details, wheel, rage_and_dead_clicks, server_tree, agents_traces_table) | -| `--dataset ` | Widget dataset (default: spans) | -| `-q, --query ...` | Aggregate expression (e.g. count, p95:span.duration) | -| `-w, --where ` | Search conditions filter (e.g. is:unresolved) | -| `-g, --group-by ...` | Group-by column (repeatable) | -| `-s, --sort ` | Order by (prefix - for desc, e.g. -count) | -| `-n, --limit ` | Result limit | -| `--x ` | Grid column position (0-based, 0–5) | -| `--y ` | Grid row position (0-based) | -| `--width ` | Widget width in grid columns (1–6) | -| `--height ` | Widget height in grid rows (min 1) | - -### `sentry dashboard widget edit ` - -Edit a widget in a dashboard - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `` | [<org/project>] <dashboard-id-or-title> | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-i, --index ` | Widget index (0-based) | -| `-t, --title ` | Widget title to match | -| `--new-title <new-title>` | New widget title | -| `-d, --display <display>` | Display type (big_number, line, area, bar, table, stacked_area, top_n, text, categorical_bar, details, wheel, rage_and_dead_clicks, server_tree, agents_traces_table) | -| `--dataset <dataset>` | Widget dataset (default: spans) | -| `-q, --query <query>...` | Aggregate expression (e.g. count, p95:span.duration) | -| `-w, --where <where>` | Search conditions filter (e.g. is:unresolved) | -| `-g, --group-by <group-by>...` | Group-by column (repeatable) | -| `-s, --sort <sort>` | Order by (prefix - for desc, e.g. -count) | -| `-n, --limit <limit>` | Result limit | -| `--x <x>` | Grid column position (0-based, 0–5) | -| `--y <y>` | Grid row position (0-based) | -| `--width <width>` | Widget width in grid columns (1–6) | -| `--height <height>` | Widget height in grid rows (min 1) | - -### `sentry dashboard widget delete <org/project/dashboard...>` - -Delete a widget from a dashboard - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project/dashboard...>` | [<org/project>] <dashboard-id-or-title> | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-i, --index <index>` | Widget index (0-based) | -| `-t, --title <title>` | Widget title to match | -| `-y, --yes` | Skip confirmation prompt | -| `-f, --force` | Force the operation without confirmation | -| `-n, --dry-run` | Show what would happen without making changes | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -### List dashboards - -```bash -# List all dashboards -sentry dashboard list - -# Filter by name pattern -sentry dashboard list "Backend*" - -# Open dashboard list in browser -sentry dashboard list -w -``` - -``` -ID TITLE WIDGETS CREATED -12345 General 4 2024-01-15 -12346 Frontend Performance 6 2024-02-20 -12347 Backend Errors 3 2024-03-10 -``` - -### View a dashboard - -```bash -# View by title -sentry dashboard view 'Frontend Performance' - -# View by ID -sentry dashboard view 12345 - -# Auto-refresh every 30 seconds -sentry dashboard view "Backend Performance" --refresh 30 - -# Open in browser -sentry dashboard view 12345 -w -``` - -``` -Dashboard: Frontend Performance (ID: 12345) -URL: https://my-org.sentry.io/dashboard/12345/ - -Widgets: - #0 Error Count big_number count() - #1 Errors Over Time line count() - #2 Errors by Browser bar count() group by browser.name - #3 Top Endpoints table count(), p95(span.duration) group by transaction -``` - -### Create a dashboard - -```bash -sentry dashboard create 'Frontend Performance' -``` - -``` -Created dashboard: Frontend Performance (ID: 12348) -URL: https://my-org.sentry.io/dashboard/12348/ -``` - -### Add widgets - -```bash -# Simple counter widget -sentry dashboard widget add 'My Dashboard' "Error Count" \ - --display big_number --query count - -# Line chart with group-by -sentry dashboard widget add 'My Dashboard' "Errors by Browser" \ - --display line --query count --group-by browser.name - -# Table with multiple aggregates, sorted descending -sentry dashboard widget add 'My Dashboard' "Top Endpoints" \ - --display table \ - --query count --query p95:span.duration \ - --group-by transaction \ - --sort -count --limit 10 - -# With search filter -sentry dashboard widget add 'My Dashboard' "Slow Requests" \ - --display bar --query p95:span.duration \ - --where "span.op:http.client" \ - --group-by span.description -``` - -### Edit widgets - -```bash -# Change display type -sentry dashboard widget edit 12345 --title 'Error Count' --display bar - -# Rename a widget -sentry dashboard widget edit 'My Dashboard' --index 0 --new-title 'Total Errors' - -# Change the query -sentry dashboard widget edit 12345 --title 'Error Rate' --query p95:span.duration -``` - -### Delete widgets - -```bash -# Delete by title -sentry dashboard widget delete 'My Dashboard' --title 'Error Count' - -# Delete by index -sentry dashboard widget delete 12345 --index 2 -``` - -## Query Shorthand - -The `--query` flag supports shorthand for aggregate functions: - -| Input | Expands to | -|-------|-----------| -| `count` | `count()` | -| `p95:span.duration` | `p95(span.duration)` | -| `avg:span.duration` | `avg(span.duration)` | -| `count()` | `count()` (passthrough) | - -## Sort Shorthand - -| Input | Meaning | -|-------|---------| -| `count` | Sort by `count()` ascending | -| `-count` | Sort by `count()` descending | diff --git a/docs/src/content/docs/commands/event.md b/docs/src/content/docs/commands/event.md deleted file mode 100644 index 34d1e0465..000000000 --- a/docs/src/content/docs/commands/event.md +++ /dev/null @@ -1,92 +0,0 @@ ---- -title: event -description: Event commands for the Sentry CLI ---- - -View and list Sentry events - -## Commands - -### `sentry event view <org/project/event-id...>` - -View details of a specific event - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project/event-id...>` | [<org>/<project>] <event-id> - Target (optional) and event ID (required) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `--spans <spans>` | Span tree depth limit (number, "all" for unlimited, "no" to disable) (default: "3") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry event list <issue>` - -List events for an issue - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<issue>` | Issue: @latest, @most_frequent, <org>/ID, <project>-suffix, ID, or suffix | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Number of events (1-1000) (default: "25") | -| `-q, --query <query>` | Search query (Sentry search syntax) | -| `--full` | Include full event body (stacktraces) | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -sentry event view abc123def456abc123def456abc12345 -``` - -``` -Event: abc123def456abc123def456abc12345 -Issue: FRONT-ABC -Timestamp: 2024-01-20 14:22:00 - -Exception: - TypeError: Cannot read property 'foo' of undefined - at processData (app.js:123:45) - at handleClick (app.js:89:12) - at HTMLButtonElement.onclick (app.js:45:8) - -Tags: - browser: Chrome 120 - os: Windows 10 - environment: production - release: 1.2.3 - -Context: - url: https://example.com/app - user_id: 12345 -``` - -```bash -# Open in browser -sentry event view abc123def456abc123def456abc12345 -w -``` - -## Finding Event IDs - -Event IDs can be found: - -1. In the Sentry UI when viewing an issue's events -2. In the output of `sentry issue view` commands -3. In error reports sent to Sentry (as `event_id`) diff --git a/docs/src/content/docs/commands/index.md b/docs/src/content/docs/commands/index.md deleted file mode 100644 index b8e51e2da..000000000 --- a/docs/src/content/docs/commands/index.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Commands -description: Available commands in the Sentry CLI ---- - -The Sentry CLI provides commands for interacting with various Sentry resources. - -## Available Commands - -| Command | Description | -|---------|-------------| -| [`auth`](./auth/) | Authenticate with Sentry | -| [`cli`](./cli/) | CLI-related commands | -| [`dashboard`](./dashboard/) | Manage Sentry dashboards | -| [`org`](./org/) | Work with Sentry organizations | -| [`project`](./project/) | Work with Sentry projects | -| [`release`](./release/) | Work with Sentry releases | -| [`repo`](./repo/) | Work with Sentry repositories | -| [`team`](./team/) | Work with Sentry teams | -| [`issue`](./issue/) | Manage Sentry issues | -| [`event`](./event/) | View and list Sentry events | -| [`log`](./log/) | View Sentry logs | -| [`sourcemap`](./sourcemap/) | Manage sourcemaps | -| [`span`](./span/) | List and view spans in projects or traces | -| [`trace`](./trace/) | View distributed traces | -| [`trial`](./trial/) | Manage product trials | -| [`init`](./init/) | Initialize Sentry in your project (experimental) | -| [`api`](./api/) | Make an authenticated API request | -| [`schema`](./schema/) | Browse the Sentry API schema | - -<!-- GENERATED:END --> - -## Global Options - -All commands support the following global options: - -- `--help` - Show help for the command -- `--version` - Show CLI version -- `--log-level <level>` - Set log verbosity (`error`, `warn`, `log`, `info`, `debug`, `trace`). Overrides `SENTRY_LOG_LEVEL` -- `--verbose` - Shorthand for `--log-level debug` - -## JSON Output - -Most list and view commands support `--json` flag for JSON output, making it easy to integrate with other tools: - -```bash -sentry org list --json | jq '.[] | .slug' -``` - -## Opening in Browser - -View commands support `-w` or `--web` flag to open the resource in your browser: - -```bash -sentry issue view PROJ-123 -w -``` diff --git a/docs/src/content/docs/commands/issue.md b/docs/src/content/docs/commands/issue.md deleted file mode 100644 index 7b5fb9d32..000000000 --- a/docs/src/content/docs/commands/issue.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: issue -description: Issue commands for the Sentry CLI ---- - -Manage Sentry issues - -## Commands - -### `sentry issue list <org/project>` - -List issues in a project - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/ (all projects), <org>/<project>, or <project> (search) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-q, --query <query>` | Search query (Sentry search syntax) | -| `-n, --limit <limit>` | Maximum number of issues to list (default: "25") | -| `-s, --sort <sort>` | Sort by: date, new, freq, user (default: "date") | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "90d") | -| `-c, --cursor <cursor>` | Pagination cursor (use "next" for next page, "prev" for previous) | -| `--compact` | Single-line rows for compact output (auto-detects if omitted) | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry issue events <issue>` - -List events for a specific issue - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<issue>` | Issue: @latest, @most_frequent, <org>/ID, <project>-suffix, ID, or suffix | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Number of events (1-1000) (default: "25") | -| `-q, --query <query>` | Search query (Sentry search syntax) | -| `--full` | Include full event body (stacktraces) | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -### `sentry issue explain <issue>` - -Analyze an issue's root cause using Seer AI - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<issue>` | Issue: @latest, @most_frequent, <org>/ID, <project>-suffix, ID, or suffix | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--force` | Force new analysis even if one exists | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry issue plan <issue>` - -Generate a solution plan using Seer AI - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<issue>` | Issue: @latest, @most_frequent, <org>/ID, <project>-suffix, ID, or suffix | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--cause <cause>` | Root cause ID to plan (required if multiple causes exist) | -| `--force` | Force new plan even if one exists | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry issue view <issue>` - -View details of a specific issue - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<issue>` | Issue: @latest, @most_frequent, <org>/ID, <project>-suffix, ID, or suffix | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `--spans <spans>` | Span tree depth limit (number, "all" for unlimited, "no" to disable) (default: "3") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -### List issues - -```bash -# List issues in a specific project -sentry issue list my-org/frontend - -# All projects in an org -sentry issue list my-org/ - -# Search for a project across organizations -sentry issue list frontend -``` - -``` -ID SHORT ID TITLE COUNT USERS -123456789 FRONT-ABC TypeError: Cannot read prop... 1.2k 234 -987654321 FRONT-DEF ReferenceError: x is not de... 456 89 -``` - -**Filter by status:** - -```bash -# Show only unresolved issues -sentry issue list my-org/frontend --query "is:unresolved" - -# Show resolved issues -sentry issue list my-org/frontend --query "is:resolved" - -# Sort by frequency -sentry issue list my-org/frontend --sort freq --limit 20 -``` - -### View an issue - -```bash -sentry issue view FRONT-ABC -``` - -``` -Issue: TypeError: Cannot read property 'foo' of undefined -Short ID: FRONT-ABC -Status: unresolved -First seen: 2024-01-15 10:30:00 -Last seen: 2024-01-20 14:22:00 -Events: 1,234 -Users affected: 234 - -Latest event: - Browser: Chrome 120 - OS: Windows 10 - URL: https://example.com/app -``` - -```bash -# Open in browser -sentry issue view FRONT-ABC -w -``` - -### Explain and plan with Seer AI - -```bash -# Analyze root cause (may take a few minutes for new issues) -sentry issue explain 123456789 - -# By short ID with org prefix -sentry issue explain my-org/MYPROJECT-ABC - -# Force a fresh analysis -sentry issue explain 123456789 --force - -# Generate a fix plan (requires explain to be run first) -sentry issue plan 123456789 - -# Specify which root cause to plan for -sentry issue plan 123456789 --cause 0 -``` - -**Requirements:** - -- Seer AI enabled for your organization -- GitHub integration configured with repository access -- Code mappings set up to link stack frames to source files -- Root cause analysis must be completed (`sentry issue explain`) before generating a plan diff --git a/docs/src/content/docs/commands/org.md b/docs/src/content/docs/commands/org.md deleted file mode 100644 index 98fbb4784..000000000 --- a/docs/src/content/docs/commands/org.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: org -description: Org commands for the Sentry CLI ---- - -Work with Sentry organizations - -## Commands - -### `sentry org list` - -List organizations - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Maximum number of organizations to list (default: "25") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry org view <org>` - -View details of an organization - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org>` | Organization slug (optional if auto-detected) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List organizations -sentry org list -``` - -``` -SLUG NAME ROLE -my-org My Organization owner -another-org Another Org member -``` - -```bash -# View organization details -sentry org view my-org -``` - -``` -Organization: My Organization -Slug: my-org -Role: owner -Projects: 5 -Teams: 3 -Members: 12 -``` - -```bash -# Open in browser -sentry org view my-org -w - -# JSON output -sentry org list --json -``` diff --git a/docs/src/content/docs/commands/project.md b/docs/src/content/docs/commands/project.md deleted file mode 100644 index b973c43eb..000000000 --- a/docs/src/content/docs/commands/project.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: project -description: Project commands for the Sentry CLI ---- - -Work with Sentry projects - -## Commands - -### `sentry project create <name> <platform>` - -Create a new project - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<name>` | Project name (supports org/name syntax) | -| `<platform>` | Project platform (e.g., node, python, javascript-nextjs) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-t, --team <team>` | Team to create the project under | -| `-n, --dry-run` | Show what would happen without making changes | - -### `sentry project delete <org/project>` - -Delete a project - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/<project> or <project> (search across orgs) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-y, --yes` | Skip confirmation prompt | -| `-f, --force` | Force the operation without confirmation | -| `-n, --dry-run` | Show what would happen without making changes | - -### `sentry project list <org/project>` - -List projects - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/ (all projects), <org>/<project>, or <project> (search) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Maximum number of projects to list (default: "25") | -| `-p, --platform <platform>` | Filter by platform (e.g., javascript, python) | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -### `sentry project view <org/project>` - -View details of a project - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/<project>, <project> (search), or omit for auto-detect | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List all projects in an org -sentry project list my-org/ -``` - -``` -ORG SLUG PLATFORM TEAM -my-org frontend javascript web-team -my-org backend python api-team -my-org mobile-ios cocoa mobile-team -``` - -```bash -# Filter by platform -sentry project list my-org/ --platform javascript - -# View project details -sentry project view my-org/frontend -``` - -``` -Project: frontend -Organization: my-org -Platform: javascript -Team: web-team -DSN: https://abc123@sentry.io/123456 -``` - -```bash -# Open project in browser -sentry project view my-org/frontend -w -``` - -### Create a project - -```bash -# Create a new project -sentry project create my-new-app javascript-nextjs - -# Create under a specific org and team -sentry project create my-org/my-new-app python --team backend-team - -# Preview without creating -sentry project create my-new-app node --dry-run -``` - -### Delete a project - -```bash -# Delete a project (will prompt for confirmation) -sentry project delete my-org/old-project - -# Delete without confirmation -sentry project delete my-org/old-project --yes -``` diff --git a/docs/src/content/docs/commands/release.md b/docs/src/content/docs/commands/release.md deleted file mode 100644 index 739b8322f..000000000 --- a/docs/src/content/docs/commands/release.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -title: release -description: Release commands for the Sentry CLI ---- - -Work with Sentry releases - -## Commands - -### `sentry release list <org/project>` - -List releases - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/ (all projects), <org>/<project>, or <project> (search) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Maximum number of releases to list (default: "25") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -### `sentry release view <org/version...>` - -View release details - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version...>` | [<org>/]<version> - Release version to view | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry release create <org/version...>` - -Create a release - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version...>` | [<org>/]<version> - Release version to create | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-p, --project <project>` | Associate with project(s), comma-separated | -| `--finalize` | Immediately finalize the release (set dateReleased) | -| `--ref <ref>` | Git ref (branch or tag name) | -| `--url <url>` | URL to the release source | -| `-n, --dry-run` | Show what would happen without making changes | - -### `sentry release finalize <org/version...>` - -Finalize a release - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version...>` | [<org>/]<version> - Release version to finalize | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--released <released>` | Custom release timestamp (ISO 8601). Defaults to now. | -| `--url <url>` | URL for the release | -| `-n, --dry-run` | Show what would happen without making changes | - -### `sentry release delete <org/version...>` - -Delete a release - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version...>` | [<org>/]<version> - Release version to delete | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-y, --yes` | Skip confirmation prompt | -| `-f, --force` | Force the operation without confirmation | -| `-n, --dry-run` | Show what would happen without making changes | - -### `sentry release deploy <org/version environment name...>` - -Create a deploy for a release - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version environment name...>` | [<org>/]<version> <environment> [name] | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--url <url>` | URL for the deploy | -| `--started <started>` | Deploy start time (ISO 8601) | -| `--finished <finished>` | Deploy finish time (ISO 8601) | -| `-t, --time <time>` | Deploy duration in seconds (sets started = now - time, finished = now) | -| `-n, --dry-run` | Show what would happen without making changes | - -### `sentry release deploys <org/version...>` - -List deploys for a release - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version...>` | [<org>/]<version> - Release version | - -### `sentry release set-commits <org/version...>` - -Set commits for a release - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/version...>` | [<org>/]<version> - Release version | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--auto` | Auto-discover commits via repository integration (needs local git checkout) | -| `--local` | Read commits from local git history | -| `--clear` | Clear all commits from the release | -| `--commit <commit>` | Explicit commit as REPO@SHA or REPO@PREV..SHA (comma-separated) | -| `--initial-depth <initial-depth>` | Number of commits to read with --local (default: "20") | - -### `sentry release propose-version` - -Propose a release version - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List releases (auto-detect org) -sentry release list - -# List releases in a specific org -sentry release list my-org/ - -# View release details -sentry release view 1.0.0 -sentry release view my-org/1.0.0 - -# Create and finalize a release -sentry release create 1.0.0 --finalize - -# Create a release, then finalize separately -sentry release create 1.0.0 -sentry release set-commits 1.0.0 --auto -sentry release finalize 1.0.0 - -# Set commits from local git history -sentry release set-commits 1.0.0 --local - -# Create a deploy -sentry release deploy 1.0.0 production -sentry release deploy 1.0.0 staging "Deploy #42" - -# Propose a version from git HEAD -sentry release create $(sentry release propose-version) - -# Output as JSON -sentry release list --json -sentry release view 1.0.0 --json - -# Full release workflow with explicit org -sentry release create my-org/1.0.0 --project my-project -sentry release set-commits my-org/1.0.0 --auto -sentry release finalize my-org/1.0.0 -sentry release deploy my-org/1.0.0 production -``` - -## Important Notes - -- **Version matching**: The release version must match the `release` value in your `Sentry.init()` call. If your SDK uses `"1.0.0"`, create the release as `sentry release create org/1.0.0` (version = `1.0.0`), **not** `sentry release create org/myapp/1.0.0`. -- **The `org/` prefix is the org slug**: In `sentry release create sentry/1.0.0`, `sentry` is the org slug and `1.0.0` is the version. The `/` separates org from version — it is not part of the version string. -- **`--auto` needs a git checkout**: The `--auto` flag lists repos from the Sentry API and matches against your local `origin` remote URL. Without a local git repo, use `--local` instead. -- **Default mode tries `--auto` first**: When neither `--auto` nor `--local` is specified, `set-commits` tries auto-discovery first and falls back to local git history if the integration isn't configured. diff --git a/docs/src/content/docs/commands/repo.md b/docs/src/content/docs/commands/repo.md deleted file mode 100644 index 01dd2807c..000000000 --- a/docs/src/content/docs/commands/repo.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: repo -description: Repo commands for the Sentry CLI ---- - -Work with Sentry repositories - -## Commands - -### `sentry repo list <org/project>` - -List repositories - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/ (all projects), <org>/<project>, or <project> (search) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Maximum number of repositories to list (default: "25") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List repositories (auto-detect org) -sentry repo list - -# List repos in a specific org with pagination -sentry repo list my-org/ -c next - -# Output as JSON -sentry repo list --json -``` diff --git a/docs/src/content/docs/commands/schema.md b/docs/src/content/docs/commands/schema.md deleted file mode 100644 index caa3cdc0e..000000000 --- a/docs/src/content/docs/commands/schema.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: schema -description: Schema command for the Sentry CLI ---- - -Browse the Sentry API schema - -## Usage - -### `sentry schema <resource...>` - -Browse the Sentry API schema - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<resource...>` | Resource name and optional operation | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--all` | Show all endpoints in a flat list | -| `-q, --search <search>` | Search endpoints by keyword | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List all API resources -sentry schema - -# Browse issue endpoints -sentry schema issues - -# View details for a specific operation -sentry schema issues list - -# Search for monitoring-related endpoints -sentry schema --search monitor - -# Flat list of every endpoint -sentry schema --all -``` diff --git a/docs/src/content/docs/commands/sourcemap.md b/docs/src/content/docs/commands/sourcemap.md deleted file mode 100644 index 2a1c25674..000000000 --- a/docs/src/content/docs/commands/sourcemap.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: sourcemap -description: Sourcemap commands for the Sentry CLI ---- - -Manage sourcemaps - -## Commands - -### `sentry sourcemap inject <directory>` - -Inject debug IDs into JavaScript files and sourcemaps - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<directory>` | Directory to scan for JS + sourcemap pairs | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--ext <ext>` | Comma-separated file extensions to process (default: .js,.cjs,.mjs) | -| `--dry-run` | Show what would be modified without writing | - -### `sentry sourcemap upload <directory>` - -Upload sourcemaps to Sentry - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<directory>` | Directory containing sourcemaps | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--release <release>` | Release version to associate with the upload | -| `--url-prefix <url-prefix>` | URL prefix for uploaded files (default: ~/) | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -### Inject debug IDs - -```bash -# Inject debug IDs into all JS files in dist/ -sentry sourcemap inject ./dist - -# Preview changes without writing -sentry sourcemap inject ./dist --dry-run - -# Only process specific extensions -sentry sourcemap inject ./build --ext .js,.mjs -``` - -### Upload sourcemaps - -```bash -# Upload sourcemaps from dist/ -sentry sourcemap upload ./dist - -# Associate with a release -sentry sourcemap upload ./dist --release 1.0.0 - -# Set a custom URL prefix -sentry sourcemap upload ./dist --url-prefix '~/static/js/' -``` diff --git a/docs/src/content/docs/commands/span.md b/docs/src/content/docs/commands/span.md deleted file mode 100644 index 053367ccb..000000000 --- a/docs/src/content/docs/commands/span.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: span -description: Span commands for the Sentry CLI ---- - -List and view spans in projects or traces - -## Commands - -### `sentry span list <org/project/trace-id...>` - -List spans in a project or trace - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project/trace-id...>` | [<org>/<project>] or [<org>/<project>/]<trace-id> | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Number of spans (<=1000) (default: "25") | -| `-q, --query <query>` | Filter spans (e.g., "op:db", "duration:>100ms", "project:backend") | -| `-s, --sort <sort>` | Sort order: date, duration (default: "date") | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -### `sentry span view <trace-id/span-id...>` - -View details of specific spans - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<trace-id/span-id...>` | [<org>/<project>/]<trace-id> <span-id> [<span-id>...] - Trace ID and one or more span IDs | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--spans <spans>` | Span tree depth limit (number, "all" for unlimited, "no" to disable) (default: "3") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -### List spans - -```bash -# List recent spans in the current project -sentry span list - -# Find all DB spans -sentry span list -q "op:db" - -# Slow spans in the last 24 hours -sentry span list -q "duration:>100ms" --period 24h - -# List spans within a specific trace -sentry span list abc123def456abc123def456abc12345 - -# Paginate through results -sentry span list -c next -``` - -### View spans - -```bash -# View a single span -sentry span view abc123def456abc123def456abc12345 a1b2c3d4e5f67890 - -# View multiple spans at once -sentry span view abc123def456abc123def456abc12345 a1b2c3d4e5f67890 b2c3d4e5f6789012 - -# With explicit org/project -sentry span view my-org/backend/abc123def456abc123def456abc12345 a1b2c3d4e5f67890 -``` diff --git a/docs/src/content/docs/commands/team.md b/docs/src/content/docs/commands/team.md deleted file mode 100644 index b3afacde5..000000000 --- a/docs/src/content/docs/commands/team.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: team -description: Team commands for the Sentry CLI ---- - -Work with Sentry teams - -## Commands - -### `sentry team list <org/project>` - -List teams - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/ (all projects), <org>/<project>, or <project> (search) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Maximum number of teams to list (default: "25") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List teams -sentry team list my-org/ - -# Paginate through teams -sentry team list my-org/ -c next - -# Output as JSON -sentry team list --json -``` diff --git a/docs/src/content/docs/commands/trace.md b/docs/src/content/docs/commands/trace.md deleted file mode 100644 index b5d8c1e07..000000000 --- a/docs/src/content/docs/commands/trace.md +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: trace -description: Trace commands for the Sentry CLI ---- - -View distributed traces - -## Commands - -### `sentry trace list <org/project>` - -List recent traces in a project - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project>` | <org>/<project> or <project> (search) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Number of traces (1-1000) (default: "25") | -| `-q, --query <query>` | Search query (Sentry search syntax) | -| `-s, --sort <sort>` | Sort by: date, duration (default: "date") | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "7d") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | -| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) | - -### `sentry trace view <org/project/trace-id...>` - -View details of a specific trace - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project/trace-id...>` | [<org>/<project>/]<trace-id> - Target (optional) and trace ID (required) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `--spans <spans>` | Span tree depth limit (number, "all" for unlimited, "no" to disable) (default: "3") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry trace logs <org/trace-id...>` - -View logs associated with a trace - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/trace-id...>` | [<org>/]<trace-id> - Optional org and required trace ID | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open trace in browser | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" (default: "14d") | -| `-n, --limit <limit>` | Number of log entries (<=1000) (default: "100") | -| `-q, --query <query>` | Additional filter query (Sentry search syntax) | -| `-s, --sort <sort>` | Sort order: "newest" (default) or "oldest" (default: "newest") | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -### List traces - -```bash -# List last 20 traces (default) -sentry trace list - -# Sort by slowest first -sentry trace list --sort duration - -# Filter by transaction name, last 24 hours -sentry trace list -q "transaction:GET /api/users" --period 24h - -# Paginate through results -sentry trace list my-org/backend -c next -``` - -### View a trace - -```bash -# View trace details with span tree -sentry trace view abc123def456abc123def456abc12345 - -# Open trace in browser -sentry trace view abc123def456abc123def456abc12345 -w - -# Auto-recover from an issue short ID -sentry trace view PROJ-123 -``` - -### View trace logs - -```bash -# View logs for a trace -sentry trace logs abc123def456abc123def456abc12345 - -# Search with a longer time window -sentry trace logs --period 30d abc123def456abc123def456abc12345 - -# Filter logs within a trace -sentry trace logs -q 'level:error' abc123def456abc123def456abc12345 -``` diff --git a/docs/src/content/docs/commands/trial.md b/docs/src/content/docs/commands/trial.md deleted file mode 100644 index 8eaa739b0..000000000 --- a/docs/src/content/docs/commands/trial.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: trial -description: Trial commands for the Sentry CLI ---- - -Manage product trials - -## Commands - -### `sentry trial list <org>` - -List product trials - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org>` | Organization slug (auto-detected if omitted) | - -### `sentry trial start <name> <org>` - -Start a product trial - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<name>` | Trial name (seer, replays, performance, spans, profiling, logs, monitors, uptime, plan) | -| `<org>` | Organization slug (auto-detected if omitted) | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> - -## Examples - -```bash -# List all trials for the current org -sentry trial list - -# List trials for a specific org -sentry trial list my-org - -# Start a Seer trial -sentry trial start seer - -# Start a trial for a specific org -sentry trial start replays my-org - -# Start a Business plan trial (opens browser) -sentry trial start plan -``` diff --git a/docs/src/content/docs/commands/api.md b/docs/src/fragments/commands/api.md similarity index 52% rename from docs/src/content/docs/commands/api.md rename to docs/src/fragments/commands/api.md index 1214ac9bb..0a6fa9efc 100644 --- a/docs/src/content/docs/commands/api.md +++ b/docs/src/fragments/commands/api.md @@ -1,39 +1,4 @@ ---- -title: api -description: API command for the Sentry CLI ---- -Make an authenticated API request - -## Usage - -### `sentry api <endpoint>` - -Make an authenticated API request - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<endpoint>` | API endpoint relative to /api/0/ (e.g., organizations/) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-X, --method <method>` | The HTTP method for the request (default: "GET") | -| `-d, --data <data>` | Inline JSON body for the request (like curl -d) | -| `-F, --field <field>...` | Add a typed parameter (key=value, key[sub]=value, key[]=value) | -| `-f, --raw-field <raw-field>...` | Add a string parameter without JSON parsing | -| `-H, --header <header>...` | Add a HTTP request header in key:value format | -| `--input <input>` | The file to use as body for the HTTP request (use "-" to read from standard input) | -| `--silent` | Do not print the response body | -| `--verbose` | Include full HTTP request and response in the output | -| `-n, --dry-run` | Show the resolved request without sending it | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> ## Examples diff --git a/docs/src/content/docs/commands/auth.md b/docs/src/fragments/commands/auth.md similarity index 53% rename from docs/src/content/docs/commands/auth.md rename to docs/src/fragments/commands/auth.md index 278961982..0a0884d76 100644 --- a/docs/src/content/docs/commands/auth.md +++ b/docs/src/fragments/commands/auth.md @@ -1,66 +1,4 @@ ---- -title: auth -description: Auth commands for the Sentry CLI ---- -Authenticate with Sentry - -## Commands - -### `sentry auth login` - -Authenticate with Sentry - -**Options:** - -| Option | Description | -|--------|-------------| -| `--token <token>` | Authenticate using an API token instead of OAuth | -| `--timeout <timeout>` | Timeout for OAuth flow in seconds (default: 900) | -| `--force` | Re-authenticate without prompting | - -### `sentry auth logout` - -Log out of Sentry - -### `sentry auth refresh` - -Refresh your authentication token - -**Options:** - -| Option | Description | -|--------|-------------| -| `--force` | Force refresh even if token is still valid | - -### `sentry auth status` - -View authentication status - -**Options:** - -| Option | Description | -|--------|-------------| -| `--show-token` | Show the stored token (masked by default) | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry auth token` - -Print the stored authentication token - -### `sentry auth whoami` - -Show the currently authenticated user - -**Options:** - -| Option | Description | -|--------|-------------| -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> ## Examples diff --git a/docs/src/content/docs/commands/cli.md b/docs/src/fragments/commands/cli.md similarity index 52% rename from docs/src/content/docs/commands/cli.md rename to docs/src/fragments/commands/cli.md index 9f3d2cc96..a0aa5bc21 100644 --- a/docs/src/content/docs/commands/cli.md +++ b/docs/src/fragments/commands/cli.md @@ -1,70 +1,4 @@ ---- -title: cli -description: CLI commands for the Sentry CLI ---- -CLI-related commands - -## Commands - -### `sentry cli feedback <message...>` - -Send feedback about the CLI - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<message...>` | Your feedback message | - -### `sentry cli fix` - -Diagnose and repair CLI database issues - -**Options:** - -| Option | Description | -|--------|-------------| -| `--dry-run` | Show what would be fixed without making changes | - -### `sentry cli setup` - -Configure shell integration - -**Options:** - -| Option | Description | -|--------|-------------| -| `--install` | Install the binary from a temp location to the system path | -| `--method <method>` | Installation method (curl, npm, pnpm, bun, yarn) | -| `--channel <channel>` | Release channel to persist (stable or nightly) | -| `--no-modify-path` | Skip PATH modification | -| `--no-completions` | Skip shell completion installation | -| `--no-agent-skills` | Skip agent skill installation for AI coding assistants | -| `--quiet` | Suppress output (for scripted usage) | - -### `sentry cli upgrade <version>` - -Update the Sentry CLI to the latest version - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<version>` | Specific version (e.g. 0.5.0), or "nightly"/"stable" to switch channel; omit to update within current channel | - -**Options:** - -| Option | Description | -|--------|-------------| -| `--check` | Check for updates without installing | -| `--force` | Force upgrade even if already on the latest version | -| `--offline` | Upgrade using only cached version info and patches (no network) | -| `--method <method>` | Installation method to use (curl, brew, npm, pnpm, bun, yarn) | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> ## Examples diff --git a/docs/src/fragments/commands/dashboard.md b/docs/src/fragments/commands/dashboard.md new file mode 100644 index 000000000..a532548a9 --- /dev/null +++ b/docs/src/fragments/commands/dashboard.md @@ -0,0 +1,127 @@ + + +## Examples + +### List dashboards + +```bash +# List all dashboards +sentry dashboard list + +# Filter by name pattern +sentry dashboard list "Backend*" + +# Open dashboard list in browser +sentry dashboard list -w +``` + +``` +ID TITLE WIDGETS CREATED +12345 General 4 2024-01-15 +12346 Frontend Performance 6 2024-02-20 +12347 Backend Errors 3 2024-03-10 +``` + +### View a dashboard + +```bash +# View by title +sentry dashboard view 'Frontend Performance' + +# View by ID +sentry dashboard view 12345 + +# Auto-refresh every 30 seconds +sentry dashboard view "Backend Performance" --refresh 30 + +# Open in browser +sentry dashboard view 12345 -w +``` + +``` +Dashboard: Frontend Performance (ID: 12345) +URL: https://my-org.sentry.io/dashboard/12345/ + +Widgets: + #0 Error Count big_number count() + #1 Errors Over Time line count() + #2 Errors by Browser bar count() group by browser.name + #3 Top Endpoints table count(), p95(span.duration) group by transaction +``` + +### Create a dashboard + +```bash +sentry dashboard create 'Frontend Performance' +``` + +``` +Created dashboard: Frontend Performance (ID: 12348) +URL: https://my-org.sentry.io/dashboard/12348/ +``` + +### Add widgets + +```bash +# Simple counter widget +sentry dashboard widget add 'My Dashboard' "Error Count" \ + --display big_number --query count + +# Line chart with group-by +sentry dashboard widget add 'My Dashboard' "Errors by Browser" \ + --display line --query count --group-by browser.name + +# Table with multiple aggregates, sorted descending +sentry dashboard widget add 'My Dashboard' "Top Endpoints" \ + --display table \ + --query count --query p95:span.duration \ + --group-by transaction \ + --sort -count --limit 10 + +# With search filter +sentry dashboard widget add 'My Dashboard' "Slow Requests" \ + --display bar --query p95:span.duration \ + --where "span.op:http.client" \ + --group-by span.description +``` + +### Edit widgets + +```bash +# Change display type +sentry dashboard widget edit 12345 --title 'Error Count' --display bar + +# Rename a widget +sentry dashboard widget edit 'My Dashboard' --index 0 --new-title 'Total Errors' + +# Change the query +sentry dashboard widget edit 12345 --title 'Error Rate' --query p95:span.duration +``` + +### Delete widgets + +```bash +# Delete by title +sentry dashboard widget delete 'My Dashboard' --title 'Error Count' + +# Delete by index +sentry dashboard widget delete 12345 --index 2 +``` + +## Query Shorthand + +The `--query` flag supports shorthand for aggregate functions: + +| Input | Expands to | +|-------|-----------| +| `count` | `count()` | +| `p95:span.duration` | `p95(span.duration)` | +| `avg:span.duration` | `avg(span.duration)` | +| `count()` | `count()` (passthrough) | + +## Sort Shorthand + +| Input | Meaning | +|-------|---------| +| `count` | Sort by `count()` ascending | +| `-count` | Sort by `count()` descending | diff --git a/docs/src/fragments/commands/event.md b/docs/src/fragments/commands/event.md new file mode 100644 index 000000000..aee035756 --- /dev/null +++ b/docs/src/fragments/commands/event.md @@ -0,0 +1,42 @@ + + +## Examples + +```bash +sentry event view abc123def456abc123def456abc12345 +``` + +``` +Event: abc123def456abc123def456abc12345 +Issue: FRONT-ABC +Timestamp: 2024-01-20 14:22:00 + +Exception: + TypeError: Cannot read property 'foo' of undefined + at processData (app.js:123:45) + at handleClick (app.js:89:12) + at HTMLButtonElement.onclick (app.js:45:8) + +Tags: + browser: Chrome 120 + os: Windows 10 + environment: production + release: 1.2.3 + +Context: + url: https://example.com/app + user_id: 12345 +``` + +```bash +# Open in browser +sentry event view abc123def456abc123def456abc12345 -w +``` + +## Finding Event IDs + +Event IDs can be found: + +1. In the Sentry UI when viewing an issue's events +2. In the output of `sentry issue view` commands +3. In error reports sent to Sentry (as `event_id`) diff --git a/docs/src/fragments/commands/index.md b/docs/src/fragments/commands/index.md new file mode 100644 index 000000000..d1ab7faf7 --- /dev/null +++ b/docs/src/fragments/commands/index.md @@ -0,0 +1,26 @@ + + +## Global Options + +All commands support the following global options: + +- `--help` - Show help for the command +- `--version` - Show CLI version +- `--log-level <level>` - Set log verbosity (`error`, `warn`, `log`, `info`, `debug`, `trace`). Overrides `SENTRY_LOG_LEVEL` +- `--verbose` - Shorthand for `--log-level debug` + +## JSON Output + +Most list and view commands support `--json` flag for JSON output, making it easy to integrate with other tools: + +```bash +sentry org list --json | jq '.[] | .slug' +``` + +## Opening in Browser + +View commands support `-w` or `--web` flag to open the resource in your browser: + +```bash +sentry issue view PROJ-123 -w +``` diff --git a/docs/src/content/docs/commands/init.md b/docs/src/fragments/commands/init.md similarity index 68% rename from docs/src/content/docs/commands/init.md rename to docs/src/fragments/commands/init.md index 20970f459..226084c32 100644 --- a/docs/src/content/docs/commands/init.md +++ b/docs/src/fragments/commands/init.md @@ -1,35 +1,4 @@ ---- -title: init -description: Init command for the Sentry CLI ---- -Initialize Sentry in your project (experimental) - -## Usage - -### `sentry init <target> <directory>` - -Initialize Sentry in your project (experimental) - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<target>` | <org>/<project>, <org>/, <project>, or a directory path | -| `<directory>` | Project directory (default: current directory) | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-y, --yes` | Non-interactive mode (accept defaults) | -| `-n, --dry-run` | Show what would happen without making changes | -| `--features <features>...` | Features to enable: errors,tracing,logs,replay,metrics,profiling,sourcemaps,crons,ai-monitoring,user-feedback | -| `-t, --team <team>` | Team slug to create the project under | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> > **Experimental:** `sentry init` is experimental and may modify your source files. Always review changes before committing. diff --git a/docs/src/fragments/commands/issue.md b/docs/src/fragments/commands/issue.md new file mode 100644 index 000000000..e47f42cea --- /dev/null +++ b/docs/src/fragments/commands/issue.md @@ -0,0 +1,87 @@ + + +## Examples + +### List issues + +```bash +# List issues in a specific project +sentry issue list my-org/frontend + +# All projects in an org +sentry issue list my-org/ + +# Search for a project across organizations +sentry issue list frontend +``` + +``` +ID SHORT ID TITLE COUNT USERS +123456789 FRONT-ABC TypeError: Cannot read prop... 1.2k 234 +987654321 FRONT-DEF ReferenceError: x is not de... 456 89 +``` + +**Filter by status:** + +```bash +# Show only unresolved issues +sentry issue list my-org/frontend --query "is:unresolved" + +# Show resolved issues +sentry issue list my-org/frontend --query "is:resolved" + +# Sort by frequency +sentry issue list my-org/frontend --sort freq --limit 20 +``` + +### View an issue + +```bash +sentry issue view FRONT-ABC +``` + +``` +Issue: TypeError: Cannot read property 'foo' of undefined +Short ID: FRONT-ABC +Status: unresolved +First seen: 2024-01-15 10:30:00 +Last seen: 2024-01-20 14:22:00 +Events: 1,234 +Users affected: 234 + +Latest event: + Browser: Chrome 120 + OS: Windows 10 + URL: https://example.com/app +``` + +```bash +# Open in browser +sentry issue view FRONT-ABC -w +``` + +### Explain and plan with Seer AI + +```bash +# Analyze root cause (may take a few minutes for new issues) +sentry issue explain 123456789 + +# By short ID with org prefix +sentry issue explain my-org/MYPROJECT-ABC + +# Force a fresh analysis +sentry issue explain 123456789 --force + +# Generate a fix plan (requires explain to be run first) +sentry issue plan 123456789 + +# Specify which root cause to plan for +sentry issue plan 123456789 --cause 0 +``` + +**Requirements:** + +- Seer AI enabled for your organization +- GitHub integration configured with repository access +- Code mappings set up to link stack frames to source files +- Root cause analysis must be completed (`sentry issue explain`) before generating a plan diff --git a/docs/src/content/docs/commands/log.md b/docs/src/fragments/commands/log.md similarity index 58% rename from docs/src/content/docs/commands/log.md rename to docs/src/fragments/commands/log.md index dcbd6b470..00ff24276 100644 --- a/docs/src/content/docs/commands/log.md +++ b/docs/src/fragments/commands/log.md @@ -1,53 +1,4 @@ ---- -title: log -description: Log commands for the Sentry CLI ---- -View Sentry logs - -## Commands - -### `sentry log list <org/project-or-trace-id...>` - -List logs from a project - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project-or-trace-id...>` | [<org>/[<project>/]]<trace-id>, <org>/<project>, or <project> | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-n, --limit <limit>` | Number of log entries (1-1000) (default: "100") | -| `-q, --query <query>` | Filter query (Sentry search syntax) | -| `-f, --follow <follow>` | Stream logs (optionally specify poll interval in seconds) | -| `-t, --period <period>` | Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" | -| `-s, --sort <sort>` | Sort order: "newest" (default) or "oldest" (default: "newest") | -| `--fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -### `sentry log view <org/project/log-id...>` - -View details of one or more log entries - -**Arguments:** - -| Argument | Description | -|----------|-------------| -| `<org/project/log-id...>` | [<org>/<project>] <log-id> [<log-id>...] - Target (optional) and one or more log IDs | - -**Options:** - -| Option | Description | -|--------|-------------| -| `-w, --web` | Open in browser | -| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data | - -All commands support `--json` for machine-readable output and `--fields` to select specific JSON fields. - -<!-- GENERATED:END --> ## Examples diff --git a/docs/src/fragments/commands/org.md b/docs/src/fragments/commands/org.md new file mode 100644 index 000000000..d102dfde4 --- /dev/null +++ b/docs/src/fragments/commands/org.md @@ -0,0 +1,36 @@ + + +## Examples + +```bash +# List organizations +sentry org list +``` + +``` +SLUG NAME ROLE +my-org My Organization owner +another-org Another Org member +``` + +```bash +# View organization details +sentry org view my-org +``` + +``` +Organization: My Organization +Slug: my-org +Role: owner +Projects: 5 +Teams: 3 +Members: 12 +``` + +```bash +# Open in browser +sentry org view my-org -w + +# JSON output +sentry org list --json +``` diff --git a/docs/src/fragments/commands/project.md b/docs/src/fragments/commands/project.md new file mode 100644 index 000000000..ba0f401f8 --- /dev/null +++ b/docs/src/fragments/commands/project.md @@ -0,0 +1,59 @@ + + +## Examples + +```bash +# List all projects in an org +sentry project list my-org/ +``` + +``` +ORG SLUG PLATFORM TEAM +my-org frontend javascript web-team +my-org backend python api-team +my-org mobile-ios cocoa mobile-team +``` + +```bash +# Filter by platform +sentry project list my-org/ --platform javascript + +# View project details +sentry project view my-org/frontend +``` + +``` +Project: frontend +Organization: my-org +Platform: javascript +Team: web-team +DSN: https://abc123@sentry.io/123456 +``` + +```bash +# Open project in browser +sentry project view my-org/frontend -w +``` + +### Create a project + +```bash +# Create a new project +sentry project create my-new-app javascript-nextjs + +# Create under a specific org and team +sentry project create my-org/my-new-app python --team backend-team + +# Preview without creating +sentry project create my-new-app node --dry-run +``` + +### Delete a project + +```bash +# Delete a project (will prompt for confirmation) +sentry project delete my-org/old-project + +# Delete without confirmation +sentry project delete my-org/old-project --yes +``` diff --git a/docs/src/fragments/commands/release.md b/docs/src/fragments/commands/release.md new file mode 100644 index 000000000..a3b862501 --- /dev/null +++ b/docs/src/fragments/commands/release.md @@ -0,0 +1,50 @@ + + +## Examples + +```bash +# List releases (auto-detect org) +sentry release list + +# List releases in a specific org +sentry release list my-org/ + +# View release details +sentry release view 1.0.0 +sentry release view my-org/1.0.0 + +# Create and finalize a release +sentry release create 1.0.0 --finalize + +# Create a release, then finalize separately +sentry release create 1.0.0 +sentry release set-commits 1.0.0 --auto +sentry release finalize 1.0.0 + +# Set commits from local git history +sentry release set-commits 1.0.0 --local + +# Create a deploy +sentry release deploy 1.0.0 production +sentry release deploy 1.0.0 staging "Deploy #42" + +# Propose a version from git HEAD +sentry release create $(sentry release propose-version) + +# Output as JSON +sentry release list --json +sentry release view 1.0.0 --json + +# Full release workflow with explicit org +sentry release create my-org/1.0.0 --project my-project +sentry release set-commits my-org/1.0.0 --auto +sentry release finalize my-org/1.0.0 +sentry release deploy my-org/1.0.0 production +``` + +## Important Notes + +- **Version matching**: The release version must match the `release` value in your `Sentry.init()` call. If your SDK uses `"1.0.0"`, create the release as `sentry release create org/1.0.0` (version = `1.0.0`), **not** `sentry release create org/myapp/1.0.0`. +- **The `org/` prefix is the org slug**: In `sentry release create sentry/1.0.0`, `sentry` is the org slug and `1.0.0` is the version. The `/` separates org from version — it is not part of the version string. +- **`--auto` needs a git checkout**: The `--auto` flag lists repos from the Sentry API and matches against your local `origin` remote URL. Without a local git repo, use `--local` instead. +- **Default mode tries `--auto` first**: When neither `--auto` nor `--local` is specified, `set-commits` tries auto-discovery first and falls back to local git history if the integration isn't configured. diff --git a/docs/src/fragments/commands/repo.md b/docs/src/fragments/commands/repo.md new file mode 100644 index 000000000..e62b2a747 --- /dev/null +++ b/docs/src/fragments/commands/repo.md @@ -0,0 +1,14 @@ + + +## Examples + +```bash +# List repositories (auto-detect org) +sentry repo list + +# List repos in a specific org with pagination +sentry repo list my-org/ -c next + +# Output as JSON +sentry repo list --json +``` diff --git a/docs/src/fragments/commands/schema.md b/docs/src/fragments/commands/schema.md new file mode 100644 index 000000000..8983ad548 --- /dev/null +++ b/docs/src/fragments/commands/schema.md @@ -0,0 +1,20 @@ + + +## Examples + +```bash +# List all API resources +sentry schema + +# Browse issue endpoints +sentry schema issues + +# View details for a specific operation +sentry schema issues list + +# Search for monitoring-related endpoints +sentry schema --search monitor + +# Flat list of every endpoint +sentry schema --all +``` diff --git a/docs/src/fragments/commands/sourcemap.md b/docs/src/fragments/commands/sourcemap.md new file mode 100644 index 000000000..ba5af15f0 --- /dev/null +++ b/docs/src/fragments/commands/sourcemap.md @@ -0,0 +1,29 @@ + + +## Examples + +### Inject debug IDs + +```bash +# Inject debug IDs into all JS files in dist/ +sentry sourcemap inject ./dist + +# Preview changes without writing +sentry sourcemap inject ./dist --dry-run + +# Only process specific extensions +sentry sourcemap inject ./build --ext .js,.mjs +``` + +### Upload sourcemaps + +```bash +# Upload sourcemaps from dist/ +sentry sourcemap upload ./dist + +# Associate with a release +sentry sourcemap upload ./dist --release 1.0.0 + +# Set a custom URL prefix +sentry sourcemap upload ./dist --url-prefix '~/static/js/' +``` diff --git a/docs/src/fragments/commands/span.md b/docs/src/fragments/commands/span.md new file mode 100644 index 000000000..65598084f --- /dev/null +++ b/docs/src/fragments/commands/span.md @@ -0,0 +1,35 @@ + + +## Examples + +### List spans + +```bash +# List recent spans in the current project +sentry span list + +# Find all DB spans +sentry span list -q "op:db" + +# Slow spans in the last 24 hours +sentry span list -q "duration:>100ms" --period 24h + +# List spans within a specific trace +sentry span list abc123def456abc123def456abc12345 + +# Paginate through results +sentry span list -c next +``` + +### View spans + +```bash +# View a single span +sentry span view abc123def456abc123def456abc12345 a1b2c3d4e5f67890 + +# View multiple spans at once +sentry span view abc123def456abc123def456abc12345 a1b2c3d4e5f67890 b2c3d4e5f6789012 + +# With explicit org/project +sentry span view my-org/backend/abc123def456abc123def456abc12345 a1b2c3d4e5f67890 +``` diff --git a/docs/src/fragments/commands/team.md b/docs/src/fragments/commands/team.md new file mode 100644 index 000000000..3606123f4 --- /dev/null +++ b/docs/src/fragments/commands/team.md @@ -0,0 +1,14 @@ + + +## Examples + +```bash +# List teams +sentry team list my-org/ + +# Paginate through teams +sentry team list my-org/ -c next + +# Output as JSON +sentry team list --json +``` diff --git a/docs/src/fragments/commands/trace.md b/docs/src/fragments/commands/trace.md new file mode 100644 index 000000000..b426c61b1 --- /dev/null +++ b/docs/src/fragments/commands/trace.md @@ -0,0 +1,45 @@ + + +## Examples + +### List traces + +```bash +# List last 20 traces (default) +sentry trace list + +# Sort by slowest first +sentry trace list --sort duration + +# Filter by transaction name, last 24 hours +sentry trace list -q "transaction:GET /api/users" --period 24h + +# Paginate through results +sentry trace list my-org/backend -c next +``` + +### View a trace + +```bash +# View trace details with span tree +sentry trace view abc123def456abc123def456abc12345 + +# Open trace in browser +sentry trace view abc123def456abc123def456abc12345 -w + +# Auto-recover from an issue short ID +sentry trace view PROJ-123 +``` + +### View trace logs + +```bash +# View logs for a trace +sentry trace logs abc123def456abc123def456abc12345 + +# Search with a longer time window +sentry trace logs --period 30d abc123def456abc123def456abc12345 + +# Filter logs within a trace +sentry trace logs -q 'level:error' abc123def456abc123def456abc12345 +``` diff --git a/docs/src/fragments/commands/trial.md b/docs/src/fragments/commands/trial.md new file mode 100644 index 000000000..0847a9be6 --- /dev/null +++ b/docs/src/fragments/commands/trial.md @@ -0,0 +1,20 @@ + + +## Examples + +```bash +# List all trials for the current org +sentry trial list + +# List trials for a specific org +sentry trial list my-org + +# Start a Seer trial +sentry trial start seer + +# Start a trial for a specific org +sentry trial start replays my-org + +# Start a Business plan trial (opens browser) +sentry trial start plan +``` diff --git a/package.json b/package.json index 888eb065b..80870ae03 100644 --- a/package.json +++ b/package.json @@ -71,25 +71,25 @@ "@sentry/core@10.47.0": "patches/@sentry%2Fcore@10.47.0.patch" }, "scripts": { - "dev": "bun run generate:schema && bun run generate:skill && bun run generate:sdk && bun run src/bin.ts", - "build": "bun run generate:schema && bun run generate:skill && bun run generate:sdk && bun run script/build.ts --single", - "build:all": "bun run generate:schema && bun run generate:skill && bun run generate:sdk && bun run script/build.ts", - "bundle": "bun run generate:schema && bun run generate:skill && bun run generate:sdk && bun run script/bundle.ts", - "typecheck": "bun run generate:skill && bun run generate:sdk && tsc --noEmit", + "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", + "bundle": "bun run generate:schema && bun run generate:docs && bun run generate:sdk && bun run script/bundle.ts", + "typecheck": "bun run generate:docs && bun run generate:sdk && tsc --noEmit", "lint": "bunx ultracite check", "lint:fix": "bunx ultracite fix", "test": "bun run test:unit && bun run test:isolated", - "test:unit": "bun run generate:skill && bun run generate:sdk && bun test --timeout 15000 test/lib test/commands test/types --coverage --coverage-reporter=lcov", - "test:isolated": "bun run generate:skill && bun run generate:sdk && bun test --timeout 15000 test/isolated", - "test:e2e": "bun run generate:skill && bun run generate:sdk && bun test --timeout 15000 test/e2e", + "test:unit": "bun run generate:docs && bun run generate:sdk && bun test --timeout 15000 test/lib test/commands test/types --coverage --coverage-reporter=lcov", + "test:isolated": "bun run generate:docs && bun run generate:sdk && bun test --timeout 15000 test/isolated", + "test:e2e": "bun run generate:docs && bun run generate:sdk && bun test --timeout 15000 test/e2e", "test:init-eval": "bun test test/init-eval --timeout 600000 --concurrency 6", "generate:sdk": "bun run script/generate-sdk.ts", "generate:skill": "bun run script/generate-skill.ts", + "generate:docs": "bun run generate:command-docs && bun run generate:skill", "generate:schema": "bun run script/generate-api-schema.ts", "generate:command-docs": "bun run script/generate-command-docs.ts", "eval:skill": "bun run script/eval-skill.ts", - "check:skill": "bun run script/check-skill.ts", - "check:command-docs": "bun run script/check-command-docs.ts", + "check:fragments": "bun run script/check-fragments.ts", "check:deps": "bun run script/check-no-deps.ts", "check:errors": "bun run script/check-error-patterns.ts" }, diff --git a/plugins/README.md b/plugins/README.md index 21ad163d6..afa8d0ad4 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -81,10 +81,10 @@ The SKILL.md file is **auto-generated** from the CLI's command definitions. Do n To regenerate after modifying commands: ```bash -bun run generate:skill +bun run generate:docs ``` -CI will fail if SKILL.md is out of date and post a comment with the required changes. +CI will auto-commit updated skill files when they are stale. ## License diff --git a/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md b/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md index e1f837354..49d258cea 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/dashboard.md @@ -42,7 +42,7 @@ View a dashboard - `-w, --web - Open in browser` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` - `-r, --refresh <value> - Auto-refresh interval in seconds (default: 60, min: 10)` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07"` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01"` **Examples:** diff --git a/plugins/sentry-cli/skills/sentry-cli/references/event.md b/plugins/sentry-cli/skills/sentry-cli/references/event.md index 573eb2e1d..b15aefe06 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/event.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/event.md @@ -28,7 +28,7 @@ List events for an issue - `-n, --limit <value> - Number of events (1-1000) - (default: "25")` - `-q, --query <value> - Search query (Sentry search syntax)` - `--full - Include full event body (stacktraces)` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-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)` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/issue.md b/plugins/sentry-cli/skills/sentry-cli/references/issue.md index 197f9da95..a637796c8 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/issue.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/issue.md @@ -19,7 +19,7 @@ List issues in a project - `-q, --query <value> - Search query (Sentry search syntax)` - `-n, --limit <value> - Maximum number of issues to list - (default: "25")` - `-s, --sort <value> - Sort by: date, new, freq, user - (default: "date")` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "90d")` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" - (default: "90d")` - `-c, --cursor <value> - Pagination cursor (use "next" for next page, "prev" for previous)` - `--compact - Single-line rows for compact output (auto-detects if omitted)` - `-f, --fresh - Bypass cache, re-detect projects, and fetch fresh data` @@ -78,7 +78,7 @@ List events for a specific issue - `-n, --limit <value> - Number of events (1-1000) - (default: "25")` - `-q, --query <value> - Search query (Sentry search syntax)` - `--full - Include full event body (stacktraces)` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-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)` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/log.md b/plugins/sentry-cli/skills/sentry-cli/references/log.md index a75fd06e0..41bd1ceb8 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/log.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/log.md @@ -19,7 +19,7 @@ List logs from a project - `-n, --limit <value> - Number of log entries (1-1000) - (default: "100")` - `-q, --query <value> - Filter query (Sentry search syntax)` - `-f, --follow <value> - Stream logs (optionally specify poll interval in seconds)` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07"` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01"` - `-s, --sort <value> - Sort order: "newest" (default) or "oldest" - (default: "newest")` - `--fresh - Bypass cache, re-detect projects, and fetch fresh data` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/span.md b/plugins/sentry-cli/skills/sentry-cli/references/span.md index 0bba2e955..81ef6d740 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/span.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/span.md @@ -19,7 +19,7 @@ List spans in a project or trace - `-n, --limit <value> - Number of spans (<=1000) - (default: "25")` - `-q, --query <value> - Filter spans (e.g., "op:db", "duration:>100ms", "project:backend")` - `-s, --sort <value> - Sort order: date, duration - (default: "date")` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-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)` diff --git a/plugins/sentry-cli/skills/sentry-cli/references/trace.md b/plugins/sentry-cli/skills/sentry-cli/references/trace.md index dbbd6e8aa..623a682bb 100644 --- a/plugins/sentry-cli/skills/sentry-cli/references/trace.md +++ b/plugins/sentry-cli/skills/sentry-cli/references/trace.md @@ -19,7 +19,7 @@ List recent traces in a project - `-n, --limit <value> - Number of traces (1-1000) - (default: "25")` - `-q, --query <value> - Search query (Sentry search syntax)` - `-s, --sort <value> - Sort by: date, duration - (default: "date")` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "7d")` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-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)` @@ -78,7 +78,7 @@ View logs associated with a trace **Flags:** - `-w, --web - Open trace in browser` -- `-t, --period <value> - Time range: "7d", "2026-03-07..2026-04-07", ">=2026-03-07" - (default: "14d")` +- `-t, --period <value> - Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" - (default: "14d")` - `-n, --limit <value> - Number of log entries (<=1000) - (default: "100")` - `-q, --query <value> - Additional filter query (Sentry search syntax)` - `-s, --sort <value> - Sort order: "newest" (default) or "oldest" - (default: "newest")` diff --git a/script/check-command-docs.ts b/script/check-command-docs.ts deleted file mode 100644 index 97451b856..000000000 --- a/script/check-command-docs.ts +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env bun -/** - * Check Command Documentation for Staleness - * - * Compares the auto-generated reference sections of command doc pages - * against freshly generated content. Only the portion above the - * GENERATED:END marker is checked — hand-written custom content below - * the marker is not compared. - * - * Usage: - * bun run script/check-command-docs.ts - * - * Exit codes: - * 0 - All command docs are up to date - * 1 - One or more doc pages have stale reference sections - */ - -import { $ } from "bun"; - -const DOCS_DIR = "docs/src/content/docs/commands"; -const MARKER = "<!-- GENERATED:END -->"; - -/** - * Extract the auto-generated portion of a file (everything up to and - * including the GENERATED:END marker). Returns the full content if - * no marker is found. - */ -function extractGeneratedPortion(content: string): string { - const markerIndex = content.indexOf(MARKER); - if (markerIndex === -1) { - return content; - } - return content.slice(0, markerIndex + MARKER.length); -} - -/** - * Read all command doc files and extract their generated portions. - * Returns a map of filename → generated content. - */ -async function readGeneratedPortions(): Promise<Map<string, string>> { - const files = new Map<string, string>(); - const glob = new Bun.Glob("*.md"); - - for await (const filename of glob.scan({ cwd: DOCS_DIR })) { - const file = Bun.file(`${DOCS_DIR}/${filename}`); - const content = await file.text(); - files.set(filename, extractGeneratedPortion(content)); - } - - return files; -} - -// Snapshot committed generated portions -const committedPortions = await readGeneratedPortions(); - -// Regenerate (preserves custom content below markers) -await $`bun run script/generate-command-docs.ts`.quiet(); - -// Read freshly generated portions -const newPortions = await readGeneratedPortions(); - -// Compare -const staleFiles: string[] = []; - -for (const [filename, newContent] of newPortions) { - const committedContent = committedPortions.get(filename); - if (committedContent !== newContent) { - staleFiles.push(filename); - } -} - -// Check for files that should exist but don't (committed but not generated) -for (const filename of committedPortions.keys()) { - if (!newPortions.has(filename)) { - staleFiles.push(`${filename} (unexpected — not generated)`); - } -} - -if (staleFiles.length === 0) { - console.log("✓ All command docs are up to date"); - process.exit(0); -} - -console.error("✗ Command docs are out of date:"); -for (const file of staleFiles) { - console.error(` - ${file}`); -} -console.error(""); -console.error( - "Run 'bun run generate:command-docs' locally and commit the changes." -); - -process.exit(1); diff --git a/script/check-fragments.ts b/script/check-fragments.ts new file mode 100644 index 000000000..0ad95abf2 --- /dev/null +++ b/script/check-fragments.ts @@ -0,0 +1,99 @@ +#!/usr/bin/env bun +/** + * Validate command doc fragment files. + * + * Ensures fragment files in docs/src/fragments/commands/ stay consistent + * with the CLI route tree: + * 1. Every route has a corresponding fragment file (+ index.md) + * 2. Every fragment file corresponds to an existing route (or is index.md) + * 3. Fragment files don't accidentally contain frontmatter or the generated marker + * + * Usage: + * bun run script/check-fragments.ts + */ + +import { readdirSync } from "node:fs"; +import { routes } from "../src/app.js"; +import type { RouteMap } from "../src/lib/introspect.js"; +import { extractAllRoutes } from "../src/lib/introspect.js"; + +const FRAGMENTS_DIR = "docs/src/fragments/commands"; +const GENERATED_END_MARKER = "<!-- GENERATED:END -->"; + +/** Routes that don't have doc pages (and therefore no fragments) */ +const SKIP_ROUTES = new Set(["help"]); + +const MD_EXTENSION_RE = /\.md$/; + +const routeMap = routes as unknown as RouteMap; +const routeNames = new Set( + extractAllRoutes(routeMap) + .filter((r) => !SKIP_ROUTES.has(r.name)) + .map((r) => r.name) +); + +// Expected fragment files: one per route + index +const expectedFragments = new Set([...routeNames, "index"]); + +let fragmentFiles: string[]; +try { + fragmentFiles = readdirSync(FRAGMENTS_DIR).filter((f) => + MD_EXTENSION_RE.test(f) + ); +} catch { + console.error(`ERROR: Fragment directory not found: ${FRAGMENTS_DIR}`); + process.exit(1); +} + +const actualFragments = new Set( + fragmentFiles.map((f) => f.replace(MD_EXTENSION_RE, "")) +); + +const errors: string[] = []; + +// Check 1: Every route has a fragment +for (const name of expectedFragments) { + if (!actualFragments.has(name)) { + errors.push( + `Missing fragment: ${FRAGMENTS_DIR}/${name}.md (route "${name}" exists but has no fragment file)` + ); + } +} + +// Check 2: Every fragment corresponds to a route +for (const name of actualFragments) { + if (!expectedFragments.has(name)) { + errors.push( + `Stale fragment: ${FRAGMENTS_DIR}/${name}.md (no matching route found — delete it or add the route)` + ); + } +} + +// Check 3: Fragment content validation +for (const file of fragmentFiles) { + const content = await Bun.file(`${FRAGMENTS_DIR}/${file}`).text(); + + if (content.includes("---\ntitle:") || content.startsWith("---\n")) { + errors.push( + `Fragment contains frontmatter: ${FRAGMENTS_DIR}/${file} (fragments should only contain custom content, not YAML frontmatter)` + ); + } + + if (content.includes(GENERATED_END_MARKER)) { + errors.push( + `Fragment contains generated marker: ${FRAGMENTS_DIR}/${file} (the "${GENERATED_END_MARKER}" marker should not appear in fragment files)` + ); + } +} + +if (errors.length > 0) { + console.error(`Found ${errors.length} fragment validation error(s):\n`); + for (const err of errors) { + console.error(` ✗ ${err}`); + } + process.exit(1); +} + +console.log( + `All ${actualFragments.size} fragment files valid (${routeNames.size} routes + index)` +); diff --git a/script/check-skill.ts b/script/check-skill.ts deleted file mode 100644 index 32b926ba8..000000000 --- a/script/check-skill.ts +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env bun -/** - * Check Skill Files for Staleness - * - * Compares committed skill files (SKILL.md, references/*.md, index.json) - * against freshly generated content. - * - * Usage: - * bun run script/check-skill.ts - * - * Exit codes: - * 0 - All skill files are up to date - * 1 - One or more skill files are stale - */ - -import { $ } from "bun"; - -const SKILL_DIR = "plugins/sentry-cli/skills/sentry-cli"; -const INDEX_JSON_PATH = "docs/public/.well-known/skills/index.json"; - -/** - * Read all .md files under the skill directory + the index.json. - * Returns a map of relative path → content. - * - * Note: src/generated/skill-content.ts is NOT checked here because it is - * gitignored (regenerated at build time). The markdown files and index.json - * are the committed artifacts; if they are in sync, skill-content.ts will - * also be correct since the generator produces both in the same run. - */ -async function readAllSkillFiles(): Promise<Map<string, string>> { - const files = new Map<string, string>(); - - // Read SKILL.md - const skillFile = Bun.file(`${SKILL_DIR}/SKILL.md`); - if (await skillFile.exists()) { - files.set("SKILL.md", await skillFile.text()); - } - - // Read references/*.md - const glob = new Bun.Glob("references/*.md"); - for await (const path of glob.scan({ cwd: SKILL_DIR })) { - const file = Bun.file(`${SKILL_DIR}/${path}`); - files.set(path, await file.text()); - } - - // Read index.json - const indexFile = Bun.file(INDEX_JSON_PATH); - if (await indexFile.exists()) { - files.set("index.json", await indexFile.text()); - } - - return files; -} - -// Snapshot committed files -const committedFiles = await readAllSkillFiles(); - -// Regenerate -await $`bun run script/generate-skill.ts`.quiet(); - -// Read freshly generated files -const newFiles = await readAllSkillFiles(); - -// Compare -const staleFiles: string[] = []; - -// Check for changed or new files -for (const [path, newContent] of newFiles) { - const committedContent = committedFiles.get(path); - if (committedContent !== newContent) { - staleFiles.push(path); - } -} - -// Check for files that were removed (exist in committed but not in new) -for (const path of committedFiles.keys()) { - if (!newFiles.has(path)) { - staleFiles.push(`${path} (removed)`); - } -} - -// Check that every reference file contains at least one **Examples:** section. -// This catches cases where doc pages are missing bash code blocks that the -// skill generator needs to populate examples for AI agents. -const missingExamples: string[] = []; -for (const [path, content] of newFiles) { - if (!path.startsWith("references/")) { - continue; - } - if (!content.includes("**Examples:**")) { - missingExamples.push(path); - } -} - -const issues: string[] = []; - -if (staleFiles.length > 0) { - issues.push("Skill files are out of date:"); - for (const file of staleFiles) { - issues.push(` - ${file}`); - } - issues.push(""); - issues.push("Run 'bun run generate:skill' locally and commit the changes."); -} - -if (missingExamples.length > 0) { - if (issues.length > 0) { - issues.push(""); - } - issues.push("Skill reference files missing examples:"); - for (const file of missingExamples) { - issues.push(` - ${file}`); - } - issues.push(""); - issues.push( - "Add bash code blocks to the matching docs/src/content/docs/commands/ pages" - ); - issues.push("and re-run 'bun run generate:skill' to populate examples."); -} - -if (issues.length === 0) { - console.log("✓ All skill files are up to date"); - process.exit(0); -} - -for (const line of issues) { - console.error(line.startsWith(" ") ? line : `✗ ${line}`); -} - -process.exit(1); diff --git a/script/generate-command-docs.ts b/script/generate-command-docs.ts index d658e4160..f1844a297 100644 --- a/script/generate-command-docs.ts +++ b/script/generate-command-docs.ts @@ -6,11 +6,12 @@ * pages for the documentation website. Flags, arguments, and aliases are * extracted directly from source code, preventing documentation drift. * - * Each page has two sections separated by a marker comment: - * 1. Auto-generated reference (above marker) — flags, args, descriptions - * 2. Hand-written custom content (below marker) — examples, guides, tips + * Each generated page combines: + * 1. Auto-generated reference — flags, args, descriptions (from CLI metadata) + * 2. Hand-written fragment — examples, guides, tips (from docs/src/fragments/commands/) * - * Custom content below the marker is preserved across regeneration. + * The generated output is gitignored. Fragment files are the committed + * source of truth for custom content. * * Usage: * bun run script/generate-command-docs.ts @@ -20,7 +21,7 @@ * docs/src/content/docs/commands/index.md (commands overview table) */ -import { rmSync } from "node:fs"; +import { mkdirSync, rmSync } from "node:fs"; import { routes } from "../src/app.js"; import type { CommandInfo, @@ -32,6 +33,7 @@ import type { import { extractAllRoutes } from "../src/lib/introspect.js"; const DOCS_DIR = "docs/src/content/docs/commands"; +const FRAGMENTS_DIR = "docs/src/fragments/commands"; const INDEX_PATH = `${DOCS_DIR}/index.md`; /** @@ -264,21 +266,18 @@ function generateCommandsTable(allRoutes: RouteInfo[]): string { } // --------------------------------------------------------------------------- -// Custom Content Preservation +// Custom Content (Fragment Files) // --------------------------------------------------------------------------- /** - * Read existing custom content from below the GENERATED:END marker. - * Returns empty string if no marker found or file doesn't exist. + * Read hand-written custom content from a fragment file. + * Fragment files live in docs/src/fragments/commands/ and contain only + * the custom sections (examples, guides) — no frontmatter or generated content. + * Returns empty string if the fragment file doesn't exist. */ -async function readCustomContent(filePath: string): Promise<string> { +async function readCustomContent(fragmentName: string): Promise<string> { try { - const content = await Bun.file(filePath).text(); - const markerIndex = content.indexOf(GENERATED_END_MARKER); - if (markerIndex === -1) { - return ""; - } - return content.slice(markerIndex + GENERATED_END_MARKER.length); + return await Bun.file(`${FRAGMENTS_DIR}/${fragmentName}.md`).text(); } catch { return ""; } @@ -295,6 +294,9 @@ const routeInfos = extractAllRoutes(routeMap).filter( const generatedFiles: string[] = []; +// Ensure output directory exists (it's gitignored, may be absent on fresh checkout) +mkdirSync(DOCS_DIR, { recursive: true }); + // Clean up legacy cli/ subdirectory if it exists (we now use cli.md) try { rmSync(`${DOCS_DIR}/cli`, { recursive: true, force: true }); @@ -306,7 +308,7 @@ try { for (const route of routeInfos) { const filePath = `${DOCS_DIR}/${route.name}.md`; const pageContent = generatePage(route); - const customContent = await readCustomContent(filePath); + const customContent = await readCustomContent(route.name); const fullContent = customContent ? pageContent + customContent : `${pageContent}\n`; @@ -316,7 +318,7 @@ for (const route of routeInfos) { } // Update commands/index.md -const indexCustomContent = await readCustomContent(INDEX_PATH); +const indexCustomContent = await readCustomContent("index"); const indexLines: string[] = []; indexLines.push("---"); indexLines.push("title: Commands"); diff --git a/src/lib/time-range.ts b/src/lib/time-range.ts index 7b10c67d7..56ee39549 100644 --- a/src/lib/time-range.ts +++ b/src/lib/time-range.ts @@ -59,15 +59,21 @@ const UNIT_SECONDS: Record<string, number> = { const PERIOD_UNITS = new Set(Object.keys(UNIT_SECONDS)); /** - * Dynamic example dates relative to "today" so examples never look stale. - * Computed once at module load. + * Example dates for --period help text, snapped to the 1st of the month so + * they only change ~12×/year instead of daily. Keeps examples looking current + * without causing constant regeneration churn in committed skill files. */ const EXAMPLE_START = (() => { const d = new Date(); + d.setDate(1); d.setMonth(d.getMonth() - 1); return d.toISOString().slice(0, 10); })(); -const EXAMPLE_END = new Date().toISOString().slice(0, 10); +const EXAMPLE_END = (() => { + const d = new Date(); + d.setDate(1); + return d.toISOString().slice(0, 10); +})(); /** Brief text for --period flag help, shared across commands */ export const PERIOD_BRIEF = `Time range: "7d", "${EXAMPLE_START}..${EXAMPLE_END}", ">=${EXAMPLE_START}"`; From 42febe57b12c773fe09307b58b76b2628fb1ad63 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya <byk@sentry.io> Date: Thu, 9 Apr 2026 10:11:56 +0000 Subject: [PATCH 2/2] fix(docs): create skill-content stub before importing route tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit generate-command-docs.ts imports src/app.js which transitively imports agent-skills.ts → skill-content.ts. On fresh CI checkouts the file doesn't exist yet. Use dynamic import() after writing a minimal stub to break the circular dependency with generate:skill. --- script/check-fragments.ts | 17 ++++++++++++++--- script/generate-command-docs.ts | 20 ++++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/script/check-fragments.ts b/script/check-fragments.ts index 0ad95abf2..44fcf661b 100644 --- a/script/check-fragments.ts +++ b/script/check-fragments.ts @@ -12,10 +12,21 @@ * bun run script/check-fragments.ts */ -import { readdirSync } from "node:fs"; -import { routes } from "../src/app.js"; +import { mkdirSync, readdirSync } from "node:fs"; import type { RouteMap } from "../src/lib/introspect.js"; -import { extractAllRoutes } from "../src/lib/introspect.js"; + +// Ensure skill-content stub exists (see generate-command-docs.ts for rationale) +const SKILL_CONTENT_PATH = "src/generated/skill-content.ts"; +if (!(await Bun.file(SKILL_CONTENT_PATH).exists())) { + mkdirSync("src/generated", { recursive: true }); + await Bun.write( + SKILL_CONTENT_PATH, + "export const SKILL_FILES: [string, string][] = [];\n" + ); +} + +const { routes } = await import("../src/app.js"); +const { extractAllRoutes } = await import("../src/lib/introspect.js"); const FRAGMENTS_DIR = "docs/src/fragments/commands"; const GENERATED_END_MARKER = "<!-- GENERATED:END -->"; diff --git a/script/generate-command-docs.ts b/script/generate-command-docs.ts index f1844a297..5568fcfc6 100644 --- a/script/generate-command-docs.ts +++ b/script/generate-command-docs.ts @@ -22,7 +22,21 @@ */ import { mkdirSync, rmSync } from "node:fs"; -import { routes } from "../src/app.js"; + +// Ensure src/generated/skill-content.ts exists before importing the route tree. +// The route tree transitively imports agent-skills.ts → skill-content.ts, which +// is generated by generate:skill. On a fresh checkout (or CI without prior runs), +// the file won't exist yet. We create a minimal stub so the import resolves; +// generate:skill will overwrite it with real content afterward. +// Must run before the dynamic import below (static imports hoist above top-level await). +const SKILL_CONTENT_PATH = "src/generated/skill-content.ts"; +const SKILL_CONTENT_STUB = + "export const SKILL_FILES: [string, string][] = [];\n"; +if (!(await Bun.file(SKILL_CONTENT_PATH).exists())) { + mkdirSync("src/generated", { recursive: true }); + await Bun.write(SKILL_CONTENT_PATH, SKILL_CONTENT_STUB); +} + import type { CommandInfo, FlagInfo, @@ -30,7 +44,9 @@ import type { RouteInfo, RouteMap, } from "../src/lib/introspect.js"; -import { extractAllRoutes } from "../src/lib/introspect.js"; + +const { routes } = await import("../src/app.js"); +const { extractAllRoutes } = await import("../src/lib/introspect.js"); const DOCS_DIR = "docs/src/content/docs/commands"; const FRAGMENTS_DIR = "docs/src/fragments/commands";