overspill
Self-host it
The design constraint, not a policy page

Metrics, not conversations.

This page is written to be forwarded to whoever has to approve the tool. It says what is collected, what is not, where it is enforced, and what the enforcement does not cover.

01 Capture levels

Three levels. The default is the strictest.

The level is set per machine. Nothing above metadata happens unless someone deliberately turns it on.

Level Transmitted Never transmitted
metadata
default
Token counts by class, model id, request and message ids, timestamps, turn latency, stop reason, tool names, error flags, result sizes, durations, the project directory, git branch, Claude Code version and the machine hostname. Prompts, replies, file contents, shell commands, tool inputs, tool outputs, file paths inside tool arguments.
commands The above, plus redacted tool inputs — the arguments a tool was called with, after redaction. Prompts, replies, tool outputs.
full The above, plus prompt and response text, indexed for full-text search. Self-hosted only. The hosted service will never accept this level.
Verified, not asserted. A cold install was run end to end against a scratch database at the default level: 0 content rows, 0 full-text rows, 0 tool inputs, while token counts, model ids and tool names all survived. Then the agent was set to full against a server clamped to metadata — content stayed at 0 while the event count nearly doubled. The server-side guarantee holds against an agent sending more than it should.
02 Where it is enforced

Two places, on purpose.

The agent clamps the payload at the single function that owns the network socket, so no future code path can route around it. The server clamps again in the ingest endpoint, before the body is read.

Both call the same function. Two implementations of "what counts as content" would drift, and the day they drift the promise stops matching the guarantee.

The effective level is the lower of the two. Storing content therefore requires opting in at both ends — an agent alone cannot cause a server to keep more than the server allows, and a permissive server cannot cause an agent to send more than it was told to.

# what this machine is set to
$ overspill status
config    ~/.overspill/env
server    https://spend.acme.dev
token     set
capture   metadata (default)
hook      installed in ~/.claude/settings.json
          overspill sweep --quiet --detach
server    reachable — server stores at most: metadata

# raising it is explicit, and per machine
$ overspill capture commands

Raising the level above metadata also needs BODY_SIZE_LIMIT increased on the server — batches carrying text run to several megabytes and the default is 512KB. The server returns a 413 naming the variable rather than a confusing parse error.

03 Identity and erasure

A user is never an email address.

One row holds the address

Every record is keyed to an opaque person id. The email lives in exactly one row, in one table, and connectors resolve through it rather than writing addresses across the schema.

Erasure keeps the arithmetic honest

Honouring "delete me" clears one field in one row. The id survives, so historical aggregates stay correct — a year of spend does not silently change because somebody left.

Matching is deliberately conservative

Addresses are matched case-insensitively and trimmed, and nothing further. Stripping dots or +tags is provider-specific, and merging two genuinely different people is a far worse error than failing to merge one person's two addresses.

Hosts are machines, people are people

The hostname is recorded because a laptop and a build box are different things. It is not used as an identity, and a person moving machines does not fragment into two.

04 Isolation

One database per customer.

There is no tenant, org or account column anywhere in the schema, and there is not going to be one. Routing lives above the query layer; the queries never learn that more than one database exists.

This is the arrangement in which a query bug cannot leak across customers, because there is no query that could. Export or erasure for one customer is one file rather than a delete fanned across shared tables.

Self-hosting is simply the single-tenant case of the same design, which is what lets both editions share one storage layer instead of maintaining two.

The honest costs

Migrations run once per customer and need resumable orchestration. The hosted service needs connection and file management a single shared database would not. Both were accepted deliberately, and both sit above the queries rather than inside them.

Cross-customer benchmarks

If comparative benchmarks are ever offered, they come from a nightly job that emits bucketed aggregates into a separate small store — never from scanning anyone's raw events. Scanning every customer's data to compute a median would be slow and a privacy hazard; a job that can only ever emit aggregates is both the right shape and the right answer to give a security reviewer.

05 What this does not protect against

Stated plainly, because the omissions are the useful part.

The self-hosted dashboard has no authentication

None. It is designed to sit behind a reverse proxy, a VPN or a tailnet, and it must not be exposed to the public internet. The transcript view and full-text search are additionally hidden unless a server flag turns them on.

Encryption at rest protects a leaked copy, not a compromised host

Connector credentials — a vendor admin key can read your billing data — are encrypted with AES-256-GCM. On a single self-hosted box the key lives in the same environment as the database, so this defends against a leaked backup, a stray database copy, or a disk that leaves the building. It does not defend against someone who already has the machine, and claiming otherwise would be theatre.

Lowering the capture level is not retroactive

If a server stored content at full and is later clamped to metadata, the rows already written stay written. The merge behaviour that causes this is load-bearing for correctly assembling tool calls that arrive in two pieces, so it will not be "fixed" — purging old content needs a separate explicit operation, and it is better to say so than to let anyone assume a downgrade cleans up after itself.

One dashboard widget can show command text

At capture levels above metadata, the "what I do the most" panel summarises tool inputs, which can include shell commands and file paths. At the default level it detects that the detail is missing, says so, and falls back to a tool-name frequency count rather than silently rendering less.

Self-hosted builds never phone home

There is no licence check, no usage ping, no update beacon. The licence is enforced legally and socially, not technically — a licence check is telemetry, and telemetry in a product whose pitch is "we never see your code" would be self-defeating.

The vendor-operator plane is absent from the self-hosted codebase, not disabled by a flag. The source is readable, so a flag-gated superuser would be a documented backdoor one misconfiguration from live. The only answer that survives a procurement question is that the code is not there.

06 This website

No cookies. No trackers. No third-party requests.

overspill.dev sets no cookies and runs no analytics. Fonts are self-hosted rather than loaded from a CDN, because a page arguing that nothing should leave your machine has no business calling one on every visit. Every request this page makes goes to overspill.dev and nowhere else — the content security policy makes anything else impossible, and your browser's network tab will confirm it.

The only thing that could send anything anywhere is the "notify me" form, and only if you type an address into it and press the button.

Licence

Overspill is source-available, not open source, under PolyForm Small Business 1.0.0, used verbatim.

Free for personal use, and free commercially for companies under 100 people and under $1M in revenue. Above that it needs a licence. A named standard licence was chosen over a bespoke clause deliberately: a legal team approves PolyForm on sight and escalates a homebrew paragraph, and that delay is how a deployment dies.

Questions a page cannot answer: hello@overspill.dev.