DotEmber
.Ember
This Privacy Policy describes how .Ember (DotEmber) handles your information. It supplements — and does not replace — the NilToDev master Privacy Policy, which covers studio-level matters (the website, hosting, contact) common to every app we ship.
Plain-English summary. .Ember runs entirely on your Mac. We do not operate servers, do not collect telemetry, and do not see your journal entries, todos, calendar, or timer sessions unless you opt into one of the third-party integrations described below — and even then your data flows directly between your Mac and that service, never through us.
Overview
.Ember is a local-first productivity desktop app for macOS. We do not run servers and we do not collect, store, or sell your personal data. Your journal entries, todos, calendar blocks, and timer sessions live as Markdown files in a folder you choose on your own Mac. .Ember never sees those files unless you opt in to one of the integrations described below.
This policy describes (1) what stays on your device by default, (2) the optional integrations you can enable, and (3) the third-party services those integrations use.
What stays on your device
By default, .Ember stores everything locally:
- Vault content — Journal entries, todos, calendar blocks, notebook
organization. Stored as Markdown files in a folder you pick during
onboarding (default suggestion:
~/Documents/DotEmber). - App database — A small SQLite database
(
{userData}/dotember.sqlite) caches search indexes, timer sessions, and RSS articles (when News is used). This is an accelerator for the local files; the Markdown files are the source of truth. - Settings — Theme, accent color, language, week-start day, AI
master toggle, and similar UI preferences. Stored in
localStorageand{userData}/settings.json. - AI keys — API keys you paste in the Settings → AI tab are
encrypted via Apple’s
safeStorage(Keychain) and stored in{userData}/ai-secrets.enc. They never appear inlocalStorage, never leave your Mac except in direct calls to the provider you chose, and are never transmitted to us. - OAuth tokens — Google refresh tokens are encrypted via
safeStorage(Keychain) and stored per-account at{userData}/google-accounts/{accountId}.enc. Same scope as AI keys: never inlocalStorage, never transmitted to us.
We do not transmit any of this to a .Ember server. There is no .Ember server.
Optional integrations
Each integration is off by default and can be turned off again at any time from Settings. When you enable one, your data flows directly between your Mac and the third-party service — never through .Ember.
iCloud Sync (Apple CloudKit)
When enabled in Settings → Sync, .Ember uses Apple CloudKit to sync
your vault between your Macs. Records are stored in your private
CloudKit database under container iCloud.com.dotember.app — only
your iCloud account can read them. Apple’s standard iCloud privacy
applies. Disabling sync does not delete the data already on iCloud —
use Settings → iCloud (system) to remove app data from your iCloud
account.
Google Calendar + Tasks
When connected in Settings → Calendar, .Ember reads upcoming events
from calendars you select via Google’s Calendar REST API and task
lists you select via Google’s Tasks REST API. Scopes requested
(all in the Sensitive tier — .Ember never requests Restricted
scopes such as https://www.googleapis.com/auth/calendar):
https://www.googleapis.com/auth/calendar.events— read and write events on calendars the user has selected.https://www.googleapis.com/auth/calendar.readonly— enumerate the calendar list and derive the connected account’s primary email for display in the Settings → Calendar account row.https://www.googleapis.com/auth/tasks— read and write tasks on task lists the user has selected.
Multiple Google accounts are supported; each account’s refresh token
is stored encrypted on your Mac at
{userData}/google-accounts/{accountId}.enc. Events and task lists
are cached in the local SQLite. .Ember writes to your Google
Calendar or Google Tasks only when you create, edit, complete, or
delete an event or task from inside .Ember — every write
originates from a deliberate user action; there is no background sync
that pushes local changes you didn’t make. Disconnecting an account
(Settings → Calendar → Remove on the account row) revokes the local
token, deletes the encrypted file, and removes that account’s cached
events and tasks.
Apple Calendar (EventKit)
When connected in Settings → Calendar, .Ember reads from and writes
to your local Apple Calendar via macOS’s EventKit framework. macOS
prompts you for full Calendar access (TCC permission
personal-information.calendars); you can revoke it at any time in
System Settings → Privacy & Security → Calendars. All Apple Calendar
data stays on your device — EventKit is process-local; nothing is
transmitted off your Mac via this integration. .Ember writes to your
Apple Calendar only when you create, edit, or delete an event from
inside .Ember. Events are cached in the local SQLite for the same
selectable-calendar UX as the Google integration. Removing the Apple
account row in Settings clears the cached events; revoking
system-level Calendar access additionally blocks future reads/writes.
RSS / News feeds
Feeds you add in /news are fetched directly by your Mac from each
publisher’s URL on a 30-minute schedule. .Ember does not proxy or log
these requests. Article content is cached locally for the reader view.
BYOK AI (Claude / Gemini / OpenAI)
When AI is enabled (Settings → AI → master switch) and a provider key is configured, AI features (Auto-arrange Inbox, Daily Brief, palette commands) call the provider’s API directly from your Mac. The relevant data sent depends on the feature:
- Auto-arrange Inbox — Inbox todo titles, your block names, and the last 14 days of completed/scheduled todo titles + block + start time.
- Daily Brief — RSS article titles + sources + publication dates from your subscribed feeds, plus the titles of articles you have saved to your journal in the last 30 days.
- Palette commands — Whatever text you type into the command palette as an AI command.
Each provider has its own data-handling policy:
- Anthropic (Claude) — anthropic.com/privacy
- Google (Gemini) — policies.google.com/privacy
- OpenAI — openai.com/privacy
Disabling AI (master toggle off) immediately stops all outbound AI calls and hides every AI surface in the app.
Google API Services User Data Policy compliance
.Ember’s use and transfer of raw or derived user data received
from Google Workspace APIs will adhere to the
Google API Services User Data Policy,
including the Limited Use requirements (and the equivalent
Workspace API user data developer policy).
Specifically, for the Google Calendar (calendar.events,
calendar.readonly) and Google Tasks (tasks) scopes that .Ember
requests:
- Limited use. Data received from Google APIs is used only to
provide or improve the user-facing features that the user requested
— rendering events and tasks on the Todo Calendar grid; creating,
editing, completing, and deleting events and tasks the user
authored inside
.Ember; surfacing per-calendar visibility and color in Settings → Calendar; resolving conflicts when the same event was edited on both sides between syncs. - No transfer.
.Emberdoes not transfer Google user data to third parties, except as necessary to provide or improve the user-facing features (which currently is no such transfer at all — every API request originates from the user’s Mac and hits Google’s endpoints directly), or for security purposes (e.g., investigating abuse), or to comply with applicable laws. - No advertising.
.Emberdoes not use Google user data — including any inferences derived from it — to serve advertisements, including retargeted, personalized, or interest-based advertising. - No human reading.
.Emberdoes not allow humans to read Google user data, except (a) with the user’s explicit consent for specific data, (b) as necessary for security purposes such as investigating abuse, (c) to comply with applicable laws, or (d) for internal operations on data that is aggregated and anonymized, and only in compliance with the Google API Services User Data Policy. As of theLast updateddate above,.Emberoperates no servers, employs no support staff with access to user accounts, and performs no aggregated or anonymized processing on Google user data — so no Google user data is read by any human on the.Emberside. - No AI/ML training, no transfer for training purposes.
.Emberdoes not use Google user data — raw, aggregated, anonymized, or derived — to develop, train, or improve any generalized or foundational machine-learning or artificial-intelligence model, and does not transfer Google user data to any third party for such training purposes..Ember’s BYOK AI features (Auto-arrange Inbox, Daily Brief, command palette actions) are described in the “BYOK AI” subsection above; in version 1.0.0 those features operate on local app data (Inbox todo titles, block names, RSS article titles + saved-article titles, and text the user types into the palette) and do not include Google Calendar events or Google Tasks data in the AI request body. Should a future release route Google user data into an AI feature, it would do so only as a user-facing feature for that individual user under Limited Use — never for training a generalized model and never via any provider that re-trains on API-tier inputs.
We will continue to adhere to these restrictions as the product evolves; any future change that would alter the Limited Use posture (e.g., introducing a server-side feature that handles Google data, or routing Google user data through an AI feature) will trigger a privacy policy update and a fresh Google OAuth verification before shipping.
Data protection mechanisms
Sensitive data that .Ember handles locally — Google OAuth refresh
tokens, BYOK AI API keys, and StoreKit purchase receipts — is
protected by the following mechanisms:
- Encryption at rest. Google refresh tokens and AI API keys are
encrypted using Apple’s
safeStorageAPI, which routes through the macOS Keychain Services framework. The encrypted blobs at{userData}/google-accounts/{accountId}.encand{userData}/ai-secrets.enccannot be decrypted by any process outside.Ember’s signed app binary running under the same macOS user account. The encryption key is managed by macOS and never leaves the device. - Encryption in transit. All network requests
.Embermakes to Google APIs (https://oauth2.googleapis.com,https://www.googleapis.com,https://tasks.googleapis.com) use HTTPS with TLS 1.2 or newer enforced by the macOS networking stack (URLSession). Plaintext fallback is impossible —NSAppTransportSecurityin.Ember’sInfo.plistblocks any cleartext HTTP connection by default and.Emberdeclares no exceptions. - Access control. Encrypted credential blobs are sandbox-scoped
to the
.Emberapp bundle (App Sandbox entitlementcom.apple.security.app-sandbox = true) — no other application on the user’s Mac can read them. The sandbox is enforced by the macOS kernel; circumvention would require user-level privilege escalation, which is outside.Ember’s threat model and is itself a violation of Apple’s platform policies. - No copies.
.Emberdoes not maintain unencrypted copies of these credentials anywhere — not inlocalStorage, not inUserDefaults, not in log files, not in crash reports. Refresh tokens are decrypted into memory only for the duration of a single token-refresh REST call and are released immediately after the call completes. - Token revocation paths. Disconnecting a Google account
(Settings → Calendar → Remove on the account row) deletes the
encrypted token file and removes the account’s cached events and
tasks from the local database. Users can additionally revoke the
OAuth grant directly with Google at
myaccount.google.com/permissions;
.Embertreats subsequent 401 responses as a revoked grant and re-runs the consent flow. - No transmission to NilToDev. None of these credentials, tokens, or any data fetched using them is ever transmitted to a NilToDev server — there is no NilToDev server. The encrypted blobs leave the user’s Mac only via the user’s own iCloud Drive backup of Application Support data if the user has enabled that backup, in which case Apple’s standard iCloud encryption applies (see Apple’s iCloud security overview).
Analytics, tracking, advertising
None. .Ember does not include analytics SDKs, crash-reporting services that link to user identity, advertising trackers, or any other phone-home telemetry. The app makes zero outbound network requests on a clean install with no integrations enabled.
Purchases (Apple App Store)
.Ember 1.0.0 ships with a Free Trial followed by a one-time in-app purchase to continue use beyond the trial period. Purchase processing is handled by Apple — NilToDev does not receive your credit-card number, billing address, or any other payment instrument data; the App Store EULA governs that relationship.
What .Ember handles locally for license validation:
- StoreKit 2 transaction record. When you purchase, Apple’s StoreKit framework returns a verified transaction object containing an anonymous transaction ID, the product ID, the purchase date, and the current transaction status (purchased / refunded / revoked). .Ember stores this verified record locally so the app knows whether to show paid features.
- Trial start date. When the Free Trial begins, .Ember writes the
start timestamp to local app storage (
localStorageand/or{userData}/license.json) so the trial countdown can run without contacting an external server.
What .Ember does not handle:
- Your Apple ID email, name, or any other personal Apple-account detail (StoreKit’s verified transaction does not expose these).
- Any payment instrument (card number, last 4 digits, billing zip, etc.).
- Any per-user purchase history beyond your own most recent transaction record.
Refund handling is described in the .Ember Terms of Use §9 — refunds are processed by Apple at reportaproblem.apple.com; NilToDev cannot directly issue refunds.
Sale and sharing of personal information
We do not sell or share your personal information in any sense — including the senses contemplated by the California Consumer Privacy Act / California Privacy Rights Act (CCPA/CPRA), the Colorado Privacy Act, or any comparable framework. We do not engage in cross-context behavioral advertising. We do not have a Data Use Choices opt-out mechanism because there is nothing to opt out of.
Accounts, GDPR, CCPA
.Ember has no user account system — no signup, no login, no .Ember-issued user ID. Because we do not collect, store, or process any personal data on our side (with the narrow exceptions documented in “Purchases” above and “Contact” below), data-subject rights under GDPR / UK GDPR / CCPA / Korean PIPA generally have no NilToDev-side data to act upon. Where rights apply to data held by third-party services you opt into (Apple iCloud, Google, Anthropic, OpenAI), exercise them directly with that third party under their own privacy policies.
For completeness, the framework-by-framework rights summary:
| Framework | Rights | How to exercise against NilToDev |
|---|---|---|
| GDPR / UK GDPR (Art. 15-22) | Access, rectification, erasure, restriction of processing, portability, objection, withdrawal of consent, lodging a complaint with a supervisory authority | Email [email protected]. We respond within 30 days. Most rights have no NilToDev-side data to act on (we hold none); we’ll confirm that in writing. |
| CCPA / CPRA | Know, delete, correct, opt out of sale/sharing, limit use of sensitive personal info, non-discrimination | Email [email protected]. We do not sell or share, so the opt-out is moot. Most other rights have no NilToDev-side data to act on. |
| Korean PIPA (Art. 35-37) | Access, rectification, deletion, suspension of processing | See the dedicated KR PIPA section in the Korean version of this addendum for the full disclosures and procedure. |
For the studio-level position on these regimes (Cloudflare Analytics, hosting, contact handling), see the NilToDev master Privacy Policy.
Children
.Ember is not directed at children under 16 (GDPR threshold) or under 13 (COPPA threshold) and we do not knowingly collect data from such children. Age rating: 4+ (App Store).
Data deletion
.Ember writes user data only to (a) your vault folder, (b) the macOS Application Support directory, and (c) — if iCloud Sync is enabled — your private CloudKit database. There is no .Ember-side database to issue an erasure request against.
Inside the vault, deletes are deferred — not immediate. When you
delete a journal entry, todo, notebook, block, or when sync removes a
file that has disappeared upstream, the file is moved to
{vault}/_trash/ and kept there for 30 days before being hard-removed
by the next cleanup pass. This is a local recovery window — _trash/
lives only in your vault folder, is never synced to iCloud or any
other sync target, and is never read by any feature except the trash
recovery UI in Settings → Trash. To empty it on demand, use Settings →
Trash → Empty trash.
To remove every trace of .Ember from your Mac:
- Quit the app.
- Delete the vault folder (default
~/Documents/DotEmber, or wherever you pointed it). This includes_trash/since it lives inside the vault. - Delete
~/Library/Application Support/DotEmber/(contains the SQLite cache, AI keychain blob, OAuth token blobs undergoogle-accounts/, settings). - Delete the app from
/Applications/.
To remove iCloud-synced data, also visit System Settings → Apple ID → iCloud → Manage → .Ember → Delete.
To revoke OAuth access to your Google account, visit myaccount.google.com/permissions.
Changes to this policy
Material changes will be noted in the in-app changelog and in the
Last updated line at the top of this document. The version-controlled
source of this addendum lives at docs/privacy/privacy-policy.en.md in
the .Ember repository; the canonical published copy is this page on
niltodev.com.
Contact
Questions: [email protected]
This addendum reflects .Ember 1.0.0 and supersedes any prior version. For studio-level matters not covered here, refer to the NilToDev master Privacy Policy.