Skip to content

Commit 05d4dae

Browse files
committed
feat(config): support .sentryclirc config file for per-directory defaults
Add backward-compatible support for .sentryclirc INI config files. The CLI walks up from CWD to find config files, merging them (closest wins per-field) with ~/.sentryclirc as a global fallback. Supported fields: - [defaults] org, project, url - [auth] token Token and URL are applied via env shim (SENTRY_AUTH_TOKEN, SENTRY_URL). Org and project are inserted into the resolution chain between env vars and SQLite defaults with source tracking. This enables per-directory project defaults in monorepos and seamless migration from legacy sentry-cli.
1 parent 8c49fb2 commit 05d4dae

36 files changed

+1706
-381
lines changed

.github/workflows/ci.yml

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ jobs:
4242
skill:
4343
- 'src/**'
4444
- 'docs/**'
45-
- 'plugins/**'
4645
- 'script/generate-skill.ts'
46+
- 'script/generate-command-docs.ts'
4747
- 'script/eval-skill.ts'
4848
- 'test/skill-eval/**'
4949
code:
@@ -88,8 +88,8 @@ jobs:
8888
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
8989
echo "Nightly version: ${VERSION}"
9090
91-
check-skill:
92-
name: Check skill files
91+
check-generated:
92+
name: Validate generated files
9393
needs: [changes]
9494
if: needs.changes.outputs.skill == 'true'
9595
runs-on: ubuntu-latest
@@ -116,25 +116,30 @@ jobs:
116116
run: bun install --frozen-lockfile
117117
- name: Generate API Schema
118118
run: bun run generate:schema
119+
- name: Generate docs and skill files
120+
run: bun run generate:docs
121+
- name: Validate fragments
122+
run: bun run check:fragments
119123
- name: Check skill files
120124
id: check-skill
121-
run: bun run check:skill
122-
continue-on-error: true
123-
- name: Check command docs
124-
id: check-docs
125-
run: bun run check:command-docs
126-
continue-on-error: true
127-
- name: Auto-commit regenerated files
128-
if: (steps.check-skill.outcome == 'failure' || steps.check-docs.outcome == 'failure') && steps.token.outcome == 'success'
125+
run: |
126+
if git diff --quiet plugins/sentry-cli/skills/sentry-cli/; then
127+
echo "Skill files are up to date"
128+
else
129+
echo "stale=true" >> "$GITHUB_OUTPUT"
130+
echo "Skill files are out of date"
131+
fi
132+
- name: Auto-commit regenerated skill files
133+
if: steps.check-skill.outputs.stale == 'true' && steps.token.outcome == 'success'
129134
run: |
130135
git config user.name "github-actions[bot]"
131136
git config user.email "github-actions[bot]@users.noreply.github.com"
132-
git add plugins/sentry-cli/skills/sentry-cli/ docs/public/.well-known/skills/index.json docs/src/content/docs/commands/
133-
git diff --cached --quiet || (git commit -m "chore: regenerate skill files and command docs" && git push)
134-
- name: Fail for fork PRs with stale generated files
135-
if: (steps.check-skill.outcome == 'failure' || steps.check-docs.outcome == 'failure') && steps.token.outcome != 'success'
137+
git add plugins/sentry-cli/skills/sentry-cli/
138+
git diff --cached --quiet || (git commit -m "chore: regenerate skill files" && git push)
139+
- name: Fail for fork PRs with stale skill files
140+
if: steps.check-skill.outputs.stale == 'true' && steps.token.outcome != 'success'
136141
run: |
137-
echo "::error::Generated files are out of date. Run 'bun run generate:skill' and 'bun run generate:command-docs' locally and commit the result."
142+
echo "::error::Skill files are out of date. Run 'bun run generate:docs' locally and commit the result."
138143
exit 1
139144
140145
eval-skill:
@@ -177,6 +182,9 @@ jobs:
177182
key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }}
178183
- if: steps.detect-fork.outputs.is_fork != 'true' && steps.cache.outputs.cache-hit != 'true'
179184
run: bun install --frozen-lockfile
185+
- name: Generate docs and skill files
186+
if: steps.detect-fork.outputs.is_fork != 'true'
187+
run: bun run generate:schema && bun run generate:docs
180188
- name: Eval SKILL.md
181189
if: steps.detect-fork.outputs.is_fork != 'true'
182190
run: bun run eval:skill
@@ -659,6 +667,15 @@ jobs:
659667
steps:
660668
- uses: actions/checkout@v6
661669
- uses: oven-sh/setup-bun@v2
670+
- uses: actions/cache@v5
671+
id: cache
672+
with:
673+
path: node_modules
674+
key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }}
675+
- if: steps.cache.outputs.cache-hit != 'true'
676+
run: bun install --frozen-lockfile
677+
- name: Generate docs content
678+
run: bun run generate:schema && bun run generate:docs
662679
- name: Build Docs
663680
working-directory: docs
664681
run: |
@@ -677,15 +694,15 @@ jobs:
677694
ci-status:
678695
name: CI Status
679696
if: always()
680-
needs: [changes, check-skill, eval-skill, build-binary, build-npm, build-docs, test-e2e, generate-patches, publish-nightly]
697+
needs: [changes, check-generated, eval-skill, build-binary, build-npm, build-docs, test-e2e, generate-patches, publish-nightly]
681698
runs-on: ubuntu-latest
682699
permissions: {}
683700
steps:
684701
- name: Check CI status
685702
run: |
686703
# Check for explicit failures or cancellations in all jobs
687704
# generate-patches and publish-nightly are skipped on PRs — that's expected
688-
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 }}"
705+
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 }}"
689706
for result in $results; do
690707
if [[ "$result" == "failure" || "$result" == "cancelled" ]]; then
691708
echo "::error::CI failed"
@@ -699,8 +716,8 @@ jobs:
699716
echo "::error::CI failed - upstream job failed causing test-e2e to be skipped"
700717
exit 1
701718
fi
702-
if [[ "${{ needs.changes.outputs.skill }}" == "true" && "${{ needs.check-skill.result }}" == "skipped" ]]; then
703-
echo "::error::CI failed - upstream job failed causing check-skill to be skipped"
719+
if [[ "${{ needs.changes.outputs.skill }}" == "true" && "${{ needs.check-generated.result }}" == "skipped" ]]; then
720+
echo "::error::CI failed - upstream job failed causing check-generated to be skipped"
704721
exit 1
705722
fi
706723
if [[ "${{ needs.changes.outputs.skill }}" == "true" && "${{ needs.eval-skill.result }}" == "skipped" ]]; then

.github/workflows/docs-preview.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ on:
44
pull_request:
55
paths:
66
- 'docs/**'
7+
- 'src/**'
8+
- 'script/generate-command-docs.ts'
9+
- 'script/generate-skill.ts'
710
- '.github/workflows/docs-preview.yml'
811

912
permissions:
@@ -18,6 +21,18 @@ jobs:
1821

1922
- uses: oven-sh/setup-bun@v2
2023

24+
- uses: actions/cache@v5
25+
id: cache
26+
with:
27+
path: node_modules
28+
key: node-modules-${{ hashFiles('bun.lock', 'patches/**') }}
29+
30+
- if: steps.cache.outputs.cache-hit != 'true'
31+
run: bun install --frozen-lockfile
32+
33+
- name: Generate docs content
34+
run: bun run generate:schema && bun run generate:docs
35+
2136
- name: Build Docs for Preview
2237
working-directory: docs
2338
env:

.github/workflows/generate-skill.yml

Lines changed: 0 additions & 55 deletions
This file was deleted.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ src/generated/
5858
src/sdk.generated.ts
5959
src/sdk.generated.d.cts
6060

61+
# Generated command docs (rebuilt from fragments + CLI introspection)
62+
docs/src/content/docs/commands/
63+
64+
# Generated discovery manifest (rebuilt by generate:skill, served via symlinked skill files)
65+
docs/public/.well-known/skills/index.json
66+
6167
# OpenCode
6268
.opencode/
6369
opencode.json*

AGENTS.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -489,10 +489,14 @@ All normalize to lowercase. Throw `ValidationError` on invalid input.
489489

490490
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`.
491491

492-
### SKILL.md
492+
### Generated Docs & Skills
493493

494-
- Run `bun run generate:skill` after changing any command parameters, flags, or docs.
495-
- CI check `bun run check:skill` will fail if SKILL.md is stale.
494+
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.
495+
496+
- **Command docs** (`docs/src/content/docs/commands/*.md`) are **gitignored** and generated from CLI metadata + hand-written fragments in `docs/src/fragments/commands/`.
497+
- **Skill files** (`plugins/sentry-cli/skills/sentry-cli/`) are **committed** (consumed by external plugin systems) and auto-committed by CI when stale.
498+
- Edit fragments in `docs/src/fragments/commands/` for custom examples and guides.
499+
- `bun run check:fragments` validates fragment ↔ route consistency.
496500
- Positional `placeholder` values must be descriptive: `"org/project/trace-id"` not `"args"`.
497501

498502
### Zod Schemas for Validation
@@ -973,6 +977,7 @@ mock.module("./some-module", () => ({
973977
| Add E2E tests | `test/e2e/` |
974978
| Test helpers | `test/model-based/helpers.ts` |
975979
| Add documentation | `docs/src/content/docs/` |
980+
| Hand-written command doc content | `docs/src/fragments/commands/` |
976981
977982
<!-- This section is maintained by the coding agent via lore (https://github.com/BYK/opencode-lore) -->
978983
## Long-term Knowledge
@@ -1016,7 +1021,7 @@ mock.module("./some-module", () => ({
10161021
* **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.
10171022
10181023
<!-- lore:019d3ea5-fd4a-75b0-8dab-0b1f1cb96b0e -->
1019-
* **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.
1024+
* **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.
10201025
10211026
<!-- lore:019d275c-7cf0-7e13-bdc8-10cbbdbda933 -->
10221027
* **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.

docs/src/content/docs/agent-guidance.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Best practices and operational guidance for AI coding agents using the Sentry CL
1212
- **Use `sentry schema` to explore the API** — if you need to discover API endpoints, run `sentry schema` to browse interactively or `sentry schema <resource>` to search. This is faster than fetching OpenAPI specs externally.
1313
- **Use `sentry issue view <id>` to investigate issues** — when asked about a specific issue (e.g., `CLI-G5`, `PROJECT-123`), use `sentry issue view` directly.
1414
- **Use `--json` for machine-readable output** — pipe through `jq` for filtering. Human-readable output includes formatting that is hard to parse.
15-
- **The CLI auto-detects org/project** — most commands work without explicit targets by scanning for DSNs in `.env` files, source code, config defaults, and directory names. Only specify `<org>/<project>` when the CLI reports it can't detect the target or detects the wrong one.
15+
- **The CLI auto-detects org/project** — most commands work without explicit targets by checking `.sentryclirc` config files, scanning for DSNs in `.env` files and source code, and matching directory names. Only specify `<org>/<project>` when the CLI reports it can't detect the target or detects the wrong one.
1616

1717
## Design Principles
1818

@@ -213,7 +213,7 @@ When querying the Events API (directly or via `sentry api`), valid dataset value
213213
- **Wrong issue ID format**: Use `PROJECT-123` (short ID), not the numeric ID `123456789`. The short ID includes the project prefix.
214214
- **Pre-authenticating unnecessarily**: Don't run `sentry auth login` before every command. The CLI detects missing/expired auth and prompts automatically. Only run `sentry auth login` if you need to switch accounts.
215215
- **Missing `--json` for piping**: Human-readable output includes formatting. Use `--json` when parsing output programmatically.
216-
- **Specifying org/project when not needed**: Auto-detection resolves org/project from DSNs, env vars, config defaults, and directory names. Let it work first — only add `<org>/<project>` if the CLI says it can't detect the target or detects the wrong one.
216+
- **Specifying org/project when not needed**: Auto-detection resolves org/project from `.sentryclirc` config files, DSNs, env vars, and directory names. Let it work first — only add `<org>/<project>` if the CLI says it can't detect the target or detects the wrong one.
217217
- **Confusing `--query` syntax**: The `--query` flag uses Sentry search syntax (e.g., `is:unresolved`, `assigned:me`), not free text search.
218218
- **Not using `--web`**: View commands support `-w`/`--web` to open the resource in the browser — useful for sharing links.
219219
- **Fetching API schemas instead of using the CLI**: Prefer `sentry schema` to browse the API and `sentry api` to make requests — the CLI handles authentication and endpoint resolution, so there's rarely a need to download OpenAPI specs separately.

docs/src/content/docs/commands/dashboard.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ View a dashboard
4343
| `-w, --web` | Open in browser |
4444
| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data |
4545
| `-r, --refresh <refresh>` | Auto-refresh interval in seconds (default: 60, min: 10) |
46-
| `-t, --period <period>` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" |
46+
| `-t, --period <period>` | Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" |
4747

4848
### `sentry dashboard create <org/project/title...>`
4949

docs/src/content/docs/commands/event.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ List events for an issue
4242
| `-n, --limit <limit>` | Number of events (1-1000) (default: "25") |
4343
| `-q, --query <query>` | Search query (Sentry search syntax) |
4444
| `--full` | Include full event body (stacktraces) |
45-
| `-t, --period <period>` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "7d") |
45+
| `-t, --period <period>` | Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" (default: "7d") |
4646
| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data |
4747
| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) |
4848

docs/src/content/docs/commands/issue.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ List issues in a project
2424
| `-q, --query <query>` | Search query (Sentry search syntax) |
2525
| `-n, --limit <limit>` | Maximum number of issues to list (default: "25") |
2626
| `-s, --sort <sort>` | Sort by: date, new, freq, user (default: "date") |
27-
| `-t, --period <period>` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "90d") |
27+
| `-t, --period <period>` | Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" (default: "90d") |
2828
| `-c, --cursor <cursor>` | Pagination cursor (use "next" for next page, "prev" for previous) |
2929
| `--compact` | Single-line rows for compact output (auto-detects if omitted) |
3030
| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data |
@@ -46,7 +46,7 @@ List events for a specific issue
4646
| `-n, --limit <limit>` | Number of events (1-1000) (default: "25") |
4747
| `-q, --query <query>` | Search query (Sentry search syntax) |
4848
| `--full` | Include full event body (stacktraces) |
49-
| `-t, --period <period>` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" (default: "7d") |
49+
| `-t, --period <period>` | Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" (default: "7d") |
5050
| `-f, --fresh` | Bypass cache, re-detect projects, and fetch fresh data |
5151
| `-c, --cursor <cursor>` | Navigate pages: "next", "prev", "first" (or raw cursor string) |
5252

docs/src/content/docs/commands/log.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ List logs from a project
2424
| `-n, --limit <limit>` | Number of log entries (1-1000) (default: "100") |
2525
| `-q, --query <query>` | Filter query (Sentry search syntax) |
2626
| `-f, --follow <follow>` | Stream logs (optionally specify poll interval in seconds) |
27-
| `-t, --period <period>` | Time range: "7d", "2026-03-08..2026-04-08", ">=2026-03-08" |
27+
| `-t, --period <period>` | Time range: "7d", "2026-03-01..2026-04-01", ">=2026-03-01" |
2828
| `-s, --sort <sort>` | Sort order: "newest" (default) or "oldest" (default: "newest") |
2929
| `--fresh` | Bypass cache, re-detect projects, and fetch fresh data |
3030

0 commit comments

Comments
 (0)