saynow
Speak text aloud from the terminal. Built so LLM agents can talk to you.
saynow "the build finished, 42 tests passed"
Works with no configuration — it falls back to your OS's built-in voice, which is offline, free, and needs no API key. Add a key for better audio.
Install
pip install saynow # or: uv tool install saynow
No third-party dependencies — standard library only. An identical npm package exists for Node; both read the same config file, so pick whichever runtime you already have.
Usage
saynow "text to speak" # speak an argument
echo "text" | saynow # speak stdin
pytest 2>&1 | tail -1 | saynow # speak a command's last line
saynow -p openai -v nova "hello" # pick a provider and voice
saynow --save note.mp3 "hello" # write a file instead of playing
| Provider | Quality | Needs |
|---|---|---|
system |
Fair | Nothing — built into the OS |
openai |
Good | OPENAI_API_KEY |
elevenlabs |
Best | ELEVENLABS_API_KEY |
openrouter |
Good | OPENROUTER_API_KEY |
If a cloud provider is configured but its key is missing, saynow warns on
stderr and speaks with the system voice anyway. Use --strict to opt out.
Concurrent calls are serialized so speech never overlaps.
Configure
saynow init # interactive setup
saynow config set provider openai
saynow voices # available voices
saynow models # OpenRouter models that can speak
Config lives at ~/.config/saynow/config.json, mode 0600. Precedence is
defaults → config file → environment → flags. API keys are never accepted as
flags, since argv is visible to ps and lands in shell history.
Use it from an agent
Add this to your CLAUDE.md, AGENTS.md, or equivalent:
You can speak to the user out loud with `saynow "<text>"`. Use it for things
worth interrupting for: a long task finishing, a question that blocks
progress, or an error that needs attention. Keep it to one short sentence —
it is spoken aloud, not read. Do not narrate routine progress.
Asking, and showing
--ask speaks, then waits: a bubble appears in the corner with the
transcript and a reply box, and whatever is typed comes back on stdout.
answer=$(saynow --from "billing · migration" --ask "Drop the old table?")
Exit 0 means they answered, 2 means they dismissed it or were away —
never read 2 as consent. --file report.md renders a Markdown document in
the same bubble: headings, tables, code, links and images, local or remote.
The bubble needs a window shell — Xcode command line tools on macOS, or any
Chromium-based browser. Without one saynow still speaks, --ask exits 2, and
--file is read aloud rather than shown.
Both builds read the same config file, so installing the npm one alongside this changes nothing you have already set up.
Claude Code users can install the plugin, which teaches Claude when to speak:
/plugin marketplace add dhruvyad/saynow
/plugin install saynow@saynow
Full reference
saynow --help # complete reference: every flag, setting, and exit code
License
MIT — source at https://github.com/dhruvyad/saynow
Metadata
Release files for saynow 0.13.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| saynow-0.13.0.tar.gz | 51.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| saynow-0.13.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 104.2 kB
Release files / saynow-0.13.0.tar.gz
| Download URL | saynow-0.13.0.tar.gz |
|---|---|
| Size | 51.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0ef852590b766970ea72b7cf6a9da09a4800cf55b07df6692e38df156d51e552
|
|
BLAKE2b-256 checksum How to use checksums |
60d216ab01e7a3b9a3d65cb9e47c2144bf5b5374bf056dc886e5942e5e8c953a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency logRelease files / saynow-0.13.0-py3-none-any.whl
| Download URL | saynow-0.13.0-py3-none-any.whl |
|---|---|
| Size | 52.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
edb1781ae4ae2dd0730e065b5c056b3e76a70c7b9e1f0d4d9840ff117e8af8f3
|
|
BLAKE2b-256 checksum How to use checksums |
41a399fe5fd9f7497a4cb7288a41571101319eeffd1a849dcfdc045ef3ce1f7b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency log