Sentry Error Reporting

Optional, opt-in crash and error telemetry — completely disabled by default. No data leaves your machine unless you explicitly set SENTRY_DSN.

TL;DR SENTRY_DSN=https://key@sentry.io/123 claude — that's it. Without it, zero network requests, zero telemetry.

Quick Start

Self-hosted Sentry

SENTRY_DSN=https://public_key@your-sentry.example.com/123 claude

Sentry Cloud

SENTRY_DSN=https://public_key@o123456.ingest.sentry.io/789 claude

Disable (default)

claude

Environment Variables

VariableRequiredDefaultDescription
SENTRY_DSNyesSentry DSN to enable. Without this, everything is no-op.
SENTRY_ENVIRONMENTnoNODE_ENV or productionEnvironment tag in Sentry dashboard
SENTRY_RELEASEnoauto from package.jsonRelease version tag
SENTRY_SAMPLE_RATEno1.0Error sample rate (0.0–1.0)

What Gets Sent

Only error metadata — never prompts, responses, file contents, or command output:

What Does NOT Get Sent

CategoryExamples
Promptsuser input, AI system prompts
Responsesmodel output, streaming chunks
File contentRead/Edit/Write payload, command stdout/stderr
CredentialsAPI keys, tokens, passwords, cookies
Auth headersAuthorization, x-api-key, Cookie, Set-Cookie
OAuth tokensaccess_token, refresh_token, id_token
Environment dumpentire env block (individual vars may appear as tags)
Local pathshome directory anonymized to [HOME]
Breadcrumbsuser actions are not tracked
User identityuser field stripped from all events

Privacy Scrubber

Every event passes through a beforeSend hook that:

  1. Scrubs strings — removes API key patterns (sk-*, Bearer tokens), auth headers, cookie values
  2. Strips stack frame variables — removes vars, pre_context, context_line, post_context
  3. Removes breadcrumbs — user actions are never tracked
  4. Cleans request data — removes headers, cookies, query strings
  5. Anonymizes home directory — replaces paths with [HOME]
  6. Drops oversized strings — over 2000 chars truncated
  7. Recursively scrubs nested objects — drops keys named prompt, response, content, message, input, output, text, body, data, payload, token, key, secret, password, auth, cookie

Checking Status

Use /doctor to check Sentry status:

# When disabled
└ Sentry Telemetry: Disabled (set SENTRY_DSN to enable)

# When enabled
└ Sentry Telemetry: Enabled (https://abcd...xyz@o123.ingest.sentry.io/456)
DSN Masking The DSN is masked in the UI — only the first 8 and last 4 characters of the key are shown. The full DSN is never displayed in any output.

Architecture

SENTRY_DSN set?
  → init.ts: initSentry()
     → @sentry/node (lazy import)
        → beforeSend scrubber
           → Sentry server
  → logError() → captureException() (when enabled)
  → SentryErrorBoundary → captureException() (render crash)
  → gracefulShutdown → closeSentry(2000) (flush on exit)

Files

FilePurpose
src/utils/sentry.tsCore wrapper — init, capture, close, scrubber
src/utils/sentry.test.tsUnit tests (11 tests)
src/entrypoints/init.tsCalls initSentry() at startup
src/utils/gracefulShutdown.tsCalls closeSentry() before exit
src/utils/log.tslogError() sends to Sentry when enabled
src/components/SentryErrorBoundary.tsxReact error boundary for render crashes
src/components/App.tsxWraps app tree in SentryErrorBoundary
src/utils/doctorDiagnostic.ts/doctor Sentry status display