Privacy
Tetris runs locally. The compression pipeline never touches the network. The one thing that does leave your machine is a small heartbeat — exactly what’s in it is documented below, and the code that sends it is linked so you can read it yourself.
What never leaves your machine
- Your code. File contents, diffs, edits, scratch buffers — none of it.
- Your prompts. Nothing you type to the assistant is uploaded anywhere.
- Tool-call payloads. The thing tetris compresses. Processed in-memory; never written to disk except your own ledger; never transmitted.
- Tool names, file paths, filenames, repo names. Tetris doesn’t log them server-side. The ledger on your disk records compression stats, not identifiers.
- Hostname, username, IP. The heartbeat does not include any of these. Source IP is visible to our edge (Cloudflare) for standard request routing and dropped after that; it’s never joined to your install record.
What the heartbeat contains
Exactly these fields, and nothing else:
| Field | Value | Why |
|---|---|---|
install_id |
Random UUID generated once at first run, stored in ~/.tetris/install_id. |
Counts unique installs. Not tied to your identity. |
machine_id_hash |
SHA-256 of a salted, OS-provided machine UID. One-way; never reversible. | Enforces the license device count without knowing which machine you’re on. |
binary_version |
e.g. 0.0.23 |
So we know which versions are in the field when we ship fixes. |
platform |
Target triple, e.g. aarch64-apple-darwin. |
OS + architecture only. Five possible values. |
compression_count (optional) |
Lifetime count of compressions from your local ledger. | So the community stats page has a real denominator. |
tokens_saved_mtd (optional) |
Tokens saved this month, from your local ledger. | License gate: the free plan caps savings, Pro lifts the cap. |
active_assistants (optional) |
Array of assistant names wired on this install, e.g. ["claude", "codex"]. |
So we know which assistants to prioritize for fixes. |
strategies_used (optional) |
Array of pipeline-stage names that ran since the last beat. | So we know which compression stages earn their keep. |
That’s the whole payload. No file content, no prompt text, no tool names, no diffs, no filenames, no repo paths, no hostname, no username.
When the heartbeat fires
- First run: once, at the end of
tetris onboard. Marks the install as active. - Steady state: rate-limited to once every six hours. The next tool call after the window elapses triggers it in a detached background task; the hook itself doesn’t wait.
- License refresh:
tetris logincontacts the license server to validate or refresh your JWT. Same payload shape.
That’s it. No per-compression callback, no continuous stream, no analytics SDK.
What we do server-side
Heartbeats land in a Supabase table keyed by install_id. We aggregate counts per day
into community_stats_cache (total installs, tokens saved, rough active-assistant mix)
which is what the numbers on the landing page read from. The raw heartbeat rows are retained
for 90 days for debugging and then deleted.
We do not sell this data. We do not share it with ad networks. We do not have an ad network.
Source-code receipts
If any of the above is vague, read the code. The relevant files:
crates/tetris-core/src/license/heartbeat.rs— the full payload struct, the HTTP client, and the 10-second timeout.crates/tetris-cli/src/cmd/compress.rs— where the rate-limited heartbeat is fired on the hook path (in a detachedtokio::spawn, not awaited).crates/tetris-cli/src/cmd/onboard.rs— the one-shot first-run beacon.infra/supabase/functions/heartbeat/index.ts— the server-side endpoint. Rejects anything it doesn’t recognise.crates/tetris-core/src/compress/— the compression pipeline. No network I/O in here by construction.
Running fully offline
Compression works with the network unplugged. The license has a 72-hour offline grace
— after that, compression pauses (tool calls are passed through unchanged) until the heartbeat
reaches the server again. Enterprise customers on the air-gap plan get a self-hostable license
server; point TETRIS_API_URL at it and no request ever leaves your network.
Opting out of telemetry
Set TETRIS_TELEMETRY=0 in your shell environment before running any tetris command.
Heartbeats stop firing; the license check still needs to reach the server to validate but
sends only the minimum install_id + machine_id_hash + version.
Deleting your data
Run tetris uninstall, then rm -rf ~/.tetris/. That removes your
install_id locally. The heartbeat stops arriving; the install row is marked
inactive after 30 days and aged out of aggregates. There’s no other identifier tying a
row to you — we never knew who you were.
If you want us to hard-delete a specific install_id immediately, email
privacy@tetris.codes with the ID (you can read it from
~/.tetris/install_id) and we’ll run the deletion within 30 days of receipt.
Questions
Privacy questions: privacy@tetris.codes. General support: help@tetris.codes. If you find something in the code that contradicts anything on this page, that’s a bug — tell us and we’ll fix the code or fix the page.