Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
080ae3c
docs(spec): Codex analytics core design (piece 1 of Codex support)
Anuj7411 Oct 8, 2026
04707cf
docs(plan): Codex analytics core implementation plan (17 tasks)
Anuj7411 Oct 8, 2026
38bad06
feat(transcript): per-request key on turns, agent field on sessions
Anuj7411 Oct 8, 2026
49da2bf
feat(transcript): dedupe requests repeated across session files
Anuj7411 Oct 8, 2026
5c84f0a
fix(transcript): order dedupe by parsed start time, undated last
Anuj7411 Oct 8, 2026
ac5ad23
fix(transcript): dedupe tie-break, refreshed times, prior reads acros…
Anuj7411 Oct 8, 2026
cbf3801
docs(plan): no time pre-filter before dedupe; full-vector legacy Code…
Anuj7411 Oct 8, 2026
b5ad4ba
feat(agents): Agent.matchesCwd for --here scoping
Anuj7411 Oct 8, 2026
a313dd5
refactor(transcript): shared read-path helper; prior-read counts incl…
Anuj7411 Oct 8, 2026
c91e8c1
feat(agents): shared loadSessions (discover, --here, dedupe)
Anuj7411 Oct 8, 2026
df06ada
feat(transcript): scanClaudeRequestKeys, parse-free request-key scan
Anuj7411 Oct 8, 2026
8a5b062
perf(agents): loadSessions windowSinceMs scans out-of-window files fo…
Anuj7411 Oct 8, 2026
04c72b1
docs(plan): Task 5 passes windowSinceMs and surfaces parse issues
Anuj7411 Oct 8, 2026
d96e62b
fix(transcript): key scan no longer pins the scanned file text; exact…
Anuj7411 Oct 8, 2026
008f586
fix(stats,today,forecast,trend,impact): count requests repeated acros…
Anuj7411 Oct 8, 2026
edd44b4
fix(transcript): key scan defers ambiguous lines to the exact parser
Anuj7411 Oct 8, 2026
412eef9
fix(dedupe,impact): order-independent usage across copies; impact not…
Anuj7411 Oct 8, 2026
25df22a
feat(pricing): OpenAI price table for Codex models
Anuj7411 Oct 8, 2026
8edd518
fix(dedupe): raise-only sessions keep their parsed time span
Anuj7411 Oct 8, 2026
198fb77
fix(pricing): loose model match accepts only snapshot-id suffixes
Anuj7411 Oct 8, 2026
cd2c133
feat(codex): detect single-file shell reads
Anuj7411 Oct 8, 2026
b7038b9
fix(pricing): only date-shaped snapshot suffixes borrow a base model'…
Anuj7411 Oct 8, 2026
d20b4d1
fix(codex): stricter shell-read detection; support Select-Object and …
Anuj7411 Oct 8, 2026
3857ad2
feat(codex): rollout parser with Codex token accounting
Anuj7411 Oct 8, 2026
47d7879
fix(codex): failed-read check reads unified exec exit codes; anchor e…
Anuj7411 Oct 8, 2026
f770223
fix(codex): exec wrapper scan skips an unbalanced look-alike instead …
Anuj7411 Oct 8, 2026
53f57d6
fix(codex): a bare \server base is not absolute (win32.resolve borrow…
Anuj7411 Oct 8, 2026
acaebdf
feat(codex): rollout discovery
Anuj7411 Oct 8, 2026
efa48d5
feat(codex): Codex agent adapter (analytics)
Anuj7411 Oct 8, 2026
f7f50d4
feat(agents): resolve which agents to show; combined line
Anuj7411 Oct 8, 2026
862c7ee
feat(stats): one section per installed agent
Anuj7411 Oct 8, 2026
77c5665
feat(today): one section per installed agent
Anuj7411 Oct 8, 2026
cbc55f5
feat(forecast): one section per installed agent
Anuj7411 Oct 8, 2026
08bdfaa
feat(trend): one section per installed agent
Anuj7411 Oct 8, 2026
083a845
feat(impact): one section per installed agent
Anuj7411 Oct 8, 2026
02b763e
feat(codex): smaller discovery reads; --agent help lists codex
Anuj7411 Oct 8, 2026
86c111d
test(agents): runSections layout and exit codes
Anuj7411 Oct 8, 2026
1e81c32
fix(agents): Cursor + Codex shows Codex alone; empty states key on ag…
Anuj7411 Oct 8, 2026
831fc9d
feat(agents): pickLatestSession across agents with a hint for the other
Anuj7411 Oct 8, 2026
4f52b68
feat(loadSessions): load given sessions; scanOnly sessions only claim…
Anuj7411 Oct 8, 2026
b6a956a
feat(why,drift,pricing): agent-aware wording, OpenAI price date, pick…
Anuj7411 Oct 8, 2026
6ec0232
feat(why,receipt,drift): latest session across agents with a hint for…
Anuj7411 Oct 8, 2026
1c5dfa6
fix(why,receipt): report a resumed session's own requests only
Anuj7411 Oct 8, 2026
683ac35
fix(receipt): Codex receipts keep 8 id characters
Anuj7411 Oct 8, 2026
6e67dfb
fix(drift): prune the cache by line count; keep room for two agents
Anuj7411 Oct 8, 2026
9ed8c9d
feat(mcp): optional agent input on session tools
Anuj7411 Oct 8, 2026
eff36f4
fix(why,receipt): skip a resumed session that is all copied history
Anuj7411 Oct 8, 2026
dbc4123
fix(why,receipt,drift): the other-tool hint keeps --here
Anuj7411 Oct 8, 2026
ed1fd2b
fix(drift): --here with nothing in this folder says so
Anuj7411 Oct 8, 2026
dc130ae
test(drift): Codex skips the MCP attribution and the configs.jsonl write
Anuj7411 Oct 8, 2026
c5c5e53
perf(drift): read only what the report uses; dedupe with dropCopiedRe…
Anuj7411 Oct 8, 2026
262de43
refactor(loadSessions): drop the drift-only sessions/scanOnly options
Anuj7411 Oct 9, 2026
2dec91c
fix(why,receipt,drift): --json --session searches both tools
Anuj7411 Oct 9, 2026
4fb34b2
fix(codex): show Codex ids with their timestamp and random bits
Anuj7411 Oct 9, 2026
48dbf1e
perf(today,forecast): cache each transcript's token usage
Anuj7411 Oct 9, 2026
639f03c
fix(receipt): the ambiguity error suggests a command that runs
Anuj7411 Oct 9, 2026
dc5a70c
chore: independent token counter to cross-check every period command
Anuj7411 Oct 9, 2026
a12056f
test(codex): anonymised real-rollout fixtures checked against the ind…
Anuj7411 Oct 9, 2026
6cbf9af
test: per-test timeouts for slow scans; keep snapshot files LF on Win…
Anuj7411 Oct 9, 2026
ea3db7a
fix(copy): say "not supported for Codex yet" instead of promising a r…
Anuj7411 Oct 9, 2026
9cc5f27
docs: Codex section, local caches, drift flags, 1.7.0 changelog
Anuj7411 Oct 9, 2026
e6bd1a2
release: v1.7.0 (Codex analytics)
Anuj7411 Oct 9, 2026
18df9c0
fix(pricing): stale-price warning follows the newest bundled table
Anuj7411 Oct 9, 2026
15b86b1
docs: Node.js 20 or newer, matching package.json engines
Anuj7411 Oct 9, 2026
f536d06
docs(privacy): the npm package is `sipcode`; pricing tables ship unde…
Anuj7411 Oct 9, 2026
d6a8ebf
fix(copy): no em-dashes in the lines this release edited
Anuj7411 Oct 9, 2026
715e590
fix(why,receipt): say when a model has no known price
Anuj7411 Oct 9, 2026
8110265
fix(cache): parallel writes in one process no longer share a temp file
Anuj7411 Oct 9, 2026
c62a1ee
docs(privacy): the drift cache keeps a readable project folder name, …
Anuj7411 Oct 9, 2026
b80a02d
docs: 1.7.0 changelog notes the stale-price warning fix; 1,931 tests
Anuj7411 Oct 9, 2026
4c0fa7e
fix(codex): scan Codex logs for request keys; read only a session's f…
Anuj7411 Oct 9, 2026
6ab4728
perf(load): stream sessions through a dedupe index instead of holding…
Anuj7411 Oct 9, 2026
54e1a61
fix(here): logs outside --here still claim their copied requests
Anuj7411 Oct 9, 2026
e7b70a2
fix(agents): Claude Code has logs only when it has a transcript
Anuj7411 Oct 9, 2026
f4b16cf
fix(drift): one empty-session rule, warm or cold
Anuj7411 Oct 9, 2026
82f11f9
fix(json): say when a --json cost leaves out tokens on unpriced models
Anuj7411 Oct 9, 2026
1060029
fix(pricing): price the Codex models OpenAI lists a price for
Anuj7411 Oct 9, 2026
c439f11
fix(impact): --agent cursor prints the coded E009 like every other co…
Anuj7411 Oct 9, 2026
1a2c4e7
fix(impact): no "rules --install" advice for Codex
Anuj7411 Oct 9, 2026
73b3f31
feat(impact): label a Codex before/after as not caused by Sipcode
Anuj7411 Oct 9, 2026
08aec8d
fix(json): today/forecast/trend/impact --json report skipped logs on …
Anuj7411 Oct 9, 2026
9adcfc0
fix(today): the top leak counts re-reads, not reads (4 reads are 3 re…
Anuj7411 Oct 9, 2026
5c0d54e
fix(codex): archived-only Codex users are detected (isInstalled check…
Anuj7411 Oct 9, 2026
c5325c8
fix(stats): --html writes stats-codex.html for Codex every time, stat…
Anuj7411 Oct 9, 2026
6edb0ce
fix(stats): a Codex section's metaPricing and "prices from" show the …
Anuj7411 Oct 9, 2026
4db66ad
chore: remove dead code (listSessionsHere, findSessionById, pickLates…
Anuj7411 Oct 9, 2026
618e351
docs(code): fix stale comments (agent types, MCP server tool list and…
Anuj7411 Oct 9, 2026
bd8d27e
fix(cache): reading the usage cache removes temp files a killed write…
Anuj7411 Oct 9, 2026
a75f779
fix(action): run the package by its npm name (sipcode), not @sipcode/cli
Anuj7411 Oct 9, 2026
f6ed310
docs(readme): install Node 20+ on Linux the official way (nodejs.org,…
Anuj7411 Oct 9, 2026
1956bf0
docs(privacy): drop the major-version promise from Future telemetry
Anuj7411 Oct 9, 2026
22edc24
fix(manifest): --delta / --explain say they are not supported, with n…
Anuj7411 Oct 9, 2026
6fe79dc
docs: 1.7.0 changelog lists the review fixes; test count 2,014
Anuj7411 Oct 9, 2026
f48294c
docs: changelog verify-counts numbers from the final run (210 match, …
Anuj7411 Oct 9, 2026
ed2419b
perf(load): measure a log's UTF-8 size only when the usage cache need…
Anuj7411 Oct 9, 2026
5611daa
perf(fs): read logs as bytes, then decode, so the previous log is not…
Anuj7411 Oct 9, 2026
08809f7
docs: test count 2,015
Anuj7411 Oct 9, 2026
e23d5c2
docs: changelog gives the real-data peak memory (about 1.5 GB, 2.3-3.…
Anuj7411 Oct 10, 2026
80fc038
docs: test count 1,996 (2,015 counted the 19 e2e tests twice)
Anuj7411 Oct 10, 2026
f23b2ac
fix(copy): say Codex once in the setup-not-supported lines
Anuj7411 Oct 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# vitest writes snapshot files with LF line endings on every platform. Without
# this, core.autocrlf=true on Windows checks them out as CRLF, vitest rewrites
# them as LF on the next run, and git reports them modified.
*.snap text eol=lf
56 changes: 55 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,61 @@ This log starts at v1.6.5 (the reliability-pillar repositioning). Earlier histor

## [Unreleased]

_Nothing landed since [1.6.21]._
_Nothing landed since [1.7.0]._

## [1.7.0] - 2026-10-09

Sipcode now reads OpenAI Codex CLI session logs for spend analytics, and Claude Code totals no longer count requests that a resumed session copies from its parent.

### Added
- **Codex spend analytics.** `stats`, `today`, `forecast`, `trend`, `impact`, `why`, `receipt` and `drift` read Codex session logs (`~/.codex/sessions` and `~/.codex/archived_sessions`, or the folder `CODEX_HOME` points to). `--agent codex` shows Codex only.
- **Both tools in one view.** With no `--agent` flag and both tools installed, `stats`, `today`, `forecast`, `trend` and `impact` print one section per tool, and `stats`, `today` and `forecast` end with a `Both tools:` line (total tokens, then each tool's cost). `why`, `receipt` and `drift` report on the newest session across both tools and print a one-line hint when the other tool has a recent session too. `--json` stays one tool per call: without `--agent` it covers Claude Code and says on stderr that Codex logs were found, so scripts keep working.
- **`--here` for Codex**, matched against the working folder Codex records for each session.
- **How Codex tokens are counted.** Sipcode reads Codex's per-request usage records, or, in logs from older Codex versions, the change in the running total Codex logs after each request. Cached input is part of Codex's input count, so it is never billed twice. A request copied into a resumed or forked file counts once. On the maintainer's machine, Sipcode's per-file totals equal Codex's own final `total_token_usage` on all 15 real session logs.
- **OpenAI prices.** Codex models are priced from OpenAI's API price table (developers.openai.com/api/docs/pricing, and each Codex model's page under developers.openai.com/api/docs/models, as of 2026-10-09: gpt-5-codex, gpt-5.1-codex, gpt-5.1-codex-max, gpt-5.1-codex-mini, gpt-5.2-codex, gpt-5.3-codex, codex-mini-latest), including the long-context rate for prompts over 272,000 input tokens. A model with no known price is shown as unpriced: its tokens are counted, a line says how many the cost leaves out, and it is never shown as $0.
- **MCP:** the 7 session tools take an optional `agent` input (`"claude-code"` or `"codex"`). Still 15 tools.
- **`drift --agent`, `--here` and `--session <id>`.** Pick the tool, limit the check to the folder you are in, or check a specific session instead of the latest.
- Codex short session ids are 18 characters (the UUIDv7 timestamp plus random bits), so sessions started close together stay distinct. Claude Code ids are unchanged.

### Fixed
- **Requests copied into resumed Claude Code sessions were counted twice.** When Claude Code resumes a session, the new log file repeats requests from the old one, and Sipcode summed both. On one real machine, counting exactly the files Sipcode reads: 13.37B tokens summed vs 12.00B unique, 11.4% over (3,163 repeated requests in 8 resumed-session files). `stats`, `today`, `forecast`, `trend` and `impact` now count each request once.
- **`why` and `receipt` on a resumed session included the parent's copied requests.** Worst real case: a session shown as $218.00 whose own spend was $10.20. They now report the session's own requests, and skip a resumed session that holds nothing but copied history.
- **`verify_sipcode_impact` (MCP) output now parses as JSON.** A note used to be appended after the JSON.
- **`stats --since all`** counted days from 1970 ("20735 days"). The window now starts at your earliest session.
- **`why` and `receipt` warned that pricing was out of date (E004) for any older session**, because an older session is priced with the price table of its own date. The warning now checks the newest table Sipcode ships, and a Codex section of `stats` checks the OpenAI table.
- **Cursor next to other tools:** with no `--agent` flag, a Cursor pick now shows the tools whose logs Sipcode can read (Claude Code, Codex), instead of a Cursor section that could only report error E009. Cursor's E009 stays when neither has logs.
- **An empty `~/.claude/projects` no longer hides Codex.** Claude Code counts as having logs only when it has a transcript, the same rule for every command: `why --json`, `receipt --json` and MCP `audit_latest_session` failed with E003 while Codex had sessions.
- **`--here` and copied requests.** Logs outside the folder still claim the requests they hold, so a Codex fork whose parent ran in another folder reports only its own requests in period commands, as `why` does.
- **`drift` picked a session with turns but no token usage as "latest"** when its metrics were cached. Warm and cold runs now use one rule: a session counts only if it used tokens.
- **Unpriced tokens in `--json` and MCP.** `stats`, `today`, `forecast`, `trend` and `impact --json` print the "tokens on models without a known price" note on stderr, as `why` and `receipt` do; MCP tools return it as its own text item after the JSON. JSON schemas are unchanged.
- **Skipped logs in `--json`.** `today`, `forecast`, `trend` and `impact --json` print the note about compressed or unreadable logs on stderr, as in terminal mode.
- **`impact`:** `--agent cursor` prints the coded E009 like every other command; with no install marker, Codex users are no longer told to run `rules --install` (it returns E009 for Codex).
- **`today`'s top leak counted reads as re-reads** ("4 re-reads" for a file read 4 times); it now says 3.
- **Codex users whose rollouts are all archived** (`archived_sessions` only) were not detected.
- **`stats --html`** writes `.sipcode/stats-codex.html` for Codex every time (it used to depend on section order) and `.sipcode/stats.html` for Claude Code. A Codex section's `metaPricing` and "prices from" line show the OpenAI table date.
- **The usage cache** no longer leaves a temp file behind for good when a run is killed mid-write.
- **The GitHub Action** ran `npx @sipcode/cli@latest`; the package is `sipcode`.

### Changed
- **Lower memory for period commands.** `stats`, `today`, `forecast`, `trend` and `impact` read, dedupe and analyze one log at a time instead of holding every session in memory. On a synthetic 480,000-request log folder, peak memory went from 642 MB to 238 MB for `stats --since all` and from 752 MB to 265 MB for `today` (first run). On one real 2.4 GB log folder, `stats`, `today`, `trend` and `impact` peak at about 1.5 GB, against 2.3 to 3.4 GB in 1.6. Windowed `stats` and `trend` read only older logs that can hold a copy of a request in the window, and only their request keys (Codex logs too), so `stats` for 30 days is back to its 1.6 speed.
- **More Codex models priced:** gpt-5-codex, gpt-5.1-codex, gpt-5.1-codex-max, gpt-5.1-codex-mini, gpt-5.2-codex and codex-mini-latest, from each model's page on developers.openai.com (as of 2026-10-09). The OpenAI table is now dated 2026-10-09.
- **`impact` on Codex** shows one more line wherever it compares before and after: Sipcode does not act inside Codex yet, so the difference is not caused by Sipcode (on stderr with `--json`, its own item in MCP).
- **`manifest --delta` / `--explain`** now say they are not supported, with no version promise.
- **README:** Node.js on Linux is installed from nodejs.org (nvm), since Ubuntu's own package is often older than Node 20.
- **PRIVACY.md:** the Future telemetry section keeps its substance (opt-in, off by default, announced) without the major-version promise.
- **`today` and `forecast` are faster on repeat runs.** In measurement on a warm cache, `today` went from about 30-43s to about 1.4s and `forecast` from 24-32s to about 0.5s, with byte-identical output. The first run takes as long as before. They keep a local cache at `~/.sipcode/usage-cache/<agent>.json`: token counts, models, timestamps, the session's working folder and the paths of files the agent read. Never message text, never uploaded. [PRIVACY.md](PRIVACY.md) says how to delete it.
- **`drift` has a new cache file**, `~/.sipcode/drift/sessions-v3.jsonl`, built automatically on the first run. The old `sessions.jsonl` is no longer used and can be deleted. Drift is also faster: about 6.1s to 2.3s cold and 1.24s to 0.29s warm in measurement.
- **Help text:** every `--agent` option lists `codex`, and `why` describes itself as auditing Claude Code or Codex sessions.
- Commands that do not read Codex say "not supported for Codex yet" (error E009) for `--agent codex`, instead of showing Claude Code data under a Codex flag.

### Not supported for Codex yet
- Writing rules to `AGENTS.md` (`rules`, and the rules step of `init`), registering the MCP server in Codex, the proxy and hooks (`proxy`, `hygiene`), `estimate` and `benchmark`.
- Compressed Codex logs (`.jsonl.zst`) are skipped, and a note says how many.

### Internal
- `scripts/verify-counts.mjs` (dev only, not shipped): an independent token counter that imports nothing from Sipcode and cross-checks every period command, cold and warm cache, against the same Claude Code and Codex logs. On the maintainer's real logs: 210 checks match, 0 mismatches (Claude Code: 188 files, 26,782 requests, 3,182 copied requests dropped across 8 files; Codex: 15 files, 930 requests).
- Three slow tests got their own timeouts after measuring past or near vitest's 5s default under full-suite load. Snapshot files are pinned to LF line endings (`.gitattributes`), so a test run on Windows no longer leaves them modified.
- Test count: 1,404 to 1,996 (`npx vitest run`, which includes the 19 e2e tests).

## [1.6.21] — 2026-10-08

Expand Down
19 changes: 12 additions & 7 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ Sipcode is a CLI that reads your machine and writes to your machine. it does not
local files only:

- **`~/.claude/projects/<hash>/*.jsonl`** — claude code's own session transcripts, which it already writes to your machine. `sipcode why`, `stats`, `receipt`, `benchmark` parse these read-only.
- **`~/.codex/sessions/` and `~/.codex/archived_sessions/`** (or the folder `CODEX_HOME` points to): OpenAI Codex's own session logs, read-only, by `stats`, `today`, `forecast`, `trend`, `impact`, `why`, `receipt` and `drift` (and the MCP session tools) when Codex is installed.
- **your repo's source files** — for `manifest`, `score`, `init`. tree-sitter does the parsing in-process.
- **git history (via local `git`)** — for hot-files and change-frequency. invokes the `git` binary on disk via the standard child-process API.
- **the pricing file shipped in the npm package** — `src/lib/pricing/*.json`. ships with each release. never fetched.
- **the pricing files shipped in the npm package**: `dist/lib/pricing/*.json` (Anthropic and OpenAI tables). ships with each release. never fetched.

## What sipcode writes

Expand All @@ -29,11 +30,15 @@ every write is triggered by a command you ran. no background writes, no opportun
- **one named sub-block in your `CLAUDE.md`** — between recognizable markers. `sipcode rules --uninstall` reverses it byte-identically.
- **optional entries in `~/.claude/settings.json`** — ONLY when you run `sipcode hygiene --install`. never otherwise. `--uninstall` removes them.
- **optional hook scripts at `~/.claude/hooks/sipcode-*.mjs`** — same gate. these scripts also run zero-network; the privacy guard test scans them too.
- **local caches under `~/.sipcode/`**, written by the commands that use them, so repeat runs do not re-read every log:
- `~/.sipcode/usage-cache/claude-code.json` and `~/.sipcode/usage-cache/codex.json` (`today`, `forecast`): for each session log, its size and modified time plus token counts, model names, timestamps, request ids, the session's working folder and the paths of files the agent read. never message text, prompts, file contents or command output.
- `~/.sipcode/drift/sessions-v3.jsonl` (`drift`): per-session metrics (session id, end time, token counts, cache-hit rate, duplicate-read tokens, and the project folder as a readable encoded name such as `C--Projects-app`). `~/.sipcode/drift/configs.jsonl` keeps the names of your Claude Code MCP servers over time, so drift can say when a change lines up with a regression. an older `~/.sipcode/drift/sessions.jsonl` from before v1.7.0 is no longer used and can be deleted.
- none of these are ever uploaded. to remove them, delete the folder (for example `rm -rf ~/.sipcode/usage-cache ~/.sipcode/drift`). they are rebuilt on the next run; the only cost is a slower first run.
- **the receipt PNG is copied to your system clipboard** — ONLY when you run `sipcode receipt`, never silently. via the OS's standard clipboard tool, locally.

## What sipcode never does without you running a command

touches nothing on disk. there is no daemon, no installed service, no startup item. `npm install -g @sipcode/cli` puts a binary on your path and that is it.
touches nothing on disk. there is no daemon, no installed service, no startup item. `npm install -g sipcode` puts a binary on your path and that is it.

## The asserted property

Expand All @@ -55,10 +60,10 @@ the guarantee covers **sipcode's own code paths**. it does not extend to third-p

## Future telemetry

when (if) hosted analytics ship in a future version, they will be:
if a cloud feature ever ships, it will be:

- **explicit opt-in** — via `sipcode link` or similar. never default-on.
- **quarantined** — all network IO will live in a separate `src/modules/cloud/` directory, clearly excluded from this privacy guarantee.
- **announced** — you'll see a clear notification on first install of the version that introduces it.
- **opt-in**: you turn it on yourself.
- **off by default**: nothing leaves your machine unless you do.
- **announced**: you will see a clear notice in the version that introduces it.

the privacy guard test is the gate. weakening it requires updating this document and shipping a major version. that is not security theater; that is a contract.
the privacy guard test is the gate: weakening it requires updating this document.
Loading
Loading