Privacy Policy
Effective date: 2026-06-24
This policy explains what data CommandLatch collects, why, the legal basis for
it, how long it is kept, who it is shared with, and the rights you have over it.
It covers all CommandLatch surfaces: the web dashboard (app.commandlatch.app),
the iOS app, the macOS menu-bar app and CLI, the marketing site
(commandlatch.app), and this documentation site (commandlatch.dev). Read it
alongside the Security & trust model.
1. Who is responsible for your data (controller / Imprint)
Section titled “1. Who is responsible for your data (controller / Imprint)”The data controller responsible for processing under the GDPR is:
Adrian Filipow Tannenwaldweg 100B 61350 Bad Homburg Germany
Adrian Filipow operates CommandLatch as an individual sole operator (a natural person, not a registered company; this also serves as the Imprint per § 5 DDG).
- Privacy / data-protection contact:
privacy@commandlatch.app - Support:
support@commandlatch.app - Imprint fallback contact:
adrianfilipow@outlook.de
There is no statutory obligation to appoint a Data Protection Officer for an operation of this size, so none has been appointed; the contact above handles all privacy matters directly.
Governing law. This policy and all processing are governed by the law of Germany and the European Union — in particular the General Data Protection Regulation (GDPR) and German consumer-protection law (including the right of withdrawal, Widerrufsrecht).
2. What data we collect, why, and on what basis
Section titled “2. What data we collect, why, and on what basis”The table below is the authoritative inventory of every category of personal data CommandLatch processes. The App Store data type column maps each category to the data-type names used in the iOS App Store privacy labels, so this table and those labels describe exactly the same categories. All categories are linked to your identity and none is used for tracking (no cross-app or cross-site tracking, no advertising identifiers).
| Category | What it is | Purpose | Legal basis | Retention | Recipients | App Store data type |
|---|---|---|---|---|---|---|
| Account email address | you@example.com — the address used to sign in (passwordless 8-digit one-time code; there is no password) | Account creation and passwordless sign-in; device ownership; transactional/support correspondence | Performance of a contract (Art. 6(1)(b) GDPR) — required to provide the account/service | Until you delete your account (deletion currently by request; self-serve delete planned) | Supabase (Auth/DB, EU), Resend (delivers the sign-in code emails) | Email Address |
| Supabase user id (account identifier) | A UUID like 3f2a… that uniquely identifies the account; used as owner_id on devices/commands and as the PostHog distinct_id on identified surfaces | Internal account identification; scoping all data to the owner under Row-Level Security; joining analytics to one person across web/iOS/server | Performance of a contract (Art. 6(1)(b) GDPR); analytics linkage under legitimate interest (Art. 6(1)(f)) | Until account deletion | Supabase (EU), PostHog (EU) on identified surfaces only | User ID |
| Paired device metadata | Per Mac: agent-reported hostname (devices.name), optional user-chosen display_name, platform (macos/ios/watchos), app_version, last_seen_at, live status JSON (e.g. keep-awake / pending-lock), remote_enabled flag | Let you see and target your own machines; show agent health and connection status; device rename | Performance of a contract (Art. 6(1)(b) GDPR) | Until the device is removed or the account is deleted | Supabase (EU) | — |
| Hashed device token | SHA-256 hash (token_hash) of the per-device credential the agent/CLI use to authorize one Mac; the plaintext token lives only on your Mac (pairing.json / ~/.commandlatch) | Authorize a specific paired Mac to fetch/run commands and heartbeat | Performance of a contract (Art. 6(1)(b) GDPR); security of processing (Art. 32) | Until the device is unpaired/removed or the account is deleted; stored hashed, never plaintext, in the backend | Supabase (EU) | — |
| Pairing codes (short-lived) | A short 6-digit setup code plus a hashed claim token, used once to link a Mac to the account during pairing | Securely associate a newly installed agent with your account | Performance of a contract (Art. 6(1)(b) GDPR) | Ephemeral — expire ~10 minutes after creation; cleared on claim | Supabase (EU) | — |
| Command history (action + source) | Per command: action (lock, sleep, lock_sleep, keep_awake_start/stop, mute_toggle, volume_up/down, media_play_pause, send_notification, cancel_pending_lock, alert), trigger/source (web, ios, siri, cli, shortcut, webhook), status/result, timestamps, error text. Most actions carry no content payload | Powers the activity log; lets the agent run and de-duplicate commands (replay protection) | Performance of a contract (Art. 6(1)(b) GDPR) | Tied to the device — removed when the device is removed or the account is deleted (command rows expire ~1 minute after enqueue for delivery, but the history row persists with the device) | Supabase (EU); action+source (never content) also captured server-side to PostHog (EU) as command_enqueued | Product Interaction |
| Notification/alert command content (your typed title and body) | When you send a send_notification or alert command, the title and body text you typed is stored in the command payload / notifications table (title required, body optional) so the agent or APNs can display it | Deliver your own notification/alert text to your Mac or iPhone | Performance of a contract (Art. 6(1)(b) GDPR) — you supply this content to be delivered | With the command/notification row — removed when the device is removed or the account is deleted | Supabase (EU); for alerts, Apple APNs delivers the text to the iPhone | Other User Content |
| Hashed shortcut & webhook tokens | Per-shortcut and per-webhook credentials stored as SHA-256 hashes (token_hash), each scoped to one device + one action, with an optional fixed payload and rate limit | Let Siri Shortcuts and inbound webhooks fire a specific command without your session | Performance of a contract (Art. 6(1)(b) GDPR); security of processing (Art. 32) | Until you delete the shortcut/webhook or delete the account; stored hashed | Supabase (EU) | — |
| APNs push token (iOS) | Your iPhone’s APNs device token (lowercase hex) plus its environment (sandbox/production), owner_id, device_id, refreshed-at timestamp. It is the phone’s public push address, not a secret | Deliver the alert action as a push notification to your own iPhone | Performance of a contract (Art. 6(1)(b) GDPR) | Until the app unregisters/re-registers (stale tokens are prunable) or the account is deleted | Supabase (EU), Apple APNs | Device ID |
| Billing data (Stripe) | Stripe customer id, subscription id, subscription status, price id, current period end, cancel-at-period-end flag (stored in our DB); the account email, payment method/card details, and invoices are held by Stripe | Process and manage the CommandLatch Pro subscription (web/macOS); enforce entitlement | Performance of a contract (Art. 6(1)(b) GDPR); legal obligation for invoicing/tax records (Art. 6(1)(c)) | Subscription state retained while the account exists; Stripe retains payment/invoice records per its own legal retention obligations | Stripe (US, SCCs), Supabase (EU) | Purchase History |
| In-app purchase data (Apple, iOS — planned) | When the iOS StoreKit IAP for Pro ships: Apple-side subscription/transaction status surfaced via App Store Server Notifications, reconciled into the same subscriptions/entitlement. Apple handles the actual payment and the App Store account | Sell and honor the Pro subscription inside the iOS app; unify entitlement with web/Stripe | Performance of a contract (Art. 6(1)(b) GDPR) | Subscription/entitlement state while the account exists; Apple retains purchase records per its own policies | Apple (App Store / IAP), Supabase (EU) | Purchase History |
| Support tickets | Subject and message text you type, a coarse category (bug/billing/feature/account/other), an optional reply-to email (defaults to the account email), captured app_version + platform, and (desktop only) an optional already-redacted diagnostics bundle. A submitter name, if collected by the form, rides in the message/email, not a dedicated field | Receive, route, and respond to support requests | Performance of a contract / pre-contractual steps (Art. 6(1)(b)); legitimate interest in providing support (Art. 6(1)(f)) | Deleted within 12 months after the ticket is resolved, unless still needed to establish, exercise, or defend a legal claim, or earlier when you delete your account | Supabase (EU), Resend (emails the ticket to the support inbox) | Other User Content |
| Product analytics events | Coarse usage: page views (site/docs/web), signed_in, device_paired, command_enqueued (action + source, never content), keep-awake sessions, billing lifecycle (trial_started/subscription_started/canceled/payment_failed), support_ticket_submitted, settings_changed, app_started/app_opened. Email is never sent as an event property (only as an identify person prop on identified surfaces) | Understand product/website usage and where to improve; measure activation, engagement, retention, and billing funnels | Legitimate interest (Art. 6(1)(f) GDPR) — minimized, EU-hosted, GeoIP disabled, honors GPC/DNT; desktop is anonymous and opt-out | Retained for up to 12 months in PostHog’s EU cloud, then rolled off; anonymous on desktop/site/docs, identified on web/iOS/server | PostHog (EU) | Product Interaction |
| Technical environment (app / OS / hardware version) | app_version, OS version, CPU architecture/type — sent as base properties on analytics events; app_version is also stored per device and per support ticket | Compatibility/health monitoring, debugging, and platform-mix analytics | Legitimate interest (Art. 6(1)(f) GDPR) | With the analytics event / device / support ticket it accompanies | PostHog (EU), Supabase (EU) | — |
Where we rely on legitimate interest (Art. 6(1)(f)) — for analytics linkage, product analytics, technical environment, and providing support — our interest is in running, securing, and improving CommandLatch. We keep that processing minimized, EU-hosted, and free of location and advertising identifiers, and you can object to it (see §8). On the macOS app, analytics is additionally opt-out.
3. What’s stored on your Mac
Section titled “3. What’s stored on your Mac”The menu-bar app keeps a small amount of local state, stored privately under your
user account in ~/Library/Application Support/com.commandlatch.desktop/ and
~/.commandlatch/ (the optional CLI config).
This includes the pairing record (how the app authenticates to the backend; it holds the device token in plaintext locally — the backend only ever stores the hash), a local activity log of recent actions, your preferences (including the analytics on/off switch and a random per-install analytics id), and the CLI config if you installed the command-line tool. See the security model §5 for notes on how the device token is stored locally.
The diagnostics export (menu-bar Diagnostics) produces a redacted file for attaching to a support request. It includes your app version, OS, system checks, and recent activity — but never your device token or keys, and URLs are reduced to host-only. It is created only when you ask for it and is never uploaded automatically.
4. Where your data is hosted and our sub-processors
Section titled “4. Where your data is hosted and our sub-processors”CommandLatch’s backend runs on Supabase (a hosted Postgres database with Row-Level Security, passwordless Auth, and Deno Edge Functions), with EU data residency. Everything in §2 is scoped to your account and protected by Row-Level Security — no other user can read it (see the security model §4–5).
We use a small set of sub-processors to operate the service. The full, authoritative list — with each one’s purpose, the data categories it handles, its processing location, and the transfer safeguard — is maintained on a dedicated page:
In summary: Supabase (backend, EU) and PostHog (analytics, EU) keep data in the European Union; Stripe (payments), Resend (transactional email), Vercel (web hosting), and GitHub Actions (CI/CD — no end-user data) are US providers operating under EU Standard Contractual Clauses; and Apple handles APNs push delivery and App Store / in-app-purchase billing.
5. Analytics
Section titled “5. Analytics”CommandLatch collects minimized usage analytics to understand how the product
is used and where to improve it, via PostHog on
EU-hosted infrastructure (EU cloud, host https://eu.i.posthog.com).
- Identity by surface. The web dashboard and iOS app are identified
— the
distinct_idis your Supabase user id, and your email is attached only as a person property viaidentify()/$set. Our edge functions record canonical server-side events keyed to the owner’s Supabase user id. The macOS app sends fully anonymous events keyed to a random per-install UUID (analytics_id, never the account or device id) and is opt-out via Settings → Privacy. The marketing site and docs are anonymous (PostHog anonymous id). - No location. Every event carries
$geoip_disable: true, so no location is derived from your IP address. - We honor your browser signals. On the web dashboard, marketing site, and docs we honor Global Privacy Control and Do Not Track — PostHog never initialises when either is set, so those surfaces then send nothing.
- No replay, no autocapture, no PII in events. There is no session replay
(
disable_session_recording: trueon web) and no autocapture on the dashboard. Asanitize_propertieshook scrubs query strings and fragments and masks/devices/:deviceIdfrom every URL-bearing property, so device ids and any transient auth token never reach PostHog. No event property contains PII — no device names, hostnames, tokens, command payloads/notification text, IP addresses, or URLs-with-secrets. - No key, no analytics. Everything no-ops when no PostHog key is configured.
- No tracking. No App Tracking Transparency prompt is shown because there is no tracking — no advertising identifiers, no cross-app or cross-site tracking, and no data sales.
6. Data we do NOT collect
Section titled “6. Data we do NOT collect”CommandLatch does not collect any of the following:
- Precise or coarse location / GPS
- IP-based geolocation (GeoIP disabled on every analytics event via
$geoip_disable) - Contacts / address book
- Browsing history or search history
- Keystrokes
- Screen contents or screenshots
- File contents on your Mac
- Advertising / device advertising identifiers (IDFA); no App Tracking Transparency prompt (no tracking)
- Health, financial-account, or other sensitive special-category data
- Microphone / camera / photos input
- Cross-app or cross-site tracking; data is never sold, rented, or shared with advertisers or other users
7. International data transfers
Section titled “7. International data transfers”CommandLatch is operated from Germany and keeps its core data in the European Union. Some sub-processors are based in the United States; where personal data is transferred to them, the transfer is protected as follows:
- EU-hosted (no third-country transfer of application data): Supabase (all account/app data) and PostHog (analytics) keep processing in the EU.
- US processors under EU Standard Contractual Clauses (SCCs): Stripe (payments), Resend (transactional email), Vercel (web hosting), and GitHub Actions (CI/CD — no end-user personal data in scope).
- Apple: for APNs push delivery (the
alertaction) and App Store distribution / in-app purchases, Apple processes the relevant data under its developer/platform terms and data-protection addendum, with EU SCCs as applicable.
See the Sub-processors page for the per-provider location and safeguard.
8. Your rights (GDPR)
Section titled “8. Your rights (GDPR)”Under the GDPR you have the following rights over your personal data:
- Access — obtain confirmation of whether we process your data and a copy of it (Art. 15).
- Rectification — correct inaccurate or incomplete data (Art. 16). You can edit much of this yourself (e.g. device display names) in the dashboard.
- Erasure (“right to be forgotten”) — have your data deleted (Art. 17). See §9 for how account deletion removes your email, devices, commands, and tokens.
- Data portability — receive the data you provided in a structured, commonly used, machine-readable format, and have it transmitted to another controller where technically feasible (Art. 20).
- Restriction of processing — have processing limited in certain circumstances (Art. 18).
- Objection — object to processing based on legitimate interest (Art. 21), including the analytics described in §5. On the macOS app you can also simply switch analytics off in Settings → Privacy, and on the web you can enable Global Privacy Control or Do Not Track.
- Withdraw consent — where any processing is based on consent, withdraw it at any time without affecting the lawfulness of processing before withdrawal (Art. 7(3)).
- Lodge a complaint with a supervisory authority — you may complain to a data protection supervisory authority, in particular in your EU member state of residence or place of the alleged infringement (Art. 77). Our lead authority is the data-protection authority of Hesse, Germany (Der Hessische Beauftragte für Datenschutz und Informationsfreiheit).
How to exercise your rights. Email privacy@commandlatch.app. We will respond
within the statutory time limit (normally one month) and free of charge. We may
need to confirm your identity before acting on a request.
9. Accessing and deleting your data
Section titled “9. Accessing and deleting your data”You are in control of all of it:
- See it — the dashboard shows your devices, command history, and tokens; the data on your Mac is in the folders listed in §3.
- Delete a credential — delete a shortcut or webhook, or remove a device, in the dashboard. Removing a device also removes its command history.
- Delete everything locally — follow Uninstall, which removes the app, the CLI, all local files, and revokes device access.
- Delete your account and all backend data — email
privacy@commandlatch.appto request account deletion. This removes your email, devices, commands, and tokens from Supabase, and in addition we: (a) delete or anonymise the identified PostHog analytics events keyed to your Supabase user id; (b) let the Resend/email delivery logs age out under Resend’s own retention; and (c) cancel your Stripe subscription and detach the Stripe customer — though Stripe must retain invoice/tax records under its legal retention obligations (see §2). (A self-serve “Delete account” button is planned; for now it is a request.)
10. Children
Section titled “10. Children”CommandLatch is a developer tool and is not directed at children under 16. We
do not knowingly collect personal data from children. If you believe a child has
provided us with personal data, contact privacy@commandlatch.app and we will
delete it.
11. Contact
Section titled “11. Contact”Questions about privacy, or to exercise any of the rights in §8 (including a data-deletion request):
- Privacy / data protection:
privacy@commandlatch.app - Support:
support@commandlatch.app - Imprint fallback:
adrianfilipow@outlook.de
Controller: Adrian Filipow, Tannenwaldweg 100B, 61350 Bad Homburg, Germany.
For security-specific reports, see the security model §8.
12. Changes to this policy
Section titled “12. Changes to this policy”If this policy changes materially, the updated version will be published here, the Effective date at the top will be updated, and the change will be noted in our changelog. The version published here at any time is the current policy. For significant changes we may also notify you by email.
See also
Section titled “See also”- Sub-processors — the full list of providers, what they handle, where, and under what safeguard.
- Security & trust model — what can and can’t run, how tokens work, how to disable remote control.
- Known limitations — what CommandLatch can and can’t do.
- Get started — install, pair, and use.