macOS menu bar text-to-speech powered by MLX Audio (Kokoro)
Project description
aloud-tts
A macOS menu bar text-to-speech tool. Select text anywhere → press ⌃⌥S → a local Kokoro-82M model (via MLX) speaks it aloud.
- Fully offline. Text never leaves your machine. No API keys, no accounts.
- Fast. Runs on Apple Silicon's Neural Engine via MLX; first word plays in ~1s after warmup.
- Lightweight. One menu bar icon. No background window, no tray clutter.
- Free & open source. MIT licensed.
Requirements
- macOS 14+ (Sonoma) on Apple Silicon (M1/M2/M3/M4) — MLX doesn't support Intel Macs
Install
Option A — curl (easiest)
curl -fsSL https://raw.githubusercontent.com/simonteague6/aloud-tts/main/install.sh | bash
Installs via uv tool install. Requires no Git clone.
Option B — Homebrew
brew tap simonteague6/aloud-tts
brew install aloud-tts
Option C — .app bundle
Download TTS.app.zip from the latest GitHub Release, unzip, and drag TTS.app to /Applications. Right-click → Open the first time to bypass Gatekeeper.
Option D — from source (dev)
Requires Python 3.12 and uv.
git clone https://github.com/simonteague6/aloud-tts.git
cd tts-app
uv sync
First launch downloads the Kokoro model (~330 MB) into your Hugging Face cache.
Run the menu bar app
uv run aloud-tts
Grant permissions (one-time)
On first launch, macOS will prompt for two permissions. Both are required — the hotkey is silent without them.
- Accessibility — lets the app simulate ⌘C to grab your selection.
- Input Monitoring — lets the app listen for the global hotkey.
System Settings → Privacy & Security → add tts-app (or the terminal you launched it from) to both lists. Fully quit and relaunch afterward.
How to use it
- Select text in any app — browser, PDF, email, anywhere.
- Press ⌃⌥S (Control + Option + S).
- Listen.
The menu bar icon shows what's happening:
| Icon | State |
|---|---|
| ⋯ | Loading model (startup only) |
| 🔈 | Idle, ready |
| 📋 | Capturing selection |
| ✨ | Generating audio |
| 🔊 | Speaking |
Press the hotkey again during playback to stop. Press once more to speak a new selection.
CLI
One-shot synthesis with no menu bar:
uv run aloud-tts-cli "Hello world" # speak and exit
uv run aloud-tts-cli - < article.txt # read text from stdin
uv run aloud-tts-cli "save it" --out out.wav --no-play # generate WAV only
Configuration
Edit src/tts_app/config.py and relaunch.
| Setting | Default | Notes |
|---|---|---|
HOTKEY |
<ctrl>+<alt>+s |
pynput hotkey format |
MODEL |
prince-canuma/Kokoro-82M |
Any Kokoro checkpoint on Hugging Face |
VOICE |
af_heart |
Available voices |
SPEED |
1.0 |
Clamp to 0.5–2.0 for natural output |
Troubleshooting
The hotkey does nothing. Input Monitoring isn't granted, or was granted to the wrong binary (common after updating your terminal). Remove and re-add the entry in System Settings, then fully quit and relaunch.
It triggers but speaks nothing. Accessibility isn't granted, so the simulated ⌘C reads an empty clipboard. Same fix.
Menu bar shows ⋯ forever. Model is still downloading on first run. Watch ~/.cache/huggingface/ for progress.
ModuleNotFoundError: misaki. Rerun uv sync — it's an optional Kokoro dep that must be installed.
Development
uv run pytest tests/ # ~2s, fakes the TTS engine
uv run ruff check src/ tests/
The codebase is split so the UI layer (rumps) and the core (clipboard + TTS + audio) are independent — both the menu bar app and the CLI reuse core/.
Credits
- Kokoro-82M — the TTS model
- mlx-audio — MLX inference
- rumps — Python for macOS menu bar apps
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aloud_tts-0.1.1.tar.gz.
File metadata
- Download URL: aloud_tts-0.1.1.tar.gz
- Upload date:
- Size: 16.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58c665ca1b96159d1b12fcf23ab3840aa9b864daa09b2f9be0d773960981b9e9
|
|
| MD5 |
5a08e89c5afc8ead80bb1ce02a424edf
|
|
| BLAKE2b-256 |
1608e79f9f7cc703121c3b1ee54740ca6ac184101358fd793ce1d5022c6f87c1
|
Provenance
The following attestation bundles were made for aloud_tts-0.1.1.tar.gz:
Publisher:
release.yml on simonteague6/aloud-tts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aloud_tts-0.1.1.tar.gz -
Subject digest:
58c665ca1b96159d1b12fcf23ab3840aa9b864daa09b2f9be0d773960981b9e9 - Sigstore transparency entry: 1340064974
- Sigstore integration time:
-
Permalink:
simonteague6/aloud-tts@27313b31ebd35b1a61286d96d9760a2bb9325d9b -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/simonteague6
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@27313b31ebd35b1a61286d96d9760a2bb9325d9b -
Trigger Event:
push
-
Statement type:
File details
Details for the file aloud_tts-0.1.1-py3-none-any.whl.
File metadata
- Download URL: aloud_tts-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adda4c0cec013555fc555d24a54326493f937d201a62606f18b8a472a5f21e9a
|
|
| MD5 |
90f3be6c8aed0cc725b85c38f588c1df
|
|
| BLAKE2b-256 |
84b98bb0a21f8a72bdeb63442cf62a9bdbc5568bccdc57d2b1690d7cc60294dc
|
Provenance
The following attestation bundles were made for aloud_tts-0.1.1-py3-none-any.whl:
Publisher:
release.yml on simonteague6/aloud-tts
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aloud_tts-0.1.1-py3-none-any.whl -
Subject digest:
adda4c0cec013555fc555d24a54326493f937d201a62606f18b8a472a5f21e9a - Sigstore transparency entry: 1340064978
- Sigstore integration time:
-
Permalink:
simonteague6/aloud-tts@27313b31ebd35b1a61286d96d9760a2bb9325d9b -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/simonteague6
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@27313b31ebd35b1a61286d96d9760a2bb9325d9b -
Trigger Event:
push
-
Statement type: