Dashboard › cli › Distillation
5825e7ef-61b1-4116-a771-b917bb8ed8fe["lore_tm_v1_QGFP8lUWUyHHHR8d48QCWnLxs8PTDl2Pyr38FkXwW2A"]
Date: Sep 8, 2026
gh CLI conventions and prioritizes a zero-config, agent-friendly developer experience: DSN/source auto-detection, Seer AI debugging, JSON output, predictable behavior, Node SEA native binaries via fossilize, and SQLite API-response caching..cursor/rules/ultracite.mdc before working in the Sentry CLI codebase.<org>/<project> for an explicit organization/project, <org>/ for all projects in an organization, <project> for cross-organization project-name search, and omission for DSN/config auto-detection.<org>/<project>, 2. config defaults set via sentry config set, 3. DSN auto-detection from SENTRY_DSN or source code.org view and project view mirror gh repo view. All view commands support -w/--web, while IDs remain required for commands such as issue view <issue-id> and event view [<org>/<project>] <event-id>.ContextError for omitted required context, with a required-resource label, a primary single-line usage command, and optional alternatives.resolveOrg() or resolveOrgAndProject() from lib/resolve-target.ts, 3. support JSON through the command wrapper, 4. support -w/--web on view commands, 5. use ContextError for missing context, 6. add E2E tests under test/e2e/.@sentry/api when available instead of creating redundant Valibot schemas in src/types/sentry.ts.readFile/writeFile from node:fs/promises, existsSync and permission-aware mkdirSync(..., { recursive: true, mode: 0o700 }) from node:fs, spawn()/execFile() from node:child_process, setTimeout from node:timers/promises, the which helper in src/lib/which.ts, and scanners in src/lib/scan/.src/bin.ts as entry point, src/app.ts for Stricli application setup, src/context.ts for dependency injection, src/commands/ for command groups, src/lib/ for shared utilities, src/types/ for TypeScript types/Valibot schemas, test/ mirroring src/, script/ for build utilities, .cursor/rules/ for Cursor rules, and biome.jsonc for lint configuration.apps/cli-docs/src/content/docs/contributing.md, generated by the project-structure block in script/generate-docs-sections.ts; current commands can also be inspected with ls src/commands/ or sentry --help.src/commands/ to focus on exactly three concerns: 1. argument parsing, 2. API orchestration, 3. output dispatch. Formatting belongs in src/lib/formatters/<domain>.ts; command files exceeding approximately 400 lines should extract formatter helpers.src/lib/formatters/replay.ts, src/lib/formatters/trace.ts, and src/lib/formatters/human.ts.logger; stderr.write() is banned in command files by a GritQL rule, while data output must use CommandOutput.parseSlashSeparatedArg and parseOrgProjectArg from src/lib/arg-parsing.ts for standard [<org>/<project>/]<id> parsing. parseSlashSeparatedArg(first, "Trace ID", USAGE_HINT) returns { id, targetArg }, and parsed target types are "auto-detect", "explicit", "project-search", or "org-all".project create accepts space-separated variadic name:platform pairs such as web:javascript api:python-django; every project requires the pair, project names cannot contain whitespace, and commas in required positional values must be preserved rather than split.value.split(","); repeatable arrays use flags.x.flatMap((v) => v.split(",")). Examples include --features errors,tracing, release set-commits --path a,b, and auth login --scope a,b.renderMarkdown() must use the plainSafeMuted pattern: isPlainOutput() ? text : muted(text).DRY_RUN_FLAG and DRY_RUN_ALIASES from src/lib/mutate-command.ts for consistent --dry-run support.src/lib/mutate-command.ts include isConfirmationBypassed(flags), guardNonInteractive(flags), confirmByTyping(expected, message), requireExplicitTarget(parsed, entityType, usage), DESTRUCTIVE_FLAGS, and DESTRUCTIVE_ALIASES; buildDeleteCommand() can selectively disable behavior through noForceFlag, noDryRunFlag, or noNonInteractiveGuard.-c next increments, -c prev decrements, -c first resets to index 0, back-then-forward truncates stale entries, and "last" is a silent alias for "next".nextCursor and hasPrev; hints show -c prev when hasPreviousPage() is true and -c next when more results exist.paginationHint() from src/lib/list-command.ts rather than manually assembling navParts; it receives prebuilt prevHint/nextHint strings and returns "Prev: X | Next: Y", a one-direction hint, or "".src/lib/hex-id.ts: validateHexId(value, label) for 32-character trace/log IDs, validateSpanId(value) for 16-character span IDs, and validateTraceId(value) from src/lib/trace-id.ts. Validators strip UUID dashes where applicable, normalize to lowercase, and throw ValidationError for invalid input."date" rather than "time" for timestamp-based sorting; sort types such as SpanSortValue must be exported from API modules and imported by commands.src/types/*.ts, use InferOutput, be re-exported through src/types/index.ts, and be imported with import type; key files are src/types/sentry.ts, src/types/config.ts, src/types/oauth.ts, and src/types/seer.ts.upsert() or runUpsert() from src/lib/db/utils.ts rather than duplicating SQL UPSERT boilerplate; upsert() supports conflict-key arrays and excludeFromUpdate, such as preserving created_at.CliError from src/lib/errors.ts; numeric exit codes must use EXIT.* constants and must never be hardcoded outside errors.ts.CliError default 1; AuthError 10β12; HostScopeError 13; ConfigError 20; ValidationError 21; ContextError 22; ResolutionError 23; ApiError 30; TimeoutError 31; SeerError 40β42; UpgradeError 50; DeviceFlowError 51; OutputError 60; and WizardError 61β64.1x auth, 2x input/config, 3x API/network, 4x feature/billing, 5x operations, and 6x command-specific; the full reference is in EXIT and at https://cli.sentry.dev/exit-codes/.ContextError; provided but unfound value β ResolutionError; malformed input β ValidationError.ContextError.command to be a single-line CLI usage example; its constructor rejects \n. Use alternatives: [] when defaults are irrelevant, and join plural resource names with " and " for correct grammar.pnpm run check:errors detects multiline ContextError commands and ad-hoc "Try:" strings in CliError.fuzzyMatch() from src/lib/fuzzy.ts and show at most 5 similar candidates rather than listing every entity; resolveDashboardId() in src/commands/dashboard/resolve.ts is the reference.catch blocks. Every catch must either rethrow, log with log.debug()/log.warn(), or log before returning a fallback; command files should use logger.withTag("command-name").lint-rules/no-silent-catch.grit, registered in biome.jsonc, flags empty, comment-only, and return-only catch/.catch() handlers. Existing violations are grandfathered with // biome-ignore lint/plugin: <reason>; when fixed, the suppression must be deleted because pnpm run lint --error-on-warnings fails orphaned suppressions as suppressions/unused.log.warn(), 4. return a hint toward the correct command. Ambiguous or impossible recovery should retain the error and add entity-aware suggestions.looksLikeIssueShortId() for uppercase dash-separated IDs such as CLI-G5, SPAN_ID_RE for 16-character hex, HEX_ID_RE for 32-character hex, and /[^0-9a-f]/ for likely slugs/names. References are event/view.ts, span/view.ts, trace/view.ts, and hex-id.ts.getAuthToken(), isAuthenticated(), and setAuthToken(token, expiresIn).src/lib/*.ts: duration/relative time in src/lib/formatters/time-utils.ts, hex validation in src/lib/hex-id.ts, formatting in src/lib/formatters/, pagination in src/lib/db/pagination.ts and src/lib/list-command.ts, errors in src/lib/errors.ts, and search parsing in src/lib/search-query.ts and src/lib/arg-parsing.ts.src/lib/**/*.ts must begin with module-level JSDoc..js, external imports to precede local imports, and type-only imports to use the type keyword.src/lib/list-command.ts provides buildOrgListCommand, LIST_TARGET_POSITIONAL, LIST_JSON_FLAG, LIST_CURSOR_FLAG, and buildListLimitFlag; src/lib/org-list.ts provides dispatchOrgScopedList, OrgListConfig, and handlers for "auto-detect", "explicit", "org-all", and "project-search".dispatchOrgScopedList overrides to access narrowed values through ctx.parsed, spread extra fields into context as needed, and override ctx.flags with command-specific types where needed; manual Extract<> casts are unnecessary.resolveCursor() inside the "org-all" override rather than before dispatchOrgScopedList, so invalid --cursor values are rejected correctly for non-org-all modes.handleProjectSearch errors to use "Project" as the ContextError resource, not config.entityName.dispatchOrgScopedList call to set orgSlugMatchBehavior: use "redirect" where organization-wide listing makes sense, including project list, team list, and issue list; use "error" where it does not. Cached organizations avoid N API calls, while a cold-cache handler check must throw ResolutionError with a hint.queryEvents uses project:<slug> via buildProjectQuery(); replay index listReplays uses projectSlugs; issue index listIssuesPaginated uses either a project parameter or query based on mode. Both mechanisms must never be applied simultaneously.explore datasets to centralize sort, query, fetch, filtering, and field validation in resolveDatasetConfig, rather than scattering if (dataset === ...) branches through func.*.property.test.ts under test/lib/, model-based tests to use *.model-based.test.ts under test/lib/db/, unit tests to mirror src/ under test/, and E2E tests to live under test/e2e/.useTestConfigDir() from test/helpers.ts; it creates a unique directory in beforeEach, sets SENTRY_CONFIG_DIR, restores rather than deletes the prior environment value in afterEach, closes the database, and cleans temporary files.process.env.SENTRY_CONFIG_DIR, capturing process.env[CONFIG_DIR_ENV_VAR] at module scope, or manually managing SENTRY_CONFIG_DIR in beforeEach/afterEach.process.env remains shared within a file lifecycle, and TEST_TMP_DIR is namespaced by VITEST_POOL_ID in test/constants.ts; deleting SENTRY_CONFIG_DIR can cause TypeError: The "paths[0]" property must be of type string.DEFAULT_NUM_RUNS from test/model-based/helpers.ts; the standard value is 50 runs. Good property candidates include parsing, round trips, symmetry, idempotence, and valid/invalid-input acceptance.createIsolatedDbContext() with cleanup in finally and fast-check command sequences; suitable targets include database operations, cache invalidation, and cross-cutting state invariants.*.property.test.ts.gh pr list --state open --search "in:title <file-or-symbol>" and gh issue list --state all --search "<symbol>"; if an open PR already touches the function, comment on or extend it instead of duplicating it.main, re-verify that the bug still exists, and rerun verification before requesting review; CI drift or superseded fixes in stale snapshots are not sufficient evidence.autoPaginate() and safeParseJson() instead of re-deriving one-off pagination or JSON guards.