1. What we use
“Cookies” here covers cookies and equivalent browser storage: localStorage, IndexedDB and the secure storage the mobile apps use. We use them in three categories, and only the first is strictly necessary:
- Strictly necessary: without these the Service does not work. Signing in, staying signed in, and holding a device credential.
- Preferences: remembering your theme choice and similar settings.
- Analytics: visit counting on this website, off unless you allow it, and never in the app you sign in to. See section 2.
We set no advertising cookies, and we do not share browsing data with ad networks.
2. On this website
| Key | Type | Purpose | Duration |
|---|---|---|---|
mailcycle.theme-preference | localStorage | Remembers whether you chose light or dark. Set only if you use the toggle. | Until cleared |
mailcycle.analytics-choice | localStorage | Remembers whether you allowed visit counting, so you are asked once. Holds the word "yes" or "no" and nothing else. | Until cleared |
That is the complete list. None of it is a cookie.
On the developer docs
The documentation at docs.mailcycle.email keeps these, and nothing else. It runs no visit counting.
| Key | Type | Purpose | Duration |
|---|---|---|---|
starlight-theme | localStorage | Remembers whether you chose light or dark. Set only if you use the theme picker. | Until cleared |
sl-sidebar-state | sessionStorage | Which sidebar sections are open and how far it is scrolled, so it stays put as you move between pages. | Until you close the tab |
Visit counting
We ask, once, whether we may count visits to this website with Cloudflare Web Analytics. It is off until you allow it, and the site works the same either way. You can change your mind by clearing mailcycle.analytics-choice from this site's storage, which makes us ask again.
If you allow it, each page you open sends Cloudflare:
- the address of the page and the page that linked you to it;
- your browser and operating system, the type of device and the screen size;
- the country your connection comes from, worked out from your IP address, which is not stored alongside the visit;
- how long the page took to load.
It sets no cookie, stores nothing on your device, and gives us no way to recognise you on a later visit or across other websites.
None of this runs on app.mailcycle.email, where you sign in. No analytics of any kind is loaded there, whatever you answer here.
Web fonts are served from this domain, not a third-party font CDN.
3. In the web app
| Key | Type | Purpose | Duration |
|---|---|---|---|
mailcycle.operator.session.wrapped | localStorage (necessary) | Keeps you signed in. Holds a session token, not your recovery phrase, encrypted under a key in mailcycle.keyring below. | 30 days, or until you sign out |
mailcycle.vault.seed.wrapped | localStorage (necessary, opt-in) | Your encryption key, stored only if you tick "Stay signed in on this device", and encrypted under a key in mailcycle.keyring below. Never sent to us. On phones this lives in the platform keystore instead, which is stronger than a browser. | Until you sign out |
mailcycle.keyring | IndexedDB (necessary) | The keys that encrypt the two entries above. Made in your browser, and the browser will not let them be read out, so a copy of either entry is useless on its own. Never sent to us. | Until you sign out |
mailcycle.worker.credential | localStorage (necessary) | The device credential on a browser Worker, so it survives a reload without pairing again. | Until revoked or cleared |
mailcycle.worker.pairing | localStorage (necessary) | A pairing in progress, so refreshing the page does not lose it. | Until pairing finishes or is cancelled |
mailcycle.worker.keys | localStorage (necessary) | On a browser Worker, the pairing token and the secret it uses to collect and open the keys for its addresses. Never sent to us. | Until the device is unpaired |
mailcycle.worker.drafts | localStorage (necessary) | Drafts written on a browser Worker, each sealed with the key of the address it is from. Nothing reaches us until the message is sent. | Until sent, discarded or the device is unpaired |
mailcycle.device.install | localStorage (necessary) | A random id for this browser, sent when it pairs as a device so that pairing it again replaces its old entry. We keep only a hash of it with your account id. | Until cleared |
mailcycle.app.lock | localStorage (preference) | Your idle sign-out setting. In the mobile apps it also holds biometric or passcode lock. | Until cleared |
mailcycle.app.lastActive | localStorage (necessary) | When you were last active, so idle sign-out can work. | Until cleared |
mailcycle.theme-preference | localStorage (preference) | Your theme choice. | Until cleared |
None of these are cookies, so none of them are sent to our servers automatically. None of them holds your recovery phrase in any form.
4. In the mobile apps
The iOS and Android apps do not use cookies. They store the session token, the Worker device credential, a paired device's key secret, the install id described above, a salted hash of your Mailcycle passcode if you set one with a count of wrong tries and, if you choose to stay signed in, your encryption key in the iOS Keychain or Android Keystore. The theme, the app lock settings, the last active time, a pairing in progress and a device's encrypted drafts go in ordinary app storage, under the same keys as the web app. On an Android phone preloaded by a partner, the partner's code is also kept in the Keystore, and when the app last tried to update itself in ordinary app storage. Deleting the app removes the ordinary app storage. On iOS, Keychain entries can outlast the app, so sign out first if that matters to you.
The apps contain no advertising SDKs and no third-party tracking SDKs. They do not use the advertising identifier.
5. The MCP server and the SDKs
mailcycle-mcp, which runs an AI agent, sets no cookies and stores nothing in a browser. It keeps one file on the machine it runs on, ~/.config/mailcycle/agent.json unless you choose another path, readable only by your user. It holds the agent's credential, its pairing token and the secret its address keys are sealed with. Deleting the file disconnects the agent from that machine; removing the agent in the app revokes it everywhere, and the MCP server deletes the file the next time it is refused.
It also uses one folder, ~/.config/mailcycle/files unless you choose others. An attachment the agent saves is written there decrypted, and the agent can attach only files from there. It never deletes anything in that folder, so what is saved stays until you remove it.
The SDKs (mailcycle-sdk for TypeScript, mailcycle for Python, mailcycle.email/go for Go, mailcycle for Rust, Mailcycle for Swift, mailcycle/mailcycle for PHP, email.mailcycle:mailcycle for Java, Mailcycle for .NET and mailcycle for Ruby) set no cookies and write nothing to disk at all. Each holds the recovery phrase or API key you pass it in memory for as long as your program runs, and where you keep those is your choice. Each decrypts on your machine, so the mail it opens exists in your program's memory and nowhere we can reach.
6. Controlling them
- Preferences can be cleared without affecting the Service. The app falls back to its defaults.
- Necessary storage cannot be declined while using the Service. Signing out removes your session and encryption key.
- Visit counting is off until you allow it. Clearing
mailcycle.analytics-choicemakes us ask again. - Your browser can block or clear all of them. Blocking site storage will prevent you from signing in.
7. Changes
If we add anything to browser storage, this page is updated before it ships. Questions go to hello@mailcycle.email.