Dashboard › cli › Distillation
b9c47a08-93b9-4c55-91b7-8284819576e9["lore_tm_v1_v15tr7wUnCcBFxp4MlgZiBJDU3_knhF9zADeX6sCMZE","lore_tm_v1_OAnKPyCqfwAe_yo4xCHk87fSDIl8BVWqFpg1TCennTM","lore_tm_v1_Hvtk9GwSsPXlWPHRmEPVaFND4tddPVGOIWZohB7YGHw"]
Date: Sep 10, 2026
package.json scripts; commands run from packages/cli or from the repository root via pnpm --filter sentry run <script>.devDependencies, never dependencies, because everything is bundled at build time via esbuild; CI enforces this through pnpm run check:deps.pnpm add -D <package> with the -D flag.src/lib/formatters/<domain>.ts; command files exceeding approximately 400 lines should extract formatting helpers into a dedicated formatter module.mdKvTable(), colorTag(), escapeMarkdownCell(), and renderMarkdown(); never use raw muted() or chalk in output strings, instead use colorTag("muted", text) within markdown; tree output that cannot use renderMarkdown() should use isPlainOutput() ? text : muted(text).isPlainOutput() precedence is SENTRY_PLAIN_OUTPUT > NO_COLOR > FORCE_COLOR (TTY only) > !isTTY; it resides at src/lib/formatters/plain-detect.ts and is re-exported from markdown.ts for compatibility.-c next increments, -c prev decrements, -c first resets to 0, back-then-forward truncates stale entries, and "last" silently aliases "next".per_page greater than API_MAX_PER_PAGE to the API, because the server silently caps oversized values and commands would return fewer items than requested."date", not "time"; sort types should be exported by the API layer (for example, SpanSortValue from api/traces.ts) and imported by commands, matching issue list, trace list, and span list..js extensions; imports must group external packages before local imports and use the type keyword for type-only imports.fcAssert(property(...), { numRuns: DEFAULT_NUM_RUNS }).writeJsonList envelope shape.packages/cli/src/lib/token-claims.ts defines parseSntrysClaim(token: string | undefined): SntrysClaim | undefined for sntrys_ org-auth tokens formatted as sntrys_<base64(JSON{iat, url, region_url, org})>_<random-secret>.packages/cli/src/lib/token-claims.ts defines SntrysClaim as { url: string; regionUrl?: string; org?: string }; region_url is returned as regionUrl, and org is an optional organization slug embedded when issued.parseSntrysClaim() behavior: rejects absent tokens, tokens longer than MAX_TOKEN_LENGTH = 2048, non-sntrys_ tokens, tokens not containing exactly 2 underscores, empty payloads, invalid base64/JSON payloads, non-object payloads, payloads without truthy iat, and payloads without a nonempty string url; it returns optional nonempty-string region_url and org values through optionalString().packages/cli/src/lib/token-claims.ts documents that sntrys_ claims are unsigned and forgeable; the accepted threat-model rationale is that an attacker able to provide a forged token has already compromised the credential. For legitimate tokens, the server-issued claim is treated as authoritative and resistant to environment-variable injection; captureEnvTokenHost uses the claim as its primary source ahead of environment variables.packages/cli/src/lib/sentry-client.ts imports parseSntrysClaim from ./token-claims.js and applies a defense-in-depth sntrys_ host check in prepareHeaders(): it reads parseSntrysClaim(token)?.url and, if present, throws HostScopeError("Credentials", normalizeOrigin(input) ?? "<unknown host>", claimUrl) when isHostTrustedForClaim(input, claimUrl) is false; malformed claims fail open, while valid claims permit control-silo multi-region fan-out via region URLs.prepareHeaders() in packages/cli/src/lib/sentry-client.ts also enforces isRequestOriginTrusted(input) before credential injection, throwing HostScopeError with getActiveTokenHost() for an untrusted request origin; this is defense in depth beyond URL-argument and rc-shim entry-point guards.prepareHeaders(input, init, token) preserves SDK-provided headers when the SDK invokes fetch(request) without init: it uses init?.headers ?? (input instanceof Request ? input.headers : undefined) before creating new Headers(sourceHeaders), preventing Node.js fetch(request, {headers}) behavior from stripping existing Content-Type and causing HTTP 415 responses.prepareHeaders() sets Authorization: Bearer ${token}, sets User-Agent only when absent using getUserAgent(), injects sentry-trace and baggage from getTraceData() when telemetry supplies them, and scopes self-hosted proxy custom headers through applyCustomHeaders(headers, input).packages/cli/src/lib/sentry-client.ts request configuration values include REQUEST_TIMEOUT_MS = 30_000, an /\/autofix\/?(?:\?|$)/ endpoint override of 120_000 ms for Seer autofix POSTs, MAX_RETRIES = 2, MAX_BACKOFF_MS = 10_000, retryable HTTP statuses [408, 429, 500, 502, 503, 504], and retry marker header "x-sentry-cli-retry".backoffDelay(attempt) in packages/cli/src/lib/sentry-client.ts calculates Math.min(1000 * 2 ** attempt, MAX_BACKOFF_MS).