Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Murmur

Murmur Logo

Local-first, hold-to-talk voice dictation for macOS. Hold a hotkey, speak, release — your speech is transcribed and inserted at the cursor in any app. Similar in spirit to Wispr Flow, but open and self-hosted: the speech-to-text and optional LLM cleanup run locally by default, and both endpoints are configurable so you can move processing to another machine (e.g. an NVIDIA DGX Spark) by changing a URL.

Status

Early development. See PLANNING.md and docs/superpowers/specs/2026-06-01-murmur-design.md.

How it works

  1. Hold the hotkey (default: Right Option ⌥) and speak — or, in toggle mode, tap once to start and tap again to finish (comfortable for long notes).
  2. On release/stop, Murmur sends the recorded audio to the speech-to-text engine and (optionally) runs an LLM cleanup pass.
  3. The text is inserted at your cursor in the frontmost app.

Models

  • Speech-to-text: whisper-large-v3-turbo via whisper.cpp (Metal-accelerated, multilingual).
  • Optional LLM cleanup: Qwen2.5-7B-Instruct via Ollama (OpenAI-compatible API).

Requirements

  • Apple Silicon Mac, macOS 14+ (developed targeting an M2 Pro, 32 GB).
  • A Swift toolchain (full Xcode, or Command Line Tools — see build note below).
  • macOS permissions: Microphone, Accessibility, Input Monitoring.
  • Ollama installed if you want the LLM cleanup pass.

Setup

# 1. One-time: build the whisper.cpp server + download the model
#    (installs cmake via Homebrew if missing; model is ~547 MB)
./Scripts/setup.sh

# 2. (optional) LLM cleanup backend
ollama pull qwen2.5:7b

# 3. Build the app bundle and launch
./Scripts/run.sh                # builds Murmur.app and opens it

The individual steps (build-whisper.sh, fetch-model.sh) can also be run directly; fetch-model.sh accepts MODEL_FILE/MODEL_URL overrides to use a different model.

Scripts/make-app.sh produces a real Murmur.app with an Info.plist (so macOS will grant the microphone permission — a bare swift run binary cannot request it). Grant the three permissions when prompted (or in System Settings → Privacy & Security), then hold Right Option and talk.

Build note

The standard build is SwiftPM (swift build), used automatically by make-app.sh. If your Command Line Tools install is affected by the known duplicate-SwiftBridging modulemap bug (every Foundation import fails to compile), Scripts/build-swiftc.sh builds without SwiftPM and auto-applies a VFS-overlay workaround — no system files are modified. make-app.sh falls back to it automatically.

Permissions & code signing

Murmur needs three macOS permissions — Microphone, Accessibility, and Input Monitoring. macOS (TCC) ties each grant to the app's code signature: when you grant a permission it records the app's designated requirement (DR) and re-checks it on every launch. make-app.sh signs the bundle automatically and picks the strongest mode available:

  • Ad-hoc with a stable DR — the default, zero setup. With no code-signing certificate on the machine, the app is ad-hoc signed but pinned to an explicit DR of identifier "io.github.jvr0x.murmur". That DR does not change between rebuilds, so your permission grants survive updates. Caveat: an identifier-only DR is satisfied by any local binary that claims this bundle identifier — there is no cryptographic anchor. Acceptable for a personal dev build.
  • Certificate-anchored DR — recommended. Run ./Scripts/make-signing-cert.sh once to create a self-signed code-signing certificate in your login keychain. Afterwards make-app.sh auto-detects it and signs with it, producing a DR of the form identifier "…" and certificate leaf = H"…" — stable across rebuilds and cryptographically anchored to your certificate. The script is interactive: it asks for your login-keychain password (so codesign can use the key without prompting on every build) and macOS may show a one-time trust dialog. Override the identity name with MURMUR_SIGN_IDENTITY if you like (it must match for both scripts).

Why permissions used to break on every rebuild. The old signing produced an implicit DR of cdhash H"…" — a hash of that exact build. Every rebuild changed the hash, so the DR macOS had stored no longer matched, macOS treated the new build as a different app, and all three grants silently went stale. The stable DR above fixes that.

Switching signing modes re-grants once. Moving from ad-hoc to the certificate (or the reverse) changes the DR one final time, so macOS asks for the three permissions once more right after the switch. From then on the DR is constant and grants persist.

Update in place, don't delete-then-copy. Because TCC matches on the bundle at its install path, make-app.sh rebuilds Murmur.app in place without removing the directory. If you keep a copy elsewhere (e.g. ~/Applications), overwrite it rather than deleting and re-copying, so the existing TCC entry keeps matching:

ditto Murmur.app ~/Applications/Murmur.app   # overwrites in place

A delete-then-copy can drop the TCC entry and force an unnecessary re-grant.

Configuration

Settings (menu-bar icon → Settings) let you change the hotkey, STT/LLM endpoints, models, and the cleanup prompt. To use a remote server, set the STT backend to "OpenAI-compatible" with the server URL and/or point the LLM base URL at the remote host.

The LLM Cleanup section has a Provider picker that prefills the base URL for Ollama (http://localhost:11434/v1) or LM Studio (http://localhost:1234/v1); choose Custom to point anywhere else (e.g. a model server on your Spark). The URL stays the source of truth, so editing it just flips the picker to the matching provider.

Hotkey

Pick a ready-made preset (Right Option ⌥, Right Command ⌘, fn/Globe, F20, F13, ⌃ + Space, ⌥ + Space) or record your own: click Record and press any key, modifier, or combo — modifiers plus a key (⌃ + Space), or modifiers only (⌘ + ⌥). Esc cancels. Changes apply immediately, no relaunch.

Activation chooses how the hotkey drives a dictation:

  • Hold to talk (default) — press and hold while speaking, release to transcribe.
  • Tap to start / stop — tap once to start recording, tap again to finish.

License

MIT. See LICENSE.

About

A simple, local Speech-to-Text app for MacOS using whisper.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages