Privacy architecture
Terminalhire is local-first by architecture, not by policy promise. The design is verifiable in the public source.
What never leaves your machine
Everything that knows you. The CLI downloads a public job index and derives your skill profile from your public GitHub signal and, optionally, local telemetry you explicitly enable. The matcher, your profile, and your match results never leave your machine.
An automated test suite (the "zero-egress" scan) enforces that the code paths which touch your profile have no network calls — every allowed network touchpoint in the CLI is individually allowlisted and justified, and CI fails if anyone adds one.
What ever crosses the wire
Three things, each explicit:
- A consented lead. If you choose to share your profile with a recruiter or accept an intro, that specific, consented payload is sent — after a typed yes.
- Anonymous click analytics. Job links route through a redirect that counts clicks in aggregate. No profile data rides along.
- Opt-in connection features. Publishing to the developer directory, requesting intros, and chat are all double-opt-in. Chat is end-to-end encrypted (X25519 + XChaCha20-Poly1305) — the server stores ciphertext it cannot read.
- Opt-in click attribution. Off by default. If you turn on "Share job click activity" in the dashboard, and only while you are signed in, a job link you open is also recorded against your GitHub login so you can see your own recent clicks. Anyone signed out, or opted out, stays on the anonymous path above — nothing is attributed. Turning it back off deletes the history it collected, not just stops new rows.
- Anonymous install/init counters. Downloads of the install script and
completed
terminalhire initruns are counted as anonymous daily aggregates — a date, an optional campaign tag from the link you followed, and a count. The install-script download additionally records a coarse client kind (CLI pipe vs. browser view) — never the raw user-agent string. No account, IP address, or device information is stored or associated; the tag travels only in the URL and carries nothing about you. - The "Proof of Work" newsletter — double opt-in. If you sign up, we store your email address — and, only if you choose to add it after confirming, your GitHub username. Nothing else that identifies you (optionally a campaign tag from the link you followed — never an IP address, user-agent, or cookie). We send one confirmation email; you are only a subscriber once you click to confirm. The optional GitHub username is used only to pick issues that match your stack, never linked to your résumé or profile, and deleted with your email. If you add it, we also read your public GitHub following list so we can occasionally pick issues from maintainers you already follow ("From your orbit") — that list is used only to choose picks, never shown to anyone, and deleted with your email. An unconfirmed signup is auto-deleted after 7 days. Every issue carries a one-click unsubscribe that hard-deletes your email — not archived, not suppression-listed, deleted. Delivery is handled by our email processor (Resend); the list itself lives in our own database, disjoint from any profile or résumé data.
- "Check against my GitHub" on a project page — public data, nothing stored. On a public project page you can, while signed in, ask whether your work fits its open issues. The check is computed server-side from your public GitHub only — the same public proof-of-work signal that backs your résumé (which domains you have merged pull requests into), matched against that project's issues. It reads nothing from your local machine or profile — your local profile never reaches the server, here or anywhere. The result is computed, returned, and discarded: we write no record keyed to you and that project, and the answer is never shown to anyone but you. If your public credential can't be verified at that moment (GitHub is rate-limiting us, say), you get an honest "can't verify right now" — never a fabricated score.
- Contribution-dossier synthesis — envelope-derived facts only, off by default. The Contribution Dossier can optionally use an LLM (Anthropic) to phrase a few narrative sections and a résumé bullet from your merged work. What the model receives is only the identity-free dossier envelope and deterministic counts derived from it — pseudonym labels, enums, sizes, timestamps. No third-party free text is ever sent to the provider: not a comment body, not a review comment, not an issue description — nothing written by another person. Third-party maintainers appear to the model only as stable pseudonyms, never as a name, login, or email. Every generated sentence must cite the specific envelope fact that supports it, a second pass discards any sentence those facts don't back, and anything that slips through those checks is dropped — so the output can't say more than your structured record already proves. The feature is off unless explicitly enabled by the operator, and it runs only for a signed-in developer who has opted the dossier in; erasing your account or a maintainer's Article-17 request deletes the synthesized text alongside the record it was derived from.
- Founder notification emails — your own public address, nothing stored. If you post a bounty, we email you when a developer claims it, when a patch arrives, when the checks finish, and when work is waiting on your verdict. We send to the public email on your GitHub profile, read at the moment we send and not stored — there is no notification address on file to leak or to erase. No public email on your profile means no email, and nothing else changes. The emails carry no developer's name or identity: they say what happened and link to the row on your own dashboard, which grants nothing to anyone not already signed in as you. Delivery is handled by our email processor (Resend).
The surfaces inherit the rules
- The MCP server's match tools answer from the local cache with zero network calls. Claim preview uses governed public reads; claim record writes only the local ledger and cannot start, push, submit, or open a PR. If you configured an Anthropic API key, record applies the same semantic policy-doc reader as the CLI. Message content and consent actions remain excluded (details).
- The editor extension is a read-only renderer of the local cache with no network access at all (details).
- The spinner/statusline surfaces in Claude Code render content computed from a profile that never leaves your machine; supply comes from the public index, not from your data.
- The website counts page views with Vercel Web Analytics — cookieless and anonymous, aggregate numbers only. Your profile never touches the site, so there is nothing for a page view to be tied to.
The point
A credential you can trust has to be derived from real work and verifiable — and a matcher you can trust has to prove it isn't quietly a data business. Keeping the profile on your machine is what makes both claims checkable rather than promised.