Skip to content

Checked September 23, 2026

Where your data goes

Excellent runs on your machine. This page says what it stores, where it stores it, what leaves, and what changes when you turn on team sync.

Everything below was checked against the product source on September 23, 2026. Where we do not have an answer yet, it says so instead of guessing.

In short

Stays on your machine:
tasks, attempts, evidence, results and receipts, in ~/.excellent. We run no cloud that holds a copy.
Goes to your model provider:
what the run needs, from your machine, under your own account. We do not proxy it.
Comes to us:
nothing from a verification run. Only five actions you take by hand send us anything.
Not done yet:
no SOC 2 report, no third-party penetration test, no SSO.

Where it keeps things

WhatWhereNotes
Tasks, attempts, evidence, results and receiptsA data directory on your machine (~/.excellent by default)The main database. It leaves the machine only if you switch on sync, and then only to a server you run (see team sync below).
Evidence larger than 1 MiBContent-addressed files beside the databaseWritten to files rather than inlined into a record.
Sessions, sign-in credentials and the local event logA second database on your machineAlways local, never synced.
A copy in our cloudNoneWe do not run a cloud that holds a copy of any of it, and local use needs no Excellent account.

Encryption at rest

This one is more conditional than we would like, so here is the whole picture rather than the flattering half.

  • On a single-machine install built with the SQLCipher driver, the local database is encrypted at rest by default.
  • If you configure sync, the database is deliberately left unencrypted. The replica file has to stay readable by the sync engine, so at-rest protection on a sync-configured machine is your disk encryption — FileVault or the equivalent — not ours. Turning sync back off does not by itself re-encrypt the file.
  • The key is never stored in the database. Excellent resolves it in order: an environment variable, then your OS keychain (macOS Keychain, the Secret Service on Linux, DPAPI on Windows), then a file with 0600 permissions under the data directory. One key held in the keychain wraps the separate keys for the database, for credentials, and for the event log.
  • The Docker image used for self-hosting forces the file backend, because a server has no OS keychain. On that deployment the key sits on the same volume as the data — exclude it from snapshots.

Secrets and model keys

  • Provider API keys and OAuth tokens are sealed with AES-256-GCM before they are written to the database. The master key lives outside the database. A tampered value fails the authentication check and the read throws — there is no silent fall back to plaintext.
  • A key you paste into the app is sealed the same way, and only a “a key is present” flag is read back out. Excellent does not read a key out of a plaintext config file.
  • The credentials table is excluded from team exchange, so a sealed key never reaches a teammate. It is not excluded from single-owner sync: it lives in the main database, and that whole file is replicated to your own server when you switch sync on — so the sealed blobs go with it. The key that opens them is held separately and does not travel in that file.
  • You can also run with no key at all. Pointing Excellent at a coding CLI you already have uses that tool’s own authentication, and Excellent never sees a key.

What leaves your machine

To us, from a verification run: nothing. Your repository, the attempts, the evidence and the receipts are not sent to Excellent Software, LLC. The CLI makes no automatic call to Excellent: there is no licence check, no activation, no crash reporter and no update ping. Everything that does leave is in this table.

What leavesGoes toWhen
The context a run needs, when Excellent drives the modelThe model provider you chose, straight from your machine with your keyEvery run that calls a model. We do not proxy it, and Excellent refuses to send an unauthenticated request to a remote endpoint.
The context your own coding agent sendsThat agent's provider, under its own accountWhenever the agent calls it. Excellent is not in the path.
A bug reportUs, at excellent.soOnly when you run excellent bug, which prints the exact payload and asks you to confirm before posting it.
Your email, display name and handleUs, at excellent.so, where we record who is using the appOnly if you fill in the optional email field when creating an Excellent account. Leave it empty and nothing is sent.
Your recovery codes and email addressOur mailer, which sends the message and stores neitherOnly when you press the button that emails you a backup of them.
A request for the install scriptUs, at excellent.soOnly when you run excellent update.
A pairing code and the email you giveUs, to link this install to a consulting engagementOnly when you run excellent hire pair.
Your IP address and app versionOur update feedEvery launch of a packaged desktop app, without asking. There is no released desktop build yet, so this reaches nobody today.

Model calls take your context to your provider under your account, on that provider’s terms, and never to us. If you need to know exactly what is in a prompt, that is a question about your agent and your provider, not about Excellent.

The packaged desktop app is the one exception to “only what you ask for”. A packaged build arms an auto-updater at every launch: it queries the update feed on startup and downloads a new version in the background. That call is not consent-gated — being packaged is the whole condition. None of it reaches you today, because there is no released desktop build to download (see releases below). We are telling you now rather than when it lands.

Team sync (beta)

Team sync is off unless you turn it on. An unset or mistyped value behaves as solo, so it cannot switch on by accident.

  • It syncs to a server you provision and operate. Excellent does not host it, does not hold its credentials, and cannot read it. There is no Excellent-hosted alternative.
  • Devices authenticate by signing a single-use challenge with an Ed25519 key, checked against an allowlist on the server. The relay re-reads that allowlist whenever the file changes, so adding or removing a device takes effect without a restart — a removal drops the device’s key, its live session and its bearer tokens together. You edit that file by hand: there is no roster API for it, and no token-rotation path for the team relay. Being on the allowlist is necessary and not sufficient: a teammate joining an existing workspace has to do it from the command line, because the in-app switch takes a relay address but no workspace id.
  • The server speaks plain HTTP. TLS comes from a reverse proxy the provisioning recipe sets up when you give it a domain name. Without one, plain HTTP is safe only on a trusted LAN, over a VPN or SSH tunnel, or on loopback.
  • mTLS and certificate pinning are not implemented.
  • Verification records do not sync. The verification run table never crosses any sync boundary at all. Gate receipts and judgment receipts are excluded from team exchange — they travel only to your own server, on your own whole-database replica, and only if you have single-owner sync switched on. Do not plan on a teammate opening the evidence behind your result yet.
  • Machines doing the editing must be Apple Silicon Macs; the server can be Linux.

Receipts, and what they prove

  • A receipt binds the input, the checks, the evidence, the decision and the software version together. It does not prove that every external source was truthful.
  • Current receipts are signed with Ed25519, and excellent-mcp receipt verify <pack.json> --pubkey <key.pem> checks the payload hash and the signature against a public key you pin yourself. Receipts minted before that change used a shared-secret HMAC and are verify-only. The format, a zero-dependency verifier and a worked example are published at the receipt format.
  • Two limits worth knowing before you build a process on it. You have to obtain the signing key out of band — a receipt re-signed under an attacker’s key verifies perfectly well against that attacker’s key, so pinning is on you. And nothing is anchored to an outside target by default, so a receipt carries no independent proof of when it existed. Publishing a key and anchoring chain heads are both on the list below.

Releases and install integrity

  • CLI releases publish a SHA256SUMS file. The install script fetches it and refuses to install bytes it could not verify — a missing checksum file, a missing entry, no hashing tool on the machine, or a mismatch all exit non-zero. One documented environment variable is the deliberate opt-out.
  • That checksum file sits next to the artifact and is not itself signed. It protects against a corrupted download, not against someone who controls the bucket.
  • There is no released macOS desktop build, and the build that exists today is ad-hoc signed — not Developer-ID signed, not notarized, and its disk image is neither signed nor stapled. macOS rejects it: a Gatekeeper check on a quarantined copy blocks it outright as “damaged”. Notarization is wired into the build script and has never been run against a release. So there is no desktop release signature to verify, because there is no desktop release; the CLI checksum file above is the only install integrity we publish.

Telemetry

  • Off by default, and no collector is deployed to receive it.
  • If you turn it on, everything passes one strict allowlist: roughly seventeen named events whose values may only be a known token, a boolean, or a count. Error text, message bodies, titles, descriptions and stack traces are refused by name.
  • Source code, file paths and prompts are never included.

What we have not done

The useful half of a security page is the part that says no. As of September 23, 2026:

  • No SOC 2 report. A SOC 2 Type 2 audit is in progress: the budget is approved and the work has started. Nothing has been audited yet, no auditor has issued an opinion, and there is no report we can send you: today the commitment and this page are the whole of it. We are targeting the report by September 2027. That is a target for a report, not a date on which we become certified, and if it moves this line moves with it. Type 2 is the one enterprise buyers actually ask for, and it grades controls across a months-long observation window rather than on a single day — which is why the target is twelve months out rather than three.
  • No third-party penetration test. The product’s own posture statement records it as not yet done, and our security scorecard is self-measurement.
  • No published signing-key distribution and no external anchoring by default — see receipts above.
  • No hash-chained access log in an export. The internal event log is hash-chained and its heads are signed; the access history in an exported pack is metadata until that ships.
  • No shared verification evidence across a team — see team sync above.
  • No SSO, SCIM or audit-log export.
  • No status page — we do not run one yet, so there is nowhere to check whether a problem is ours or yours.

If a control you need is not named on this page, ask security@excellent.so rather than assuming it exists. We would rather answer the question than have you infer the answer.

Report a problem

Email security@excellent.so. Include the affected version, the command or route involved, and the smallest reproduction you can share.

Every security report is answered. We aim to acknowledge within three business days. There is no paid bounty program.

Excellent is local-first and trusts the operating-system user it runs as. Findings that need a second user on the same OS account, or physical access to the machine, are out of scope. A way to bypass the verification gate — for example spoofing an agent identity so work approves itself — is always in scope and treated as high severity.

Try it on your own repository

Everything above runs on your machine. Install it and check what it writes to ~/.excellent yourself.