> ## Documentation Index
> Fetch the complete documentation index at: https://docs.crewship.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Telemetry

> Anonymous crash reporting — defaults by build flavour, the onboarding consent step, the Sentry DSN override, and exactly what does and does not leave your machine.

# Telemetry

Crewship can send anonymous crash reports to help the maintainer
diagnose bugs. This page covers the default for your build, the
onboarding consent step, what is sent, how to opt in/out, and how to
redirect crash data to your own Sentry project.

<Note>
  This guide is about **crash reporting** (the `crewship telemetry`
  command). For distributed-tracing setup (OpenTelemetry spans into a
  collector) see [Tracing](/guides/tracing). Different package, different
  concern — same English word.
</Note>

## Default by build flavour

The default is decided by the version your binary was built from:

| Build flavour     | Version string                                     | Default      |
| ----------------- | -------------------------------------------------- | ------------ |
| Prerelease        | contains `-beta` / `-rc` (e.g. `v0.1.0-beta.4`)    | **Enabled**  |
| Dev / unversioned | `dev`, empty, bare commit SHA                      | **Enabled**  |
| Stable release    | `vX.Y.Z` with no prerelease suffix (e.g. `v1.0.0`) | **Disabled** |

On a **prerelease or dev build**, the first `crewship start` enables
telemetry automatically and writes a consent row to the local database
— non-interactive deployments (Docker, systemd, CI) would otherwise end
up silently telemetry-less, and a solo maintainer needs the crash
signal while a release is still baking. (Dev builds ship with an empty
compiled-in DSN, so nothing is actually sent unless you set
`CREWSHIP_SENTRY_DSN`.)

On a **stable release**, telemetry is strictly **opt-in**: nothing is
enabled and nothing is written until you explicitly consent — in the
onboarding wizard, or with `crewship telemetry on`.

Your explicit choice is sticky in both directions. Once you've answered
— via onboarding or the CLI — no version default ever overrides it,
including across upgrades.

## Onboarding asks explicitly

Both onboarding surfaces include a consent step, so even on a
prerelease build you get an explicit choice the first time you set up
a workspace:

* the **web wizard** shows a "Send anonymous crash reports" checkbox in
  the final step, pre-ticked to your build's default;
* **`crewship setup`** asks the same question interactively, or takes
  `--telemetry=true|false` for scripted runs (omit the flag with
  `--yes` to keep the server's default).

The answer is stored exactly as if you had run
`crewship telemetry on|off` yourself.

## Opting out

```bash theme={null}
crewship telemetry off
```

Output:

```
Telemetry disabled. No crash reports will be sent.
```

The setting is stored in `app_settings.telemetry_opt_in` in the local
SQLite database and survives binary upgrades. To opt back in:

```bash theme={null}
crewship telemetry on
```

## Checking current state

```bash theme={null}
crewship telemetry status
```

Sample output when enabled:

```
Telemetry: ENABLED
  install_id: 7c4a9f1e2b...
  endpoint:   o12345.ingest.sentry.io (vendor default (compiled in))
  to disable: crewship telemetry off
```

* `install_id` — anonymous random identifier (32 hex chars) generated
  on first opt-in, stable across opt-out/opt-in cycles. The backend
  uses it only to group crashes by install; it carries no PII.
* `endpoint` — the host portion of the resolved Sentry DSN, so you can
  see *where* events route without the full secret-shaped URL ending
  up in terminal scrollback.

## Routing to your own Sentry

If you self-host or have a regulated environment that can't share
crash data with the vendor, point Crewship at your own Sentry project
with the `CREWSHIP_SENTRY_DSN` env var:

```bash theme={null}
CREWSHIP_SENTRY_DSN=https://<key>@<org>.ingest.sentry.io/<project> crewship start
```

Resolution order (most specific wins):

1. `CREWSHIP_SENTRY_DSN` environment variable
2. The vendor DSN compiled into the release binary
3. Empty — telemetry stays off regardless of consent

`crewship telemetry status` will show `CREWSHIP_SENTRY_DSN env override`
as the source when your value is in use. Local development builds ship
with an empty compiled-in DSN, so they are off by default unless you
provide one.

## What is sent

When telemetry is enabled:

* Go **stack traces** and **error messages** (subject to scrubbing —
  see below)
* Crewship **version**, commit SHA, OS, and architecture
* The anonymous **install ID** (random 32-hex)
* A **Sentry "environment"** tag derived from the version (`beta`,
  `production`, `development`)

## What is never sent

The client-side `BeforeSend` hook in `internal/crashreport/sentry_adapter.go`
strips the following before the event leaves the process:

* Workspace, user, or credential data
* HTTP request bodies
* `Authorization`, `Cookie`, `Set-Cookie`, `X-API-Key`, `X-Auth-Token`,
  `X-CSRF-Token`, `X-Amz-Security-Token`, `Proxy-Authorization`, and
  `X-Crewship-Internal-Token` headers
* Query-string keys whose name contains `token`, `secret`, `password`,
  `auth`, `session`, `code`, or `key`
* Environment variables
* The machine hostname — Sentry's `ServerName` field is overridden
  with the anonymous install ID
* The Go module list, runtime/device/culture contexts that `sentry-go`
  normally attaches

The pinning test `TestScrubEvent_DropsLeakyContexts` in
`internal/crashreport/crashreport_test.go` enforces this list — adding
a new context to the Sentry event requires updating the scrub hook *or*
the test fails.

### Server-side scrubbing as a defense in depth

The client scrub catches everything in structured fields. It cannot
reliably catch free-form strings *we* generate, e.g.
`fmt.Errorf("auth failed for %s", userEmail)`. The maintainer's Sentry
project has server-side regex scrubbing rules enabled (`@email-pattern`,
`@password-pattern`, `@creditcard-pattern`, bearer-token and API-key
regexes) to mask anything that slips through.

If you've routed Crewship to your **own** Sentry project via
`CREWSHIP_SENTRY_DSN`, configure the same rules under **Project
Settings → Security & Privacy → Data Scrubbing**. The full rule list
is documented in [RELEASING.md](https://github.com/crewship-ai/crewship/blob/main/RELEASING.md#telemetry-crash-reporting--sentry-setup).

## Verifying nothing leaks

The cheapest end-to-end check is to opt in temporarily, raise a test
error in your own Crewship instance, and inspect the event in the
Sentry UI:

1. `crewship telemetry on`
2. Trigger a known-safe error (e.g. `crewship retry <run-with-nonexistent-id>`)
3. Open the resulting Sentry event
4. Confirm headers/query/env contexts are absent and `ServerName`
   matches your install ID

If anything looks wrong, **file an issue** (security label) at
[github.com/crewship-ai/crewship/issues](https://github.com/crewship-ai/crewship/issues)
and opt out (`crewship telemetry off`) while it's investigated.

## Related

* [Tracing (OpenTelemetry)](/guides/tracing) — distributed tracing
  pipeline, different package, different opt-in surface.
* [Threat model](/security/threat-model) — broader security posture.
* [`PRIVACY.md`](https://github.com/crewship-ai/crewship/blob/main/PRIVACY.md)
  in the repo (PR #441) — first-pass privacy policy: data controller
  (Unify Technology s.r.o.), GDPR rights, supervisory authority (ÚOOÚ),
  and the two real outbound surfaces (the `crewship doctor` update
  check + the optional background update notifier on `crewship start`,
  both GitHub-Releases-API only).
* [`NOTICE`](https://github.com/crewship-ai/crewship/blob/main/NOTICE)
  * [`THIRD-PARTY-NOTICES.md`](https://github.com/crewship-ai/crewship/blob/main/THIRD-PARTY-NOTICES.md) —
    Apache-2.0 §4.4 attribution + auto-generated dependency NOTICE
    aggregate (Next.js, Prisma, Docker Go SDK, cosign).
* `RELEASING.md` in the repo — maintainer-side Sentry project setup.
