MenuHUD Privacy Policy
MenuHUD has no accounts, advertising, or cross-app tracking. In Beta and Release builds with a validated Product Telemetry configuration, Usage Analytics through Mixpanel and Crash Reporting through Sentry are enabled by default. You can turn either one off independently in General Settings. Sparkle update checks are controlled separately, and Public Network Status makes a request only after you explicitly enable that default-off feature.
Since 1.7.0 the public Release Build withholds the Tip Jar: it has no Support Page, shows no Support Prompt, and makes no commerce request. A Supporter License issued by an earlier version stays valid and verifies offline. The next section describes the Supporter License purchases those earlier versions offered and the purchase-email recovery this website still provides for them.
Fan Control (1.9 Beta)
The 1.9 Beta introduces Fan Control for Apple silicon Macs with fans. It installs a privileged Fan Control Helper only when you turn Fan Control on in Settings → Sensors and approve it in macOS. The helper makes no network calls. Fan Speeds never leave the Mac. Manual speeds are temporary and are never saved or restored after wake. Choose Remove Fan Control Helper in Settings → Sensors before deleting MenuHUD; turning Fan Control off releases all fans but leaves the helper registered. Usage Analytics records only whether Fan Control was turned on or off; it never includes RPM, fan counts, or Manual holds.
Supporter License purchases
Paddle.com is the Merchant of Record for Supporter License purchases. It handles payment details, applicable tax, receipts, payment support, and refunds in Paddle Hosted Checkout. MenuHUD never receives your card or bank details.
- Checkout creation sends only the selected
small,medium, orlargeTip Tier to MenuHUD's isolated Live commerce Worker atcommerce.menuhud.justinyan.app. The request contains no calendar data, system measurement, Product Telemetry identity, or user-entered text. The Worker asks Paddle to create the matching transaction, generates a random claim token, and durably stores the transaction and token hash before it returns the Hosted Checkout URL. MenuHUD saves the pending transaction ID, claim token, checkout URL, timestamps, environment, and last known state on that Mac before it opens the URL in your browser. - Bounded automatic claim checks begin only for a checkout created and saved by that Mac. MenuHUD checks for roughly five minutes after creation and may check again when the app launches, the Support Page opens, or Paddle redirects back to the app. Unpaid pending checkouts are checked automatically for up to 30 days; a checkout Paddle has reported as paid may keep being checked so a delayed license is not lost. Each no-store request sends the random claim token to the Worker. MenuHUD stores a returned raw license in local preferences and verifies it against a public key built into the app; future verification needs no network request. Paddle Hosted Checkout may append the transaction ID, purchase email, and Paddle customer ID to its
menuhud://purchase-completereturn URL. MenuHUD accepts only that callback route and deliberately does not parse, persist, log, or use the appended query data; it checks only claims already saved on that Mac. - Issuance and transaction recovery recheck the canonical Paddle transaction before the Worker creates or returns a license. Paddle's verified
transaction.completednotification accelerates fulfillment but is not the sole recovery path. The Worker keeps the transaction, signed license, purchase date, and pending-claim relation in its durable D1 recovery database. If Paddle supplies an email address, the Worker normalizes it and stores only a versioned keyed HMAC as a recovery index; a separate shorter one-way hint may appear inside the signed license. Transaction and HMAC recovery records have no scheduled expiry; neither do claim-token-hash mappings. A canceled transaction's claim-token hash remains as a terminal mapping so a retry after a lost response can tell the app to remove its saved checkout. Advanced recovery in the app may present the unguessable Paddle transaction ID in a no-store POST body; the Worker rechecks it with Paddle before returning the license to the app. - Purchase-email recovery is the default app path and the only public website path. The email travels in a same-origin JSON POST body, never a URL. The app does not save it in preferences. The Worker normalizes and HMACs it immediately and does not persist plaintext. After rate limits admit a request, the Worker uses the HMAC index and asks Paddle for an exact customer-email match and paginated completed transactions before choosing the newest purchase. The normalized email exists only for that request. Every response says Check Your Inbox whether the address matched, was limited, or hit a recoverable failure, and no HTTP response contains a license.
- Each email HMAC is limited to three attempts in an exact rolling 24-hour window in D1. Each opaque attempt row stops counting at that exact boundary; the next request for the same HMAC or the scheduled five-minute maintenance scan removes expired rows. A delayed maintenance scan can retain an expired row longer without extending the limit. A separate Cloudflare rate-limit binding applies a coarse 20-per-minute source-IP burst limit with different Live and Sandbox namespaces. The binding receives a one-way IP-derived key, not the plaintext email or IP. Limited requests keep the same generic response.
- A recovery request creates only a random opaque Queue job. Before sending, the consumer rechecks every included purchase and its current customer email with Paddle, requires the email HMAC to match, and sends only the newest license. Other completed purchases are summarized by canonical date and amount without including their keys. Cloudflare Email Sending necessarily receives the canonical recipient, subject, complete message (including the one license), provider message ID, and delivery metadata. Email Preview is disabled for the sending domain. Application logs and Product Telemetry exclude email bodies, licenses, request bodies, claim tokens, and complete transaction IDs.
- The Worker and Paddle necessarily receive the source IP address as ordinary HTTPS connection metadata. Cloudflare hosts the Worker, its dedicated encrypted bindings, and the D1 recovery database. MenuHUD does not join purchase records to Usage Analytics, Crash Reporting, calendar content, or system measurements.
- A full refund within 14 days does not revoke the purchase. The Supporter License remains valid and keeps working because it unlocks no app feature.
- Supporter Recovery Deletion is a private human-support operation with no public destructive endpoint. Support verifies one selected transaction using its canonical Purchase Email, a forwarded receipt, or the transaction ID with exact canonical date, currency, and amount. MenuHUD never asks for an identity document, full card number, or CVV. The operation removes the selected MenuHUD recovery record and related delivery state; Paddle's merchant, legal, and financial retention is separate, and a license already stored or copied on a Mac continues to verify offline.
- Before deleting the server-side record, the operator must durably append an application-encrypted, digest-only
DELETEevent to a private Tencent Cloud COS Recovery Privacy Ledger outside Cloudflare. Live and Sandbox use separate write-only identities and separate buckets with 90-day COMPLIANCE Object Lock plus matching 90-day lifecycle expiration. Tencent receives the encrypted object, its deterministic one-way object identifier, environment prefix, size, upload and retention metadata, and ordinary HTTPS connection metadata; it does not receive the plaintext event, transaction ID, Purchase Email, receipt, or license. The versioned deletion digest inside the ciphertext is not a transaction ID or bearer credential. A separately controlled GitHub Actions identity performs a read-only daily Live inventory and a Sandbox inventory during release and restore drills, retaining for 90 days an Ed25519-signed proof containing only the environment, provider cutoff, object count, and a digest of deterministic object identifiers. If an in-flight email lease delays deletion, D1 temporarily keeps the same digest, applicable verification time, and fixed expiry with the fenced transaction so a retry cannot silently extend the window. Before that expiry, a retry resumes the same verified intent. At expiry, scheduled maintenance clears an unfinished fence and its intent; any later deletion requires fresh purchase evidence and a new ledger event with a new 90-day window. A later explicit transaction-ID or Purchase Email restore may reconstruct a missing record only after COS durably records a freshRECONSTRUCTevent. If that append boundary is unavailable, reconstruction remains fenced and fails closed. Automatic checks, webhooks, and reconciliation never insert a missing root and cannot reconstruct a deleted record.
Product Telemetry
There is no Product Telemetry prompt. In a configured Beta or Release build, both services start enabled. You can turn either one off independently in General Settings, and MenuHUD preserves any explicit on or off choice from an earlier version.
- Usage Analytics sends allowlisted daily app activity and named feature actions directly to Mixpanel. Each Usage Signal contains fixed app, build, schema, and Release channel metadata; a random per-signal retry identifier; and a random identifier that resets each UTC day. It contains no free-form text or automatic device properties. Counts describe daily active installs with Usage Analytics enabled, not people or every MenuHUD install. The complete Usage Signal payload catalog lists every event and closed property.
- Crash Reporting sends native crash stacks and the minimum compatibility and debug-image details needed to symbolicate them directly to Sentry. It sends no Usage Analytics identifier, MenuHUD user identity, app content, breadcrumbs, logs, screenshots, attachments, performance data, session data, or handled errors. Crashes that happen while Crash Reporting is disabled cannot be recovered.
- Release 1.8.1 uses United States storage. Sentry retains crash events for 30 days. Mixpanel may retain raw analytics events for up to two years; MenuHUD has not verified a shorter account-specific limit. This release uses a version-scoped maintainer waiver for that Mixpanel retention exception. The release gate still limits project access to maintainers who use multifactor authentication, prohibits using MenuHUD data with provider AI or advertising, and disables data forwarding to secondary integrations.
- Each provider necessarily receives the source IP address as ordinary HTTPS connection metadata. MenuHUD does not add it to a payload. Mixpanel requests set
ip=0so it is not used for event geolocation, and Sentry is configured to prevent storing the inferred IP address. Server-side data scrubbing provides a second boundary for crash records. - Disabling Usage Analytics deletes the current daily identifier and clears queued local Usage Signals; no new request starts after disabling completes. Disabling Crash Reporting closes the SDK and captures no later crash. Data a provider accepted before disabling remains until the applicable retention period expires.
- Because the analytics identifier changes daily and Crash Reporting has no MenuHUD-supplied identity, MenuHUD cannot reliably target historical records for per-person deletion. Broader project/date deletion and the stated retention period remain available.
- Mixpanel and Sentry receive no shared MenuHUD-supplied identity or correlation key. Neither provider receives calendar content, Meeting Links, World Clock content, process names, network identities as payload fields, or hardware or system measurements.
What stays on your Mac
- The calendar events MenuHUD displays are read from the macOS system calendar database (EventKit), with your permission, entirely on your Mac.
- Open Calendar and Reveal in Calendar run only when you activate their controls. macOS may ask for Automation permission so MenuHUD can navigate Apple Calendar to the Selected Day or show the chosen Event. This local integration is limited to Calendar's read and user-interface scripting groups; it cannot create, edit, move, accept, decline, or delete Events. Event locators stay in bounded process memory and are never persisted or logged.
- World Clocks use the time zones and city coordinates installed in macOS's local time-zone database. MenuHUD computes local times, relative day offsets, and sun and moon rise and set times entirely on your Mac without a network request. Your configured cities, custom labels, order, and menu bar choices are stored only in local preferences.
- CPU, GPU, memory, disk, Temperature Sensor, and battery measurements are read from macOS and the Mac's local hardware interfaces. Recent graphs are bounded in-memory windows and are cleared when their Module stops, loses continuity, or MenuHUD quits. MenuHUD neither persists these measurements nor sends them anywhere.
- CPU, Memory, and Disk Top Processes read process names and local resource counters while their Module is visible. They keep only the latest bounded ranking in memory, exclude MenuHUD itself, and share one local process reader that stops and clears its cache after the last consuming Module is hidden. No process name or resource measurement is persisted or transmitted.
- The Network Speed Indicator reads aggregate byte counters for eligible local network interfaces. Its popover keeps at most 15 minutes of aggregate rates in memory and reads the Measured Interfaces' local IP addresses from macOS. This transient data is cleared when measurement stops or loses continuity; it is never persisted or sent anywhere. MenuHUD does not capture packets or inspect traffic contents.
- Network Top Processes reads process names and process-attributed upload and download byte counters from macOS while the Network Module is visible. It keeps only the latest one-second ranking in memory, excludes MenuHUD itself, and never reads packet payloads. Hiding the Network Module or quitting MenuHUD stops the reader and clears the names and rates. None of this data is persisted or sent anywhere.
- Wi-Fi Details is off by default. When you enable it, macOS requires MenuHUD to ask for Location access before CoreWLAN can reveal the current network name. MenuHUD does not request your location, receive or store coordinates, scan for nearby networks, or send Wi-Fi details anywhere. It keeps only the current network name, signal strength, and band in memory while the visible Network Module is observing them. Disabling Wi-Fi Details or hiding the Network Module stops that observation and clears the readout.
- Public Network Status is off by default. When you enable it, MenuHUD makes an HTTPS request to
api64.ipify.orgwhen visible Network monitoring starts and every five minutes thereafter. The request sends no calendar data, local IP addresses, throughput, hardware metrics, or identifier created by MenuHUD. Like every web service, ipify necessarily sees the public IP address making the request; its response contains that same IPv4 or IPv6 address. MenuHUD holds the response only in process memory. Disabling the feature or hiding the Network Module cancels an in-flight request, stops future refreshes, and clears the result; a failed lookup clears any previous result instead of displaying it as current. - MenuHUD checks for updates using Sparkle. Update checks are separate from the Product Telemetry controls described above. Sparkle downloads a list of available versions and, if you choose to install one, the update itself. macOS asks whether you want automatic checks the first time MenuHUD launches, and you can turn them off. These requests carry no account, no identifier MenuHUD creates, and nothing about your calendars or your network; only what any download needs: your IP address and the version you are updating from.
- Every update is verified against a signing key built into MenuHUD before it is installed, so a tampered or substituted download is refused rather than applied.
- MenuHUD uploads neither calendar data nor network measurements. Since 1.7.0 the app contacts no commerce service; the disclosed commerce Worker now serves only this website's purchase-email recovery for earlier purchases.
- Hiding any Module removes its menu bar status item and stops that Module's sampling, Module-specific observers, process reader, and optional network work. Re-enabling it starts a fresh collecting interval instead of reusing a hidden measurement.
- Settings, such as hidden calendars, Module Visibility, your update channel, World Clocks, Wi-Fi Details, and Public Network Status, are stored locally on your Mac. While Usage Analytics is enabled, MenuHUD may send only an allowlisted setting name and closed selection such as
enabledordisabled; it never sends calendar names, city names, network names, labels, or a settings dump.
About this website
This website (not the app) uses Plausible, a cookie-less, privacy-friendly analytics service, to count visits in aggregate. It sets no cookies, collects no personal identifiers, and does not follow you across sites. The app's Product Telemetry is separate: Mixpanel and Sentry start enabled in configured Beta and Release builds and have independent opt-outs inside MenuHUD.