Privacy, by construction
How CoSquared handles your data.
This is the plain-language version of how CoSquared handles your data. If anything here ever drifts from what the code does, the code is the bug — the collector is open source precisely so you can check.
last updated july 2026 · canonical source: docs/privacy.md
01Privacy by construction
The core guarantee is not a promise to scrub your data carefully — it is that the sensitive data never enters the pipeline in the first place.
The tool reads the local session stores of Claude Code, Codex CLI, and Cursor — all read-only and metadata-only. When a collector reads a transcript or a repo, it converts everything into a normalized event stream that has no free-text fields. Each event is a set of structural facts — counts, booleans, categories, durations: "a prompt was sent; it was 42 words; it referenced a plan", "a change was accepted; a test run followed it", "a commit touched 3 files, +120/−15 lines".
The prompt text, the code, the diff, the commit message, the file paths — none of it is ever stored in the event. There is no field for it to live in, so there is nothing raw to leak, even by accident. The schema is strict: an unexpected field is rejected at validation, so a bug that tried to smuggle raw text in would fail loudly instead of silently shipping it.
02What never leaves your machine
In any mode, these are never transmitted:
- raw source code and file contents
- API keys, credentials, tokens, and secrets
- environment variable values
- full file paths (only structural counts and ratios, never the paths themselves)
- raw transcripts of your AI coding sessions
03What each mode transmits
You choose a privacy mode at cosq init and can change it anytime; a per-repo config can override it for a single repository.
- Local-only: nothing. Analysis runs entirely offline; no data leaves the machine, ever.
- Metadata (default): event counts, score inputs, deterministic redacted summaries, repo-shape signals (e.g.
has_tests: true), language/framework labels, and your Builder Profile. Never raw code or transcripts. - Rich: designed but deferred — not built. It is the only mode that would put verbatim text on the wire, so it ships only if early users need it and a pre-registered experiment shows it helps. Until then: raw transcript text never leaves your machine, in any mode.
Two small, disclosed relaxations: score evidence cites the calendar date of an example session (never a wall-clock time), and — unless you turn it off with upload_repo_label = false — each synced repo sends its name (the owner/repo slug or folder name) so your dashboard is readable. Never the full path, never for local-only repos, and you can rename or remove any label. A single closed-enum work type label (e.g. backend, student) is inferred locally to tailor recommendations — only the category label is sent, and a value you set by hand is never overwritten.
04Redaction is defense in depth, not the guarantee
For the few free-text surfaces outside the structured schema (today: none in the upload path; later: opt-in crash reports), a redaction engine with rules derived from gitleaks removes secrets before text is ever serialized toward a network buffer. Its test suite is release-blocking.
But redaction is probabilistic, and a probabilistic guard is the wrong foundation for a privacy-first product. The primary mechanism is the no-free-text schema in §01 — there is nothing to redact in the structured path because nothing raw is there to begin with. Redaction guards the edges; it does not hold up the roof.
05Inspect, deletion, and the AI provider
- Inspect before upload.
cosq inspectshows the exact bytes an upload would send — byte-identical, not a summary. - Deletion is honest about backups.
cosq delete --alldeletes your live rows within 24 hours and prints a deletion receipt. Database backup snapshots containing already-deleted data expire within 30 days and are never restored except for disaster recovery. - The AI provider. The coaching prose is the one place an AI model is involved, and it sees only your already-redacted structured profile — the same counts, ratios, and dates the dashboard renders. It never sees your code, prompts, transcripts, or file paths; there is no path for that data to reach it. Calls to Anthropic run under a zero-retention, no-training posture, and the model is constrained to restate computed numbers — never to invent a fact, a trend, or a comparison.
06No default-on telemetry
Error reporting and usage analytics are opt-in and off by default. You are asked once, at cosq init; if you decline (the default), nothing diagnostic is ever collected. If you opt in, crash reports pass through the same redaction pipeline as everything else. There is no hidden, default-on crash reporter.
07Continuous tracking (background sync)
Daily background sync is opt-in — you are asked once during onboarding. A background run sends the exact same metadata-only payload as cosq analyze, governed by the same privacy mode; a local-only repo is never uploaded by sync, and a repo with no new sessions uploads nothing. cosq status shows the state, cosq pause stops it immediately, and cosq delete --scheduler removes the OS timer entirely. The schedule is a normal user-level OS job (launchd on macOS, a systemd user timer on Linux) — never root.
08Weekly report emails
Weekly reports are generated server-side from the metadata-only profiles already on your account — nothing new leaves your machine to produce them. Deltas are computed deterministically; the model that writes the prose sees only those computed numbers. Reports are visible only to you (row-level security, like every other field), and every email carries a one-click unsubscribe that needs no login. Deleting your account removes reports and preferences through the same cascade as everything else.
09Never visible to managers
Your scores and reports are for you. Individual profiles are never visible to managers or admins — a product invariant, not a setting. There is no team roll-up that exposes an individual's numbers.
10Bug reports you choose to send
Everything above describes data collected about your work. The Report a bug form is different: it is the one place where you type free text and ask us to read it. It is manual, never background — nothing is captured unless you open the form and press Send.
What is sent: the fields you fill in, the choices you pick, which app page you started from (one value from a fixed list like dashboard — never a URL), and the email address you signed in with, so we can reply. What is not sent: no scores, no Builder Profile, no repo names or ids, no analysis ids, no code, no transcripts, and no browser fingerprint or User-Agent. The optional "browser and OS" field exists precisely so that context is something you choose to give, in your own words.
Your text is redacted before it is stored — by the same open-source engine described in section 04. Anything shaped like a secret, an API key, a credential in a URL, an email address, or an absolute path under your home directory becomes a [REDACTED:…] placeholder, and the confirmation tells you how many values were removed. Please still don't paste code, prompts, transcripts, or credentials: redaction is defence in depth, not a licence to paste secrets.
The redacted report and your sign-in email are filed in CoSquared's private Notion workspace, where bugs are triaged. A minimal notification goes to the team by email carrying only the short id, the redacted one-line summary, the category labels, the redaction count, and a link — not the body of your report, and not your email address. We save a private copy first so that a temporary Notion or email outage never loses your report or asks you to write it again; that copy is readable only by CoSquared's servers.
Deleting your account deletes it — by the same cascade as everything else, and because the Notion copy lives outside our database, deletion immediately queues that page to be moved to Notion's Trash and cancels any delivery still in progress. Once a report is marked Fixed, Closed, or Won't fix it stays in the active tracker for 90 continuous days (reopening restarts the clock) and is then moved to Trash and removed from our database. To be precise about a limit rather than imply more: the Notion API cannot permanently delete a page, only move it to Trash, so final destruction depends on Notion's trash handling and the workspace owner emptying it.
11Questions
The canonical, versioned source of this policy lives in the public collector repository — docs/privacy.md. Questions or concerns: open an issue — in a privacy-first product, answering these in public is the point.