Skip to main content
PathDocs

Data and Privacy

Short version: by default DSH uploads session telemetry (which can be disabled); credentials and sessions are stored locally (0600 / zstd); an anonymous user.id is used for statistics. This page explains "what leaves the machine, who can see it, and how to turn it off".

1. Telemetry (on by default)

Under the default configuration, session telemetry is enabled:

  • Content: a raw copy of the session log: full user/assistant messages, tool arguments and results, system prompts, and the local session.cwd path
  • Cadence: batched export (configured by scheduledDelayMillis etc. in the OTel SDK processor, adjustable)
  • Endpoint: the deployer-level default is https://harness-telemetry.deepseeksvc.com/v1/logs (overridable with DSH_TELEMETRY_OTLP_URL; in OTel exporter.url is required with no default)
  • Identity: the anonymous user.id (see below)

Three modes

session-telemetry-otel's mode decides whether the telemetry seam follows session events, only replays at recording feedback, or stays local:

modeWhat gets reported
FULLDefault. Every projected record (including lifecycle ops) is handed to the OTel SDK immediately
FEEDBACK_ONLYOn each feedback/record, replays, projects, and redacts the log suffix before that event; later records wait for the next feedback, or stay local if none comes
DISABLEDNo pipeline is constructed, no record leaves the process; feedback stays in the local session log

The upload modes (FULL / FEEDBACK_ONLY) both require exporter.url (no default; must resolve to http(s)); under DISABLED the exporter can be omitted and is ignored. All three modes share one sharing disclosure (full / feedback-only / disabled), and /feedback confirmation reports how the session is shared accordingly.

Exporter configuration

# Override by id in the deployer-level composition (see Configuration)
- id: session-telemetry-otel
name: '@deepseek-ai/dsh-session-telemetry-otel'
config:
mode: FULL
shutdownTimeoutMillis: 3000 # optional, outer DSH shutdown deadline, default 3000ms
exporter: # passed verbatim to the OTLP/HTTP log exporter
url: https://collector.example.com/v1/logs
headers:
authorization: !!js `Bearer ${process.env.OTLP_TOKEN}`
processor: {} # optional, passed verbatim to BatchLogRecordProcessor

Both exporter and processor are passed through wholesale to the SDK: headers, timeoutMillis, compression, keepAlive, etc. reach the exporter; batching, export cadence (scheduledDelayMillis), retries, queue limits, and the drop-policy under sustained failure are all SDK behavior, tuned via processor. Field mapping: timetimestamp/observedTimestamp, severityseverityNumber/severityText (INFO 9 / WARN 13 / ERROR 17), body → the structured log body, attributes passed through as-is; the receiver deduplicates by (session.id, event.seq) and can alert by severity.

The seam carries no redaction rules: with no session-telemetry/record listener, the raw captured copy is what's uploaded. Deployments crossing trust boundaries must mount their own redaction rules (see Session System). FULL redacts at append time; FEEDBACK_ONLY keeps no telemetry copy and redacts with the currently-mounted rules when recording feedback.

Disabling telemetry

export DSH_TELEMETRY_DISABLED=1 # any non-empty value, including 0 / false

Restart dsh for it to take effect; disabling affects no functionality. You can also use OTel's mode: DISABLED.

2. Anonymous user ID (.anonymous-user-id)

  • File: ~/.dsh/.anonymous-user-id, whose content is a random UUID
  • Generation rule: not derived from any identifiable source such as hostname, NIC, or git remote: purely random
  • Deleting the file resets the identity (a new UUID is generated at the next startup)

The same id appears in three places, letting the receiver correlate without building its own identity:

UseForm
Telemetryuser.id on the OTel Resource, used for aggregate statistics and issue triage
Feedback confirmationthe /feedback confirmation text carries the same value
DeepSeek requestsdsh-llm-deepseek sends it in the x-deepseek-harness-user-id header

Two easily-misunderstood points:

  • DSH_TELEMETRY_DISABLED only stops telemetry export, not the feedback confirmation or the DeepSeek request header — disabling telemetry is not disabling identity correlation
  • The id reaches DeepSeek only as HTTP transport metadata; it never enters the request body, prompts, or any model-visible content

In-process it is memoized by file path for the process lifetime; the first write uses exclusive creation and concurrent losers adopt the persisted winner; if the write fails (e.g. home not writable), it falls back to a process-local UUID without blocking telemetry or feedback.

3. Session data

  • All session logs live locally in ~/.dsh/sessions/ (by default a zstd-compressed session.jsonl.zstd, in the two-level --<cwd>--/<id>/ directories), including conversations, tool calls, and working-directory paths
  • Sessions persist locally; deleting the directory clears them

Want to head/jq the plaintext directly? Configure compression: 'none' or zstdcat first (see Session System).

4. Credentials

FileContentPermissions
~/.dsh/.credentials.yamlManaged structured credentials0600 (0700 directory)
~/.dsh/.envEnv-layer fallbackPermissions self-managed

Don't commit credentials into a repository; the managed .credentials.yaml is written atomically at 0600 by DSH, while .env is an ordinary env layer whose permissions are your own responsibility.

5. Network egress list

DestinationUseCan be disabled
api.deepseek.comLLM calls (chat-completions + anthropic/v1)Bypassable by switching provider
harness-telemetry.deepseeksvc.comSession telemetryDSH_TELEMETRY_DISABLED=1
Custom provider endpointsThe model gateways you configureControlled at the configuration level

6. Best practices

  1. Before using on sensitive projects, evaluate the telemetry policy (or just disable it)
  2. Watch out for the network behavior of third-party plugins (telegram/zotero etc. have outbound capability)
  3. Deleting .anonymous-user-id resets anonymity but does not affect the telemetry switch
  4. Session logs are zstd-compressed by default; redact before backup/sharing

Next steps