Privacy Policy
Last updated: 2026-07-27
I built still for myself — a single developer making a personal journal. This page explains honestly what I store, what I don't, who else touches your data, and how to delete everything if you want out.
What I store
The current database schema holds three kinds of rows scoped to your account:
- Journal entries — the words you write, stored as ciphertext. There is no readable-text column for entry content; it was removed, not left unused. What isn't encrypted is the structure around each entry: its kind (task, note, event), status, signifiers, tag, date, and time. So the shape of your journal is visible in the database even when the words aren't.
- Tags — the four canonical tag values (work, life, mind, or none) associated with entries.
- Account and session rows — your email address, authentication session tokens, and any personal-access tokens you create.
How the encryption works, and what it buys you
Every entry is encrypted under its own key. That key is then locked twice — once to a key only your browser can open, and once to a key my server holds. Which of those two locks exists is the entire design:
- Agent-visible entries — both locks. Your browser can read them and so can my server, which is what lets the paste importer and any agent you connect work at all.
- Private entries — your lock only. My server holds no key copy for them, so it cannot read one at any time, for anyone, on any request. They travel to your browser as ciphertext and are decrypted there. They are also encrypted there: a private entry is sealed by your browser before it is sent, so the words never arrive at my server in the first place. Writing one therefore needs your key on the device — which is why the composer waits for it rather than sending anything my server could read.
Searching your own journal happens on your device, over the whole thing. Your browser holds an encrypted copy, unlocks it locally, and matches there — which is the only way a search can cover private entries at all, since my server cannot read them. Nothing you type into the search box is sent anywhere.
What that actually protects against, stated without varnish:
- If the database leaks — a stolen connection string, a copied backup, a legal demand to my database host — what comes out is ciphertext for the entries themselves, private and agent-visible alike. That includes the bookkeeping rows that make a retried save safe to repeat: they used to keep a readable copy of what you had just written, and no longer do. The server's key lives in the application's environment, never in the database.
- It does not protect you from me, or from anyone who compromises the application itself. That process can read the server's key, and therefore every agent-visible entry. Private entries are sealed before they reach it — but the code that does the sealing is code I send your browser, so a compromised application could ship a build that keeps a copy. That is the floor of any encryption delivered over the web, and I would rather name it than let a padlock imply it away. I'm not going to dress the rest up either: "end-to-end encrypted" is a true description of the private zone and a false one of the agent-visible zone.
- Sharing an entry with your agent is sharing it with my server. There is no version of this where an agent can read your entry and I can't — which is exactly why it's a deliberate, per-entry choice rather than something that happens to you.
- Making an entry private later does not retract what was already exposed while it was agent-visible.
You choose, per entry. Every entry carries a small label saying who can read it — agents or only you — and that label is the control: tap it to move the entry between zones. Moving it re-encrypts it under a new key, so going private means the key my server held opens nothing from then on. What it can't do is reach backwards, and the app says so at the moment you make the move rather than in fine print here.
New entries start in whichever zone you pick on the Self page. The shipped default is agent-visible, because an app whose assistant can't see anything isn't the one most people came for — but private-by-default is one tap away, and nothing about the encryption is different for the people who choose it.
One more edge worth naming: if you've never completed key setup on a device, there is no lock of yours to use, so your entries are encrypted under the server's key alone. They behave exactly like agent-visible entries until you enrol.
What I don't store
I don't collect your IP address, User-Agent string, precise location, contacts, phone number, advertising identifiers, browsing history, biometric data, health data, or financial data. There are no third-party analytics SDKs, no trackers, and no advertising partners running in your browser at runtime — zero third-party network calls happen client-side when you use the app. The server does talk to a small set of sub-processors (listed below), but those are server-to-server calls on your behalf, not client-side tracking.
How sign-in works
still uses passwordless magic-link sign-in. When you enter your email and click "send link", I generate a one-time token and send it to your email address via Resend. You click the link in that email and you're signed in. No password is ever set, stored, or transmitted.
Your recovery code
Because sign-in is passwordless, there is no password for me to turn into an encryption key. So the first time you sign in, your device generates a key of its own and shows you a one-time recovery code. That code never reaches my server — I store only a copy of your key that the code can unlock, and I can't open it. It's what lets you sign in on a second device.
The bargain that comes with it, stated plainly: if you lose your recovery code and you're signed out of every device, nobody can get your entries back. Not you, not me, not a support request. That is the cost of my not being able to read them, and it's the honest trade — a "reset my encryption" button would mean I held a key all along.
That key now protects your entries themselves, not merely a copy of itself — which is what makes the bargain above a real cost rather than a theoretical one.
Who else touches your data
Four services help me run still. Here's what each one sees:
- Resend (email delivery) — receives your email address and the magic-link sign-in URL each time you request a sign-in. That's all Resend sees. resend.com/legal/privacy-policy
- Anthropic — two separate paths. When you use the paste import flow, the raw text you paste is sent to Anthropic's API to be parsed into structured entries; it's processed for that request only and is not retained for training. Separately, if you connect an agent from the Self page, that agent reads and writes your agent-visible entries on your behalf for as long as the connection stands. Private entries appear to it as entries that exist, with no content attached. anthropic.com/legal/privacy
- Neon (managed Postgres) — hosts the database where your account row, session rows, and entry rows live. Entry content is ciphertext there; Neon holds no key that opens it. neon.tech/privacy-policy
- Fly.io (application host) — runs the server that handles your requests and serves the web app. fly.io/legal/privacy-policy
No advertising partners. No analytics SDKs. No other services.
A candid promise
This page used to say your entries sat in the database as readable text, and that encrypting them was the next thing I'd build. That part is done — as of July 2026 the database holds no plaintext entry content at all, and the private zone is reachable from every entry.
What I won't claim is that this makes me irrelevant. I run the server, and I hold the key that opens every agent-visible entry — which, unless you move them, is most of them. Encryption moved the boundary; it didn't remove it. What changed is that the boundary is now yours to place, one entry at a time.
How to delete your account
You can delete your account at any time from the Self page — look for the "Delete account" section at the bottom. Confirming deletion permanently removes your account row and every entry, tag, and personal-access token attached to it. Deletion is immediate and irreversible. Per-row export is a future feature I plan to add; for now, copy anything you want to keep before you delete.
Effective: 2026-07-27