Wave is a lightweight, native macOS dictation app focused on fast voice-to-text workflows with minimal UI overhead. Press a shortcut, speak, and your words are instantly pasted at the cursor. Supports on-device transcription via Whisper and cloud transcription via Groq, plus an AI Mode that sends your voice to an LLM and pastes the response directly.
- Dictation — global shortcut triggers recording; transcription is pasted at the active cursor
- Push to Talk or Toggle — hold to record and release, or press once to start and again to stop
- Local transcription — on-device Whisper inference, no internet required
- Groq cloud transcription — faster cloud-based transcription via the Groq API
- AI Mode — separate shortcut sends your voice to an LLM and pastes a direct answer
- Snippets — save reusable text snippets; AI Mode is aware of them
- Dictation history — recent transcriptions with right-click copy
- Language selection — auto-detect or set a specific language (ISO 639-1)
- Custom vocabulary — bias the model toward specific words and names
- Microphone selection — choose any input device or use the system default
| Action | Default |
|---|---|
| Dictation | Fn |
| AI Mode | Right Option |
Both shortcuts are fully customizable in Settings → Shortcut.
Download the latest DMG from Releases.
Releases are distributed as signed, notarized DMGs.
make buildopen build/Build/Products/Release/Wave.appOr launch from Xcode — open Wave.xcodeproj, select the Wave scheme, and run.
GitHub Actions builds signed and notarized release DMGs for tags matching v*.*.*.
Required repository secrets:
BUILD_CERTIFICATE_BASE64— base64-encodedDeveloper ID Application.p12P12_PASSWORD— password for the.p12KEYCHAIN_PASSWORD— temporary CI keychain passwordAPPLE_ID— Apple ID email used for notarizationAPPLE_APP_SPECIFIC_PASSWORD— app-specific password for notarizationAPPLE_TEAM_ID— Apple Developer Team IDSPARKLE_PRIVATE_KEY— Sparkle EdDSA private key for appcast generation
We also maintain a self-distributed "Direct" channel (Developer ID signed + notarized DMGs, Sparkle updates) hosted entirely on Cloudflare, following the same pattern used for the Ayron app:
- Artifacts (DMG + appcast.xml): published to a Cloudflare R2 bucket (
wave-updatesor equivalent) viascripts/release/publish-r2.sh. - Custom domain:
updates.wave.mxv.sh(or similar) servesappcast.xmland/downloads/Wave-latest.dmg(stable name, short cache) + versioned DMGs (long cache). - Feed URL:
https://updates.wave.mxv.sh/appcast.xml(seeConfig/Info-Direct.plistand build settings; the public Ed key lives here too). - Landing page (Astro site at
wave.mxv.sh, deployed with wrangler): prefers the directWave-latest.dmg; falls back to GitHub release assets. This is the "site" piece — updatelanding/src/data/site.ts(directDmgUrl / directAppcastUrl) and the DownloadModal as needed. (The Ayron marketing/docs sites were built in their "Verso"/Nextra setups; here we extended the existing Astro landing.)
-
One-time machine setup (release Mac):
brew install create-dmg awscli- Store notary profile:
xcrun notarytool store-credentials "wave-notary" ... - Developer ID provisioning profile named "Wave Self Distribution" (or adjust
DEVELOPER_ID_PROFILE_NAME). - Sparkle EdDSA key: run Sparkle's
generate_keysonce; private goes to Keychain, public to the SUPublicEDKey in the Info plist(s). - Copy
scripts/release/wave-release.env.example→~/.pi/agent/wave-release.env(or$WAVE_RELEASE_ENV) and fill real R2 creds + endpoint. The bucket + custom domain must be configured in Cloudflare (R2 + DNS for the updates subdomain).
-
Build the DMG (notarizes, staples, signs with Developer ID):
make release-dmg # reads version from Info(-Direct).plist make release-dmg 0.5.0 7 # or override -
Generate the signed appcast (rewrites enclosure to stable -latest.dmg):
make release-appcast -
Publish to R2:
source scripts/release/load-release-env.sh make publish-r2 # or directly: scripts/release/publish-r2.sh
Combined target (after sourcing env) and other helpers are in the Makefile. See the scripts themselves (heavily commented, referencing the Ayron equivalents) and ExportOptions-Direct.plist + Config/Info-Direct.plist.
The old GitHub-pages appcast (mxvsh.github.io) and pure GH release DMG flow can coexist during transition; flip the SUFeedURL and landing primary URL when ready to cut over.
See also: scripts/release/*.sh, Makefile (release-* targets), Ayron's scripts/release/ for the reference implementation.
- Toggle and Push to Talk recording modes
- Local offline transcription with Whisper
- Groq cloud transcription
- AI Mode with LLM response via Groq
- Custom dictionary / vocabulary
- Language selection
- Dictation history with copy
- Snippets with AI awareness
- Microphone selection
- App-specific behavior profiles
- Quality presets for speed vs accuracy
Join the Discord community for feedback and help. For bug reports and feature requests, open a GitHub issue.
- whisper.cpp — local speech-to-text inference
- Sparkle — macOS auto-update framework
- PhosphorSwift — icon library
Contributions are welcome. See CONTRIBUTING.md for local setup and expectations.