Dashboard › cli › Distillation
67d2108b-c624-414b-bf40-0ecce5a203e2["lore_tm_v1_B2EU82La_r8hYj9kTaBlR8iDICT5Gqat7wvU84xcnv4","lore_tm_v1_rxIE7A_lyqVr1yOZlzS4kW6bDWBaIC75h_63PzzNotw","lore_tm_v1_VSXJXo8iqpc_Y2QjiYR6f71PPFE4tIXeUUWlNr7yivo","lore_tm_v1_qTIZYH6Xlem4X3-b7eOe8IlywocCyTkHjDdDjN_bPsU","lore_tm_v1_SwwwopoR16N_3IrwtgFT65Jk29DESYYYH3gsO-oXXFs"]
sentry api must preserve rawApiRequest() status text; empty textual non-2xx bodies fall back to HTTP status/request context; JSON mode exposes {status, statusText, body}; binary Uint8Array successes bypass formatters and remain raw; binary errors expose only status/content-type/byte-count summaries and never bytes or JSON coercion; prompts must not block scripted runs or interleave with stdout JSON.rawApiRequest() treats every status outside 200β299 as an error, including 304; empty or whitespace-only textual errors fall back to HTTP <status> <statusText> β <method> /api/0/<endpoint>. JSON errors preserve {status,statusText,body}, binary errors produce status/content-type/byte-count summaries, and binary successes remain raw Uint8Array.--fields filtering must apply to response.body while preserving the {status,statusText,body} envelope; it must support nested dot notation and array elements without mutating the source, while retaining literal keys containing dots.status >= 400 rule loses api_error attributes for 199 and 3xx. Boundary regression coverage is required for 199, 200, 299, and 300.statusText, e.g. HTTP 404 Not Found, with regression coverage.@sentry/symbolic@13.4.0 exports Archive, FileEntry, ObjectFile, SourceBundleWriter, and SourceFileDescriptor. SourceBundleWriter.writeObject(object: ObjectFile, object_name: string, filter: Function, provider: Function): Uint8Array | undefined is callback-based; the provider reads source content by path and the filter selects files.bundle-sources is directly implementable with SourceBundleWriter.writeObject() and a disk-reading provider; print-sources is deferred because ObjectFile in @sentry/symbolic@13.4.0 has no sourceFiles() enumeration method. ObjectFile exposes arch, codeId, debugId, fileFormat, hasDebugInfo, hasSources, hasSymbols, hasUnwindInfo, and kind; SourceFileDescriptor exposes get/set properties contents, debugId, path, sourceMappingUrl, url, and type.@sentry/symbolic@13.4.0 source-enumeration limitation; symbolic PRs #988β#993 were merged, @sentry/symbolic@13.4.0 was published, and CLI PR #1124 was merged. (meaning Jun 23, 2026)121 MiB and bundled code about 6.3 MiB; strip --strip-unneeded yields 99 MiB (-17 MiB raw, -4 MiB compressed). Fossilize 0.7.0 strips the copied binary before postject injection; after strip + SEA + binpunch the artifact is about 108 MiB raw / 30 MiB gzip versus 125 MiB / 34 MiB unstripped..rodata is 52.5 MB, including about 12 MB of V8 snapshot and about 28 MB of full ICU data. UPX yields 25 MiB but was rejected because it destroys ELF notes. --with-intl=small-icu saves about 26β28 MiB; --without-lief breaks SEA, --without-sqlite breaks the CLI, and --disable-single-executable-application breaks everything.3.5h build time versus 5min with fossilize. Final Node artifact comparison to Bun was 30 MiB versus 32 MiB download, --version about 1.0s versus 1.9s, and completions about 150ms versus 180ms.--with-intl=small-icu (safe, English-only ICU, saves about 26β28 MiB); --with-intl=none (rejected, saves about 28β30 MiB but breaks Intl.NumberFormat and String.normalize()); --without-inspector (saves about 2β4 MiB); --without-amaro (about 0.5 MiB); --v8-disable-maglev (about 1β2 MiB); and --enable-lto (about 3β5 MiB). --without-ssl, --without-lief, --without-sqlite, --disable-single-executable-application, and --v8-lite-mode were rejected because they respectively break HTTPS, SEA, SQLite-dependent CLI behavior, all SEA behavior, or cause roughly 10x slowdown. Linux-to-Darwin cross-compilation is not officially supported.TRDIFF10\x00, followed by little-endian sign-magnitude int64 values controlLen, diffLen, and newSize; control tuples are 24 bytes with readDiffBy, readExtraBy, and seekBy; control, diff, and extra blocks are zstd-compressed.<repo>:nightly for the mutable pointer, <repo>:nightly-<version> for immutable nightlies, and <repo>:patch-<version> for patches. Annotations are from-version=<prev> as a pointer rather than a hash, sha256-<binaryName>=<hex> for only the final binary hash, and org.opencontainers.image.title; artifact type is application/vnd.<prefix>.patch.MAX_OUTPUT_SIZE=2_147_483_648 (2 GiB), MAX_NIGHTLY_CHAIN_DEPTH=30, MAX_STABLE_CHAIN_DEPTH=10, and SIZE_THRESHOLD_RATIO=0.6. Patch integration verifies SHA-256 only for the final output, not intermediate hops.bspatch.ts refactored core patching into transformPatch(oldFile, patchData, onChunk) and exposes: applyPatchToFile(oldPath, patchData, destPath)βSHA-256 for the final disk sink; applyPatchToMemory(oldFile, patchData)βUint8Array for intermediate in-memory hops; and applyPatchChainInMemory(oldPath, patches[], destPath)βSHA-256 as the chain orchestrator. applyPatch() remains a thin backward-compatible wrapper, and orchestration remains in bspatch.ts rather than delta-upgrade.ts to encapsulate buffers.applyPatch() βALWAYS computes SHA-256 inline and returns it β no separate verification step.βbspatch.ts fully decompresses the random-access control block with zstdDecompressSync and streams diff/extra through createZstdStreamReader using Node Transform β Web ReadableStream β BufferedStreamReader. loadOldBinary() copies to a temporary file with COPYFILE_FICLONE, falling back to a regular copy, then reads it into memory.cleanupPatchResources() runs all cleanup actions despite prior failures. The onChunk callback checks a writeError flag populated by the writerβs 'error' event and throws immediately; this avoids ERR_UNHANDLED_ERROR for ENOSPC/EIO. applyPatchToMemory() preallocates a Uint8Array of newSize; a corrupt huge claimed size throws RangeError and triggers full-download fallback.delta-upgrade.ts supports stable GitHub Releases and nightly GHCR patch-<version> channels. Stable resolution performs one releases API call and parallel Promise.all downloads; nightly resolution lists tags, filters a semver range, fetches manifests, and downloads blobs in parallel. canAttemptDelta() blocks development versions, cross-channel upgrades, and downgrades.applyPatchesSequentially() alternates ${destPath}.patching.a and ${destPath}.patching.b so no path is read and written simultaneously, avoiding mmap corruption. The patch chain is cache-first via tryLoadCachedChain() with key patch-chain:{from}-{to}.script/check-fragments.ts performs Checks 1β4 against actual route names and Check 5 for subcommand coverage. For routes with more than one command, each subcommand must appear in a heading outside fenced code or in a sentry <route> <subcommand> code reference; bare sentry <route> covers a route-map defaultCommand. Warnings are default, --strict makes them errors, and the script runs through pnpm run check:fragments; CI check-generated runs when changes.outputs.skill == 'true'.script/check-stale-references.ts reads packageManager from package.json such as pnpm@10.11.0, dynamically derives stale package managers, and scans developer docs/scripts for stale <pm> run, <pm> remove, <pm> add -d, requires <pm>, and <pm> installed references. It excludes global user install blocks using install -g/add -g, node_modules/, and itself to prevent its JSDoc examples from causing false positives; it runs in the CI lint job.#1329 fixed nightly delta selection in .github/workflows/ci.yml:488-526: sort -V previously placed 0.41 nightlies after every 0.40 nightly, so a 0.40 build could incorrectly receive from-version: 0.41.x-dev.Y. The fix computes MAJOR_MINOR=$(echo "${VERSION}" | cut -d. -f1,2), filters with SAME_SERIES_TAGS=$(printf '%s\n' "$TAGS" | grep "^nightly-${MAJOR_MINOR}\\." || true), and walks only SAME_SERIES_TAGS.0.40.0-dev.1785526951 to 0.40.0-dev.1785546241 using 2 patches totaling 249.9 KB, compared with an approximately 31 MB full download..github/workflows/ci.yml:539-568 has a separate stable-release bug: set-prev-release-tag uses the chronologically newest non-prerelease/non-draft release from the first 5 results, so a 0.40.1 released after 0.41.0 can make a release/0.41 build select 0.40.1. The required fix is branch-derived previous-series selection (release/0.41 β 0.40); this was intentionally out of scope for PR #1329.src/commands/issue/list.ts defines LIFETIME_FIELDS = new Set(['count','userCount','firstSeen','lastSeen']). buildListApiOptions(json, fields) enables collapseLifetime only when json && fields !== undefined && fields.length > 0 && !fields.some(f => LIFETIME_FIELDS.has(f)); human output never collapses lifetime.buildIssueListCollapse() βalways starts with ['filtered',β and the complete invariant is ['filtered','unhandled'], followed conditionally by 'lifetime'and then'stats'`.ISSUE_DETAIL_COLLAPSE may safely include 'lifetime' because the detail endpoint preserves top-level count, userCount, firstSeen, and lastSeen; those fields can be absent only from issue list when lifetime collapse is active. IssueViewOutputSchema in src/types/sentry.ts extends SentryIssueSchema with event, org, replayIds, and trace from jsonTransformIssueView, and view.ts uses schema: IssueViewOutputSchema.createConsolaReporter integration. Reporters are FancyReporter on stderr and Sentry structured logs; level is controlled by SENTRY_LOG_LEVEL; buildCommand injects hidden --log-level and --verbose; withTag() creates independent instances; setLogLevel() propagates through a registry; and user-facing output must use consola rather than raw stderr.SENTRY_CLI_NO_TELEMETRY=1; 2. DO_NOT_TRACK=1; 3. metadata.defaults.telemetry; 4. enabled by default. Shell completions set SENTRY_CLI_NO_TELEMETRY=1 in bin.ts before imports. Completion timings queue in SQLite table completion_telemetry_queue, and normal runs drain with DELETE ... RETURNING.ENV_VAR_REGISTRY in src/lib/env-registry.ts is the single source of truth for honored environment variables; topLevel: true plus briefDescription exposes a variable in --help, and install-script-only variables use installOnly: true.src/lib/custom-ca.ts prioritizes the SQLite value from sentry cli defaults ca-cert, then NODE_EXTRA_CA_CERTS, and caches per process via hasResolved. resolve() adds the custom PEM to rootCertificates; tryReadPem() never throws, logging a warning and returning undefined for a missing file.injectIntoNodeTls() uses tls.setDefaultCACertificates() on Node 24+ and is a no-op on Node 22. TLS_ERROR_PATTERNS contains local issuer, verify first cert, UNABLE_TO_VERIFY_LEAF_SIGNATURE, DEPTH_ZERO_SELF_SIGNED_CERT, and SELF_SIGNED_CERT_IN_CHAIN, explicitly excluding CERT_HAS_EXPIRED and ERR_TLS_CERT_ALTNAME_INVALID. getTlsCertErrorMessage() follows error.cause with cycle detection; __resetForTests() clears all cached state.script/generate-docs-sections.ts injects generated content into committed files between <!-- GENERATED:START name --> Markdown markers or {/* GENERATED:START name */} MDX markers. --check is dry-run and exits 1 if stale. It owns 13 sections across contributing.md, DEVELOPMENT.md, self-hosted.md, README.md, and getting-started.mdx; extractPnpmVersion and extractNodeVersion throw on mismatch with no silent fallback.generateProjectStructure(), groups always use βββ because standalone entries always follow the groups; help.ts is manually added before sorting, the final standalone uses βββ, other standalones use βββ, and both sections are independently alphabetical in a fenced cli/ tree.generate:docs runs exactly: 1. generate:parser β script/generate-parser.ts; 2. generate:command-docs β script/generate-command-docs.ts; 3. generate:skill β script/generate-skill.ts; 4. generate:docs-sections β script/generate-docs-sections.ts. It is a prerequisite for dev, build, build:all, bundle, typecheck, test:unit, test:changed, and test:e2e.docs/src/content/docs/commands/ and docs/src/content/docs/configuration.md are fully generated and gitignored; docs/src/fragments/ is committed hand-written source of truth; DEVELOPMENT.md, README.md, contributing.md, self-hosted.md, and getting-started.mdx are committed files with generated marker sections.getsentry/cli uses /repos/getsentry/cli/dependabot/alerts as the source of truth; /repos/getsentry/cli/security-advisories is empty. There were exactly 13 open and 15 fixed alerts, generally stale lockfile entries without a source manifest or transitive dependencies without a direct upgrade path. pnpm.overrides in package.json is the canonical transitive-vulnerability fix; pnpm audit may separately report CVEs such as @ai-sdk/provider-utils@<=3.0.97 LOW CVE-2026-8769. (meaning Aug 1, 2026)InkUI.tearDown() order is exactly: 1. stop tip-rotation interval; 2. detach SIGINT listener and call store.setRequestCancel(undefined); 3. instance.clear(); 4. instance.unmount(); 5. restore alternate screen with \x1b[?1049l; 6. call freshStdin.setRawMode(false), .pause(), and .destroy(). Every step is wrapped in try/catch; torndown: boolean prevents double unmount, and a second Ctrl+C after cancelRequested invokes process.exit(130).src/lib/sentry-urls.ts intentionally separates isSentrySaasUrl(url), a hostname-only sentry.io/*.sentry.io routing and UX check accepting any protocol/port, from isSaaSTrustOrigin(url), which additionally requires HTTPS and the default port for credential-security decisions. Both implementations must remain synchronized on hostname matching.PrepareDifsOptions.maxZipTotalSize defaults to DEFAULT_MAX_ZIP_TOTAL_SIZE = 2GiB, is a cumulative uncompressed extraction budget and container size cap, and is distinct from per-entry server-policy maxFileSize. 0 disables the budget; prepareDifs supplies the default automatically and passes it through prepareZipDifs β readZipDifEntries as maxTotalSize.api-schema.json contains only: organizations/{org}/preprodartifacts/{artifact_id}/install-details/, organizations/{org}/preprodartifacts/{artifact_id}/size-analysis/, projects/{org}/{project}/preprod/size-analysis/status-check-rules/, and projects/{org}/{project}/preprodartifacts/build-distribution/latest/. A build list command requires a new server endpoint.renderCompleteDashboardAsSixel uses one full-dashboard sixel canvas because sixel DCS cursor movement cannot safely coexist with the character framebuffer. The compositor keeps adjacent widgets on their grid row and rasterizes text/table/error content too; if pixel geometry is unavailable it returns the complete established character rendering, and partial sixel replacement is forbidden.createAuthenticatedFetch with auth headers, a 30s timeout, at most 2 retries, 401 refresh, and span tracing. buildAttemptFactory clones Request and must not materialize FormData because doing so strips the boundary. Endpoint overrides include /autofix/ at 120s.~/.sentry/cache/responses/ for GET 2xx responses only, with TTLs stable=5min, volatile=60s, immutable=24h. When @sentry/api passes a Request with undefined init, code must fall back to input.headers or Content-Type is stripped and causes HTTP 415; array operations must guard with Array.isArray(data) because empty/204 SDK responses may be {}.useTestConfigDir(), setAuthToken(), resetCacheState(), disableResponseCache(), and resetAuthenticatedFetch() in beforeEach; response cache lookup happens before fetch, so stale test cache can result in exactly 0 fetch calls.installAgentSkills() in src/lib/agent-skills.ts installs only to ~/.agents/skills/sentry-cli/ and ~/.claude/skills/sentry-cli/; OpenCode is detected through OPENCODE_CLIENT only for telemetry and is never an install target. OpenCode scans ~/.claude/skills/**/SKILL.md and ~/.agents/**/SKILL.md, not .cursor/.plugins/sentry-cli/skills/sentry-cli/SKILL.md with 602 lines plus 28 per-command files under references/. .opencode/ and opencode.json* are gitignored; Cursor symlinks live at .cursor/skills/sentry-cli/ pointing into plugins/. Skill writes are atomic via same-directory temporary .<name>.<pid>.<rand>.tmp followed by rename().node:sqlite on Node 22.15+ and node-sqlite3-wasm on Node 18.0β22.14; a single driver was rejected because node:sqlite is unavailable before Node 22.15.undefined defensively to null, uses a manual transaction wrapper, and must not be included in the standalone SEA binary.src/lib/init/stdin-reopen.ts exports forwardFreshTtyToStdin(deps?), which always returns a Disposable TtyForwardingHandle; repeated calls return NOOP_HANDLE, preventing secondary callers from tearing down the primary installation. If prior isTTY is undefined, it uses Object.defineProperty with isTTY: true, writable: true, and configurable: true; pause and resume become no-ops to avoid Bun kqueue EINVAL.SelfCell<ByteView<'static>, di::Archive<'static>> ownership rather than PR #991βs Rc<Vec<u8>> plus reparsing. The derived_from_cell! macro uses std::mem::transmute and SelfCell::from_raw so objects() returns owned Object cells sharing the same ByteView.Object but must export as ObjectFile using #[wasm_bindgen(js_name = "ObjectFile")]. Archive exposes new(data), peek(data)->Option<String>, fileFormat, objectCount, and objects()->Result<Vec<ObjectFile>>; object getters include debugId, codeId, arch, fileFormat, kind, hasSymbols, hasDebugInfo, hasUnwindInfo, and hasSources.il2cppLineMapping(object, provider) is a free WASM function rather than an ObjectFile method. Its provider receives a path and must return Uint8Array or nullish; provider_bytes() uses dyn_ref::<js_sys::Uint8Array>() and throws a descriptive JavaScript error for other non-null values. Empty mappings return JavaScript undefined; as_debuginfo() is a pub(crate) non-WASM helper.#988 merged write_object_with_source_provider and write_object_with_filter; #989 merged workspace dependencies, cfg-zstd, and required wasm-opt conventions in @sentry/symbolic@13.3.1; #990 merged C zstd on WASM and removed ruzstd; #991 was closed in favor of Dav1ddeβs #992; branch prototype/wasm-artifact-smoke from #992 head fd94b6fe added an artifact smoke test and ObjectFile rename fix across 5 files with +122/-6.toolkit.pnpm+node+vitest.56Γ8 quadrant block-art wordmark; sixel was deferred for a future follow-up rather than permanently rejected.17.5px cell width via autocorrelation and reads a 97Γ13 ASCII grid; area averaging was rejected because it filled the E arms and R counter, striped β because a 50/50 duty cycle dissolved E arms, and solid β because it lost scanline texture. Post-processing removes isolated orthogonal-neighborless cells and small connected components.symbolic-wasm must provide a general-purpose API comparable to the Python package, not CLI-specific shortcuts. CLI-specific collect_il2cpp orchestration and source-bundle semantics belong in getsentry/cli; this avoids coupling a general-purpose library to the CLI.@stricli/core patch targets exactly version 1.2.7 and removes -H from the reserved aliases so curl-style --header/--host aliases remain valid. The dependency must stay pinned to 1.2.7, not ^1.2.8; command-level -H aliases must never be removed. This was added in commit 78c9b04a5.noParameterProperties; classes under src/lib/**/*.ts must declare fields explicitly and assign them in constructor bodies rather than using forms such as constructor(private readonly handle: FileHandle). This caught 4 errors in bspatch.ts at lines 281, 310, 311, and 312.biome check <file>), not --stdin-file-path=<file>; stdin mode produced a false-positive exit code 1 saying βcontents aren't fixedβ even though --write made zero changes during review of agent-skills.ts.bundle-sources.ts:145 directly sets this.process.exitCode = 1 when no sources are found, relying on cli.ts:622-649 not resetting the code; the preferred pattern is OutputError with code 60, though the existing behavior was retained for check.ts consistency with a comment.packages/cli/src/lib/progress.ts is cosmetic and must never abort work; both onProgress and done() remain wrapped in try/catch, and mutation testing confirmed removing these guards fails the never-throws test.check.ts, hasId() uses o.codeId !== null, while @sentry/symbolic@13.4.0 provides ObjectFile.codeId as string | undefined. parseDebugFile must therefore normalize with obj.codeId ?? null so the existing null guard remains valid..github/workflows/ci.yml Node pins must use exact patches: NODE_VERSION_22: "22.23.1" and NODE_VERSION_24: "24.18.0". Matrix selection uses ${{ matrix.node == '24' && env.NODE_VERSION_24 || env.NODE_VERSION_22 }}; floating versions risk cached vulnerable patches.process.env.SENTRY_DASHBOARD_SIXEL = "1" or calling setEnv() in CLI mode; SDK calls replace getEnv() with isolated environments, and process-level writes can leak to later commands.getsentry/cli #1322 β #1325, the original PR remains canonical: reopen it and close the duplicate so review history and squash merge remain on the intended target.mergeStateStatus=UNSTABLE but mergeable=MERGEABLE and only non-gate jobs such as Socket Security, dependency review, nightly publish, skill eval, or delta patches are failing/pending; transient organization-managed dependency-review failures should not block merge after verifying they are non-gates.getsentry/cli docs-regen workflow can force-advance a PR branch after a rebase push with a chore: regenerate docs commit from github-actions[bot]. For PR #1254, pushed head 30ad8b075 advanced to 605e8318d, touching 33 skill-doc Markdown files plus packages/cli/script/bundle.ts; after any force-push, the branch must be re-fetched and local state fast-forwarded before final verification.event/view.ts must run parseSingleArg with HEX_ID_RE before parseSlashSeparatedArg so valid project/<hex-event-id> input is not misclassified as incomplete org/project and rejected with ContextError.0.10.1 makes pnpm run build:all fail by constructing the invalid comma-joined URL https://nodejs.org/dist/v24.18.1/node-v24.18.1-darwin-arm64,darwin-x64,linux-arm64,linux-x64,win-x64.tar.xz, which returns 404. This is not a rebase issue or CI-relevant because CI builds only linux-x64; single-platform verification completed with Build complete: 1 succeeded, 0 failed.https://brand.getsentry.com/share/wLssCFiQ5ZzmQmKCWym4 is an authenticated JavaScript SPA despite returning HTTP 200; HTML/API probing does not expose brand assets, and media.ffycdn.net URLs in the shell are portal chrome. Asset retrieval requires https://brand.getsentry.com/api/screen/download/<signed-token> with a token from an authenticated session or supplied by the user.getCurlInstallPaths() in src/lib/upgrade.ts must guard a stored SQLite install path using existsSync(dirname(stored.path)); if stale, it falls back to a process.execPath starts-with match against KNOWN_CURL_DIRS = ['.local/bin','bin','.sentry/bin'], then defaults to ~/.sentry/bin. Stored paths must remain preferred when valid to preserve npm-to-nightly migration behavior.git rm docs/pnpm-lock.yaml, git commit docs/pnpm-lock.yaml fails because the deleted path no longer matches. The correct command is no-argument git commit, which includes all staged additions and deletions.packages/cli/.cursor/rules/ultracite.mdc applies Ultracite/Biome standards to TypeScript, JavaScript, JSON, HTML, Vue, Svelte, Astro, CSS, YAML, GraphQL, Markdown, and MDX. Commands are npx ultracite fix, npx ultracite check, and npx ultracite doctor; npx ultracite fix should run before committing.unknown over any; use as const for immutable literals; rely on type narrowing; use arrow functions for callbacks/short functions, for...of, optional chaining, nullish coalescing, template literals, destructuring, and const; never use var; await promises; prefer async/await; avoid async Promise executors; throw descriptive Error objects; use early returns; avoid nested ternaries; validate input; avoid eval() and direct document.cookie; avoid spread accumulators in loops, dynamic loop regexes, namespace imports, barrel files, and raw <img> where an image component exists.it()/test(), async/await rather than done, no committed .only or .skip, and reasonably flat suites. Human review must focus in this order: 1. business logic correctness; 2. meaningful naming; 3. architecture decisions; 4. edge cases; 5. user experience; 6. documentation.