Skip to content
ildellaPublic

Repository files navigation

Say It

CI Linux

Private, local text-to-speech. Say It turns copied text into speech with open models running entirely on your machine — your text and generated audio never leave your computer.

This is a Linux-first port of callebtc/sayit (macOS / Apple silicon). It keeps the original architecture and CLI while replacing Apple-specific layers with Tauri, Svelte, and kokoro-js.

Say It desktop app — Speak tab

Linux (X11 and Wayland) is built and tested. Windows CI builds an experimental MSI (needs Node and mpv on the machine; playback is not a full Windows port).

On macOS, use the original. This is the Linux port. If you want voice on Apple silicon, install callebtc/sayit — the app Calle wrote for it. This repo can compile the shell on macOS, but it is not the macOS voice experience and does not replace it. That is by design, not a gap waiting to be filled.

Highlights

  • Speak from anywhere. Copy text and press the clipboard hotkey (Ctrl+Alt+V on X11), or bind sayit-clipboard as a custom shortcut in your desktop environment — the reliable path on Wayland.
  • A desktop player. Tray window to speak, pause, seek, change playback speed, and revisit history without leaving your current app.
  • Open models. Download supported Kokoro-82M weights in the app or CLI (kokoro-q8 ~90 MB, or kokoro-q4). Speak never downloads on its own.
  • Efficient model loading. Only one model is kept in memory, and it is unloaded after a configurable idle period (ten minutes by default).
  • Local by design. Synthesis works offline after model download. There is no analytics, cloud inference, or passive clipboard monitoring.
  • Hear your coding agent work. The bundled Say It agent skill provides live, hands-free spoken progress updates while an agent works.

Install

Omarchy

Say It is in review for the Omarchy package repository — omacom/omarchy-pkgs#813. Once it is merged:

omarchy pkg add sayit-bin

One package, everything in it: the desktop app (launcher and tray), the sayit CLI, sayit-clipboard, and the agent skill. Updates come through pacman. Until it lands, a 👍 on the PR helps it get reviewed. For the clipboard hotkey, bind sayit-clipboard to a Hyprland shortcut — Wayland blocks in-app global shortcuts.

All other Linux

CLI (terminal only, no window). Needs Node ≥ 20, npm, and mpv (aplay is a limited fallback); clipboard tools (wl-paste, xclip, or xsel) only if you want the hotkey.

curl -fsSL https://raw.githubusercontent.com/ildella/sayit/master/scripts/install.sh | bash -s -- --systemd

Add ~/.local/bin to your PATH. Omit --systemd to start the daemon once without enabling it, or use bash scripts/install.sh --systemd from a clone.

Desktop. Download from Releases, then:

sudo apt install ./SayIt_*_amd64.deb              # Debian/Ubuntu
sudo rpm -Uvh SayIt-*.x86_64.rpm                  # Fedora/openSUSE
chmod +x SayIt_*.AppImage && ./SayIt_*.AppImage   # anywhere, no sudo

All three embed the sidecar, the sayit CLI, sayit-clipboard, the agent skill and the licence; they need Node ≥ 20 and mpv (the .deb/.rpm declare both). The window binary is sayit-desktop; installing the package also puts sayit and sayit-clipboard on your PATH. It does not replace an existing CLI install — whoever starts first owns port 7878, the other connects. Tags also publish an experimental Windows MSI (same Node + mpv requirement; not a full Windows port).

Auto-update (Settings → Check for updates) covers the AppImage and the MSI. .deb / .rpm belong to your package manager, so Settings points you there instead of showing a broken update button.

First run

Download a model once (after that the app stays offline) and speak:

sayit models install kokoro-q8 --use
sayit "Hello from Say It"

Or copy text and run sayit-clipboard (bind it as a desktop shortcut). Speak returns an error until a catalog model is installed and selected.

Usage

Terminal

The install includes a sayit CLI for speech, playback, models, and automation:

sayit "Read this aloud"
printf 'Read standard input' | sayit
sayit status
sayit pause
sayit resume
sayit volume 0          # silence; 1 = normal, 2 = boost
sayit service status
sayit skill path

Run sayit --help for all commands. The CLI talks to the sidecar on 127.0.0.1:7878. If the daemon is down: sayit service start (or systemctl --user start sayit after --systemd).

Coding-agent voice mode

After install:

sayit skill install

That copies SKILL.md to ~/.agents/skills/sayit/ (OpenCode and other agents that read that directory). Then tell the agent:

Load the Say It skill and use it for live spoken updates.

Claude Code (if you use it instead):

mkdir -p ~/.claude/skills/sayit
cp "$(sayit skill path)" ~/.claude/skills/sayit/SKILL.md

Re-run sayit skill install after upgrading Say It. The sidecar must be running and a model installed before speech works.

Wayland vs X11

In-app global shortcuts (Ctrl+Alt+V) work on X11. Wayland compositors block them — bind a custom shortcut in your desktop settings to sayit-clipboard (installed next to the CLI). There is no cross-compositor API for another app's selection (not clipboard); on X11 you can point sayit-clipboard at xclip -o (PRIMARY) instead.

NVIDIA on Wayland. WebKitGTK's DMA-BUF renderer crashes there with "Error 71 (Protocol error) dispatching to Wayland display". Say It detects an NVIDIA GPU and disables that renderer automatically; if another setup hits the same error, set WEBKIT_DISABLE_DMABUF_RENDERER=1 yourself.

Build from source

Contributors: live UI. The end-user GUI package is the AppImage.

You need Rust and Tauri's prerequisites as well as Node ≥ 20 and mpv.

git clone https://github.com/ildella/sayit.git && cd sayit
npm run setup              # sidecar + CLI into ~/.local (same as install.sh)
npm install                # @tauri-apps/cli
npm --prefix app install   # SvelteKit UI
npm run dev                # live UI (developer loop, not a distribution)

If a daemon is already listening on port 7878, Tauri connects to it instead of spawning a second one.

npm run build:appimage     # AppImage with sidecar inside (Linux CI)
npm run build:linux        # .deb (optional)
npm run build:msi          # MSI with sidecar inside (Windows CI; Windows host)
npm run build:ci           # compile the shell, skip installers (on-demand macOS CI)

After pulling updates, re-run npm run setup and restart the service so a CLI install is not talking to a stale sidecar.

Architecture

The SvelteKit frontend (in a Tauri v2 tray shell) is separate from a per-user Node sidecar that owns model downloads, synthesis, playback, and history. The app, CLI, and sayit-clipboard talk to that service over a token-protected REST + SSE API bound to 127.0.0.1:7878. There is no Python; synthesis is Kokoro-82M via kokoro-js / onnxruntime-node (CPU).

┌──────────────┐   REST + SSE, Bearer token   ┌──────────────────┐
│ Tauri v2 app │ ◄──────────────────────────► │ sidecar (Node)   │
│ SvelteKit UI │                              │ kokoro-js engine │
│ sayit CLI    │ ◄──────────────────────────► │ mpv playback     │
│ sayit-clipboard                            │ history, models  │
└──────────────┘                              └──────────────────┘

How the port maps onto the original (XPC → loopback HTTP, MLX → kokoro-js, selection → clipboard), filesystem layout, and invariants are in LINUX.md.

Acknowledgments

Say It was created by callebtc as a privacy-first macOS app. This project exists thanks to his generosity in releasing it under MIT. For the original Apple-silicon experience (MLX Audio, voice cloning, Voice Studio), use callebtc/sayit.

License

MIT, like the original. Models are distributed under their own licenses. Only synthesize voices you have the right to use.

Releases

Used by

Contributors

Languages