Files
VoiceStudio/docs/install/macos.md
T
Palash DebnathandClaude Opus 4.8 948bc76543 macOS: ad-hoc sign so users open without Terminal + signing/notarization verification (#290)
* chore(release): add macOS signing/Gatekeeper/notarization verification

Codify and enforce the macOS build-signing requirements. The release
pipeline built bundles and had opt-in Apple signing, but never verified
codesign/spctl/notarization — unsigned or broken bundles could ship silently.

- scripts/verify-macos-signing.sh: runs codesign --verify --deep --strict,
  spctl Gatekeeper assessment, per-nested-Mach-O signature check, stapler
  validate, and (opt-in) notarytool history. Report-only by default (unsigned
  dev/preview is expected); --require-signed fails on any unsigned/un-notarized
  component so a broken release stops instead of publishing an unsigned artifact.
- scripts/macos-dev-unquarantine.sh: local-dev-only quarantine stripper, with a
  loud "never a substitute for notarization" warning.
- release.yml: new "Verify macOS signing" step on the macOS leg — report-only on
  unsigned paths, STRICT on the opt-in signed stable path (same condition as
  "Configure Apple signing"), so signing/notarization failures fail the job.
- docs/macos-signing-verification.md: the canonical 10-point requirements +
  how-to-verify checklist, cross-linked to docs/install/macos.md and DESKTOP_RELEASE.md.

Verified locally: report-only PASS (exit 0) and --require-signed FAIL (exit 1)
against the real unsigned debug .app; release.yml parses as valid YAML.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(macos): ad-hoc sign bundle so users open it without Terminal (no Apple ID)

The "app is damaged and can't be opened" error is caused by a broken/incomplete
code-signature seal (codesign --verify failed: "code has no resources but
signature indicates they must be present") on the quarantined download — there
is no GUI bypass for that variant on modern macOS, forcing users to run `xattr`.

Give the bundle a VALID ad-hoc signature at build time (free, no Apple Developer
account) via tauri.conf.json bundle.macOS.signingIdentity = "-". Verified through
a real `tauri build`: the produced .app is now flags=adhoc,runtime and passes
codesign --verify --deep --strict. A valid seal flips the Gatekeeper prompt from
the un-bypassable "damaged" to the GUI-bypassable "unidentified developer", which
users clear with right-click → Open / Settings → "Open Anyway" — no Terminal.

Still not notarized (that needs the paid Apple ID), so there's a one-time
confirmation rather than a clean double-click. The opt-in Developer-ID path is
unchanged: APPLE_SIGNING_IDENTITY (env) overrides the "-" default on the signed
stable release.

- tauri.conf.json: signingIdentity "-" (ad-hoc default).
- verify-macos-signing.sh: detect ad-hoc tier; report the no-Terminal GUI path
  in report-only, still FAIL it under --require-signed (production must notarize).
- docs/install/macos.md: lead the Gatekeeper section with right-click → Open;
  keep xattr as fallback for the harsher "damaged"/corrupted-download case.
- docs/macos-signing-verification.md: signing-tiers table + ad-hoc default note.
- release.yml: comment the ad-hoc default + env override on the signed path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 13:26:04 +05:30

5.5 KiB
Raw Blame History

OmniVoice Studio — Install on macOS

This page is self-contained: follow it top to bottom and you'll end up with a working OmniVoice Studio install on macOS (Apple Silicon or Intel).

Prerequisites

  • macOS 12 (Monterey) or newer — Apple Silicon or Intel.
  • Python 3.11+brew install python@3.11 (or use pyenv / the system Python if you already have ≥3.11).
  • Buncurl -fsSL https://bun.sh/install | bash.
  • Xcode Command Line Toolsxcode-select --install.
  • FFmpeg (used by the dubbing + capture pipelines) — brew install ffmpeg.

Optional but recommended:

Install (from source)

git clone https://github.com/debpalash/OmniVoice-Studio.git
cd OmniVoice-Studio
bun install
bun run desktop-prod

The first launch builds the Tauri shell, creates the Python venv via uv, syncs deps, and downloads model weights (~2.4 GB). The splash screen shows live progress for every step.

Install (pre-built .app)

Download the latest DMG from the Releases page, double-click to mount, drag OmniVoice Studio.app into /Applications.

If the first launch is blocked by macOS Gatekeeper ("OmniVoice Studio cannot be opened because the developer cannot be verified"), see the next section — it opens with one right-click, no Terminal.

App is "damaged" / can't be opened (Gatekeeper)

On first launch you'll see "OmniVoice Studio cannot be opened because the developer cannot be verified" — macOS Gatekeeper blocking an app it can't trace to a paid Apple Developer account (issues #134, #72).

Why: the build is ad-hoc code-signed (a valid signature, free) but not yet notarised by Apple, so macOS quarantines any copy downloaded from the internet and asks you to confirm the first launch. This is expected for open-source builds — releases are notarised (warning-free) only once the project's Apple Developer ID pipeline is funded (see "For maintainers" below). Confirming is safe because you downloaded from the official repo / Releases page; for belt-and-braces, verify the SHA-256 against the *.dmg.sha256 checksum on the release page first.

Fix — GUI, no Terminal (do this): in Finder, right-click (or Control-click) OmniVoice Studio.appOpen → click Open again in the dialog. (On macOS 15 Sequoia: double-click once, then go to System Settings → Privacy & Security, scroll down, and click "Open Anyway".) This is a one-time confirmation per install; afterwards it launches by double-click.

If you instead see the harsher "app is damaged and can't be opened. Move to Trash" with no Open option, the download was corrupted or it's a pre-signing build — re-download the latest release, or use the Terminal fallback below.

Fix — Terminal: after dragging the app into /Applications, run:

xattr -dr com.apple.quarantine "/Applications/OmniVoice Studio.app"

(Adjust the path if you put the app somewhere other than /Applications. The broader xattr -cr "/Applications/OmniVoice Studio.app" also works — it clears all extended attributes rather than just the quarantine flag.)

That clears the quarantine attribute so Gatekeeper stops blocking the launch — a one-time fix per install.

For maintainers — enabling notarised builds

The release workflow (.github/workflows/release.yml) is already wired to code-sign + notarise the macOS bundle; it activates automatically once these repository secrets are set (it skips signing — producing today's unsigned build — when they're absent):

Secret What
APPLE_CERTIFICATE Developer ID Application cert, exported as a base64-encoded .p12
APPLE_CERTIFICATE_PASSWORD password for that .p12
APPLE_SIGNING_IDENTITY e.g. Developer ID Application: Your Name (TEAMID)
APPLE_ID Apple ID email used for notarisation
APPLE_PASSWORD an app-specific password for that Apple ID
APPLE_TEAM_ID your 10-char Apple Developer Team ID

Requires a paid Apple Developer account ($99/yr). Once set, downloaded DMGs open without the quarantine step.

Apple Silicon vs Intel

  • Apple Silicon (M-series): OmniVoice automatically picks the mlx-whisper and mlx-audio backends where available — these use the Apple Neural Engine and Metal Performance Shaders for ~2× the throughput of the CPU path.
  • Intel macs: falls back to faster-whisper (CTranslate2) on CPU. Still fast; just no ANE acceleration.

The picker in Settings → Engines shows which backend is active.

The default install works without a token, but diarization (the pyannote/speaker-diarization-3.1 model) is gated and the larger voice-design engines also download faster with a token attached.

  • Open Settings → API Keys in the app.
  • Or set the env var export HF_TOKEN=hf_… in ~/.zshrc.

Full details: docs/setup/huggingface-token.md.

Troubleshooting

Hit a wall? See docs/install/troubleshooting.md.

The in-app error UI (the React error boundary that fires on backend errors) includes an "Open docs for this error" button — that button deeplinks back into this docs tree at the right section for the error class.