Skip to main content

Speak text aloud from the terminal. Built for LLM agents to talk to you, with offline system TTS when no API key is configured.

Project description

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 at all — it falls back to your operating system's built-in voice, which is offline, free, and needs no API key. Configure a cloud provider when you want it to sound good.

Status: not published to PyPI

The shipping build of saynow is the npm package. This Python port is a complete, working equivalent that lives in the repo but is deliberately unpublished — maintaining two implementations in lockstep is a cost worth paying only once someone actually needs the Python one.

The name is available on PyPI, so it can be published at any time. Open an issue if you want it.

Install from source

git clone https://github.com/dhruvyad/saynow
uv tool install ./saynow/python

No third-party dependencies — it uses only the standard library. Both builds read the same config file, so they are interchangeable on one machine.

Usage

saynow "text to speak"             # speak an argument
echo "text" | saynow               # speak stdin
pytest 2>&1 | tail -1 | saynow     # speak the last line of a command
Flag Meaning
-v, --voice <name> Voice to use — see saynow voices
-p, --provider <id> system, openai, or elevenlabs
-r, --rate <n> Words per minute (system provider)
-s, --speed <n> Playback speed 0.25–4.0 (cloud providers)
--save <file> Write audio to a file instead of playing it
--no-queue Speak immediately, overlapping in-flight speech
--strict Fail rather than falling back to the system voice
-q, --quiet Suppress warnings on stderr

Configuration

saynow init          # interactive setup
saynow config list   # show settings, API keys redacted
saynow config set provider openai

Config is stored at ~/.config/saynow/config.json with 0600 permissions. Precedence is defaults → config file → environment → flags.

API keys are never accepted as command-line flags — argv is visible in shell history and to ps.

Providers

Provider Quality Cost Needs
system Fair Free Nothing — built into the OS
openai Good Paid OPENAI_API_KEY
elevenlabs Best Paid ELEVENLABS_API_KEY

If a cloud provider is selected but no key is available, saynow warns on stderr and speaks with the system voice anyway. Pass --strict to opt out.

Using 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.

Concurrent invocations are serialized with a lock file, so three calls in a row produce three sentences rather than one muddle.

License

MIT — source at https://github.com/dhruvyad/saynow

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

saynow-0.1.0.tar.gz (9.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

saynow-0.1.0-py3-none-any.whl (11.6 kB view details)

Uploaded Python 3

File details

Details for the file saynow-0.1.0.tar.gz.

File metadata

  • Download URL: saynow-0.1.0.tar.gz
  • Upload date:
  • Size: 9.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for saynow-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2a15212e284eca70d95d0da65114cffa27c8b58b099d28b5436701cd562c5076
MD5 11b5c44dc9042614b1ac6bb2e5eb0118
BLAKE2b-256 84cdaf953dbce136eb512856de4994ddee91a0a82a870d20d1b3553b697913d1

See more details on using hashes here.

File details

Details for the file saynow-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: saynow-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for saynow-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fee87660310b437a53dbf5a1e1d1759ec6a0c5c20e3149e1cdd5ed5ab2ee0fb0
MD5 acc52eda03ad0874131acc75fe4a9e74
BLAKE2b-256 3839d14bbd55dea341345c865fa15dc2df78f022c232d5ae706e37e32ab59b7a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page