Etna

Privacy

Last updated July 31, 2026 · Applies to Etna 1.3 and later

Etna is private by architecture, not by promise. There is no Etna cloud, no account, and no server of ours anywhere. This page is the complete account of what Etna does with data — including, below, the entire vocabulary of the optional anonymous analytics: every signal the app can ever send.

The short version

What stays on your Mac

Live audio from your microphone and from other apps (Zoom, Meet, Teams…) is processed on-device by Apple's speech models and on-device speaker separation. Transcripts, summaries, pre-meeting notes, and the stakeholder pages in your People/ folder are markdown files in your vault — readable by anything, locked to nothing, and never uploaded by Etna.

Voice profiles that let Etna recognize a named speaker across meetings are stored locally on your Mac.

Calendar data never leaves this Mac. Etna reads your calendar to detect meetings. Invite email addresses may be read transiently to infer a company label for a stakeholder page (e.g. "PandaDoc"); the addresses themselves are never written to your vault, never written to disk, and never sent anywhere. Even the opt-in analytics never use calendar data — participant counts, for example, come only from voices actually observed in the meeting.

Live translation runs on-device via Apple's Translation framework. Speech, speaker-separation, and translation models are downloaded once when needed; those download requests carry no user data.

Optional cloud summaries — your key, your choice

By default, meeting summaries run on Apple Intelligence, on-device and free. If you add your own API key for Claude (Anthropic), OpenAI, or Gemini (Google) and select it as your summarizer, the meeting transcript is sent to that provider to produce the summary. That request goes directly from your Mac to the provider under your key and their terms — Etna never sees, stores, or proxies it. No key configured, nothing is ever sent.

Anonymous usage analytics — opt-in, with the full vocabulary

Etna can send anonymous usage statistics through TelemetryDeck to help us understand which features matter and which errors happen in the wild. This is strictly opt-in:

What a signal can and cannot contain

Each signal is automatically accompanied by app version and build, OS version, device model and architecture, and locale — nothing else.

The complete signal table

This table is the entire vocabulary — the app cannot send a signal that is not listed here. It is published from the same file that gates our development process: a feature that adds a signal must update this table in the same change.

SignalParametersFired when
App.launchedautoRecord, autoDetectLanguage, summaryRouting (cloud/local), translationEnabled, detectionEnabled, peopleNotes, peopleFactsThe app starts
Consent.grantedsource (onboarding/settings/prompt)You turn analytics on
Onboarding.completedOnboarding finishes
Guide.completedThe first-run guide plays to its natural end
Vault.configuredA vault folder is chosen successfully
Meeting.startedorigin (manual/autoDetection), sourceApp (meeting-app name from a fixed registry, or none), engine (sortformer/classic)Recording begins
Meeting.finisheddurationBucket, participantBucket (observed speakers only), languages (e.g. en+ru), summaryEngine (appleIntelligence/anthropic/openai/google/none), summaryModel (catalog model ID / appleIntelligence / custom / none), summaryLatencyBucket (<5s … >3m), summaryOutcome (ok/failed/empty), transcriptionOutcome (ok/partial), translationUsed, origin, isFirst, speakersNamedBucket (0 … >5 — how many speakers ended with a real name; counts only, never the names), voiceAutoBucket, voiceSuggestBucket (0 … >5 — voice-memory auto-assignments / suggestion offers this meeting), acceptedDistanceBucket, rejectedDistanceBucket (<0.25 … >0.60 or none — median voice-match distances, per-meeting aggregates only, never per-speaker), voiceBar (0.40/0.45 — which voice-match threshold was active)A meeting completes
Meeting.discardeddurationBucketYou discard a recording
Meeting.splittrigger (calendar/appChange), decision (auto/accepted/dismissed)A back-to-back meeting boundary is handled
Meeting.autoRecordCancelledYou cancel a pending auto-record
Meeting.systemAudioStalledreason (noAudio/noTranscription), elapsedBucket (<5m … >2h — how far into the meeting it happened)The other side's audio goes quiet or stops transcribing mid-meeting (at most once per meeting)
Meeting.tapRebuildscountBucket (1-2/3-10/over10), trigger (deviceChange/rateDrift/starved/zeroByteStorm — the first rebuild trigger of the meeting)A meeting finishes after its system-audio tap had to be rebuilt (e.g. you switched audio devices)
Meeting.summaryRegeneratedsummaryEngine/summaryModel (same vocabulary as Meeting.finished), summaryLatencyBucket, summaryOutcome (ok/failed), trigger (manual/sweep)A summary that failed at meeting end is rebuilt from the saved transcript — via the finished card's "Try Again" or the automatic recovery on the next launch
Error.occurredcode (error category name, other, emptyMeeting), context (start/recording/finalize/organizer)An operation fails
Organizer.suggestionkind (folder/restructure), action (applied/snoozed/undone)You act on an organizer suggestion
Speakers.namesAppliedcountBucket, surface (panel/review/popover)You save speaker names (closing without changes sends nothing)
Speakers.mergedYou merge over-split speaker rows
Notch.openedThe notch panel opens
Scratchpad.openedYou open pre-meeting notes (closing sends nothing)
Translation.enabledLive translation is switched on
Feedback.composeddiagnosticsIncludedA feedback email draft is created
WhatsNew.openedsource (autoOpen/settings)The release-notes window opens
PeopleNotes.writtencreatedBucket, updatedBucket (bucketed page counts — never who)Stakeholder pages are updated after a meeting
PeopleNotes.toggledenabledThe stakeholder map is turned on or off
PeopleFacts.extractedfactsBucket, peopleBucket (facts kept / pages that received them this meeting — bucketed counts only), droppedBucket (facts rejected by validation), engine (which summarizer ran, or none), outcome (ok/failed/timeout/skippedNoEngine)Profile highlights are distilled after a meeting (never fired when there was nothing to extract for)
PeopleFacts.toggledenabledProfile highlights are turned on or off
PeopleFacts.consolidatedpagesBucket (pages that completed a pass), supersededBucket (facts a model correction archived), archivedBucket (facts the staleness and cap rules archived), outcome (ok/partial/failed)The once-a-day background tidy of profile highlights does work

Current as of Etna 1.4. Signal names are stable — a rename is treated as a breaking schema change.

Deliberately not tracked

Some things are untracked as a decision, not an omission:

Software updates

Etna checks for updates once a day by fetching a static file (the Sparkle appcast) from this site. The request carries no account, no identifier, and no system profile — it is the same anonymous fetch your browser makes loading this page.

Feedback emails

"Send Feedback…" opens a draft in your email client — nothing is sent until you press send, and you see exactly what is in it. The optional diagnostics report is plain text you can read: app and OS versions, an allowlisted snapshot of settings, and the current run's app logs — with redaction enforced by automated tests. It never contains meeting content, names, file paths, or API keys.

Contact

Questions about any of this? Write to mail@j-alyavdin.com.