Usage Telemetry
This page tells Claude Code users what devkit sends after a session, what it never sends, and how to switch it off. Telemetry is on by default, pseudonymous, kept privately for 90 days, and used to see which routes work, which checks fail and which shared skills are missing.
Opt out
OD_TELEMETRY=off claudeAccepted off values, case-insensitive: 0, off, false, no, n, disabled, disable; DO_NOT_TRACK=1 also opts out. An explicit opt-out prevents both state writes and uploads. CI or GITHUB_ACTIONS disables uploads only.
Data collected
Each session becomes one JSON object with schema_version: "2" and only these fields:
| Field | Meaning |
|---|---|
schema_version, session_id | Format version; session UUID for server-side deduplication |
runtime | Producing runtime: "claude" or "codex" |
od_version, run_od_version, cli_version | Uploading devkit version; version active at session start; Claude CLI version |
update_state | Update source type of the uploading machine (http, local, missing), age in days of a local source checkout's last commit, whether the last background fetch failed — never the checkout path |
stack | Stack from the generated project context |
repo_remote | Origin reduced to org/repo; may still name a customer |
user | Git email local part, or the OS username without a Git email |
client_id | Random 16-hex installation ID, hashed again by the server |
first_ts, last_ts | First and last session timestamps |
message_counts, headless | User and assistant counts; headless means fewer than two user messages |
tools | Names, invocation counts, aggregate output size |
skills_invoked | Names, invocations, errors, refusals |
slash_commands, missing_skills | Typed slash-command counts; commands matching no built-in, project or devkit skill |
skill_sequence | Ordered skill route, capped at 40 after merging consecutive repeats |
errors, unknown_record_types | Tool-error total; counts of unknown transcript record types |
token_totals, model_mix | Main-session totals; output tokens by model |
subagent_spawns, subagent_tokens | Spawn counts; token totals by subagent type |
stack_file_edits | Edits to stack-associated file extensions |
friction, events | Blocking or failure signals; non-blocking signals grouped by code |
hints | Advisory codes with session counts and whether the hinted action followed |
gates | Reach, first block, eventual pass and unresolved-attempt counts per gate |
spec_ids, entered_by_slash | Observed three-digit spec IDs; whether the first message began with / |
Unavailable data is null, empty or absent. A gate is counted only after it was reached, and an attempt without an outcome is unknown, never a pass or a block.
Data not collected
Prompt and response text, file contents and paths, full email addresses, remote URLs and embedded Git credentials. The collector reads completed Claude transcripts and completed Codex rollouts locally and sends only the fields above. The Codex source is ${CODEX_HOME:-$HOME/.codex}/sessions/**/rollout-*.jsonl; the runtime field distinguishes claude from codex.
Identity and local state
~/.claude/od-usage-buffer/client-id holds the installation ID with mode 600; delete it to reset the ID. The server hashes it with a private salt and stores only a shortened hash. The data is pseudonymous, not anonymous: repo_remote, user and behaviour can still correlate in the private store.
Per-project upload state lives under ~/.claude/od-usage-buffer/<project-hash>/. Nothing is written inside the project.
Delivery and retention
The running session is never uploaded. At a later session start the hook picks completed, not yet accepted transcripts with fewer than five attempts and uploads them in a detached process. Only an accepted POST marks a session uploaded; retries stop after five attempts, and the state disappears with the local transcript.
The data goes to https://devkit.one-dot.io/api/ingest and into a private store; everything older than 90 days is deleted daily. Resetting the local ID changes your future identity, not what is already stored.
Friction reports
A friction report sent via the relay goes to /api/feedback, which files it as a GitHub issue in onedot-digital-crew/onedot-devkit with a server-held token. It is stored nowhere else — no blob, no database, no copy on the server past the request.