Privacy
Last updated 2026-09-01. This page describes behavior implemented in the repository today, not future plans.
This website
The site is a set of static pages. It sets no cookies, loads no analytics or third-party tracking scripts, and has no accounts, forms, or comments. The only outbound links point at GitHub.
A static host may keep operational access logs (IP, user agent, request path). That data is processed by the hosting provider and is outside this project's control; once a provider is chosen, this section will name it.
The desktop app
Tidy runs locally on your Mac. Every scan, preview and deletion happens on your machine, and the app window's content security policy is limited to default-src 'self', so the web layer has no outbound network access at all.
The app does send anonymous usage statistics. This is on by default and can be turned off at any time. The "Anonymous usage statistics" section below lists every field it collects.
What is stored locally
~/.config/mole— shared state including language preference, the whitelist, andsettings(the update-check and usage-statistics switches, plus the random install identifier).~/Library/Logs/mole— operation history inoperations.logand deletion history indeletions.log, both byte-compatible with the Mole CLI.
These files are never uploaded. Deleting them clears the history; the app recreates them on the next operation.
When the app uses the network
The app makes network requests in exactly three situations:
- You deliberately run a software update check (checking the other apps you have installed);
- Checking for a Tidy update — one fetch of
latest.jsonfrom GitHub Releases after launch, at most once every 24 hours. Turn it off in Settings › General and no request is made at all; - Sending anonymous usage statistics — see the next section; can be turned off.
When checking other apps, requests go only to: Apple's bundle-ID lookup (to resolve the exact Mac App Store product page), the Sparkle feed an installed app declares for itself (HTTPS), and the provider declared in an Electron app's app-update.yml plus the GitHub release API. The Homebrew path reads local brew output and makes no additional network request. Requests carry only the app identifier and version needed to compare releases — never file paths, file contents, clipboard data, or personal information. A scan result expires after 15 minutes.
Anonymous usage statistics
They answer one question: which features people actually use, and what goes wrong on which version. On by default, announced explicitly on first launch, and switchable at any time under Settings › General › Anonymous usage statistics.
Turning it off stops reporting immediately and deletes both the pending local queue and the random install identifier. Turning it back on generates a new identifier, which statistically makes you a new user.
Random install identifier: a random UUID generated when statistics are first enabled, stored in ~/.config/mole/settings. It is unrelated to your hardware serial, Apple ID, MAC address or IP address. Delete the file and you become a new user.
Every event and field collected (this is the complete list, not a sample):
| Event | Fields |
|---|---|
app_launched | whether this is the first launch |
view_opened | screen name (clean / apps / optimize / analyze / status / settings) |
scan_completed | scan type, duration in milliseconds |
clean_executed | delete mode (trash / permanent), result (ok / partial / failed / cancelled) |
app_uninstalled | no fields |
optimize_run | the fixed task identifier (e.g. flushDNS) |
updates_run | update source (homebrew / app_store / sparkle / electron / website) |
self_update | previous version, new version, result |
error_occurred | a predefined error code, and which screen it happened on |
Every event also carries: the random install identifier, the Tidy version, the macOS version, and the interface language.
Deliberately not collected: how much space was reclaimed, how many items were found, how many apps were uninstalled, any path, any filename, any application name, your machine name, or raw error messages (those routinely contain absolute paths). These are excluded structurally in the code — event property types accept only fixed constants, never runtime strings.
Where the data goes: the one and only endpoint is https://t.tandem-clip.com — our own Cloudflare Worker proxy. The hostname does not carry the Tidy name because it shares a Cloudflare account with the author's other projects; if you spot it in a packet capture, that is what it is. The proxy strips client-IP headers before forwarding to PostHog for aggregation, so PostHog never receives your IP address and cannot geolocate you from it.
Events are queued locally and sent in batches every 60 seconds or on exit. A failed send is written to ~/.config/mole/telemetry-queue.json and retried on the next launch; the queue holds at most 500 events.
What does not happen
- Your document contents are never read or uploaded.
- Scanned paths, filenames, application names, and sizes are never sent to any server — usage statistics included.
- Nothing is deleted in the background: every deletion requires your selection and confirmation in the preview.
Permissions
The app touches the filesystem only within the scope you choose. System-scope actions require the privileged helper, which has not shipped, so they refuse with requires_admin instead of prompting for shell elevation.
Changes and contact
This page is updated alongside changes in app behavior. If anything here disagrees with the code, please say so in GitHub Issues.