Skip to main content

Soliloquy

PyPI version Python License: MIT PyPI downloads

A text-to-speech MCP server powered by Kokoro — gives Claude Code a voice.

One command to install. No config, no API keys, no cloud.

Why Soliloquy?

Cloud TTS (ElevenLabs, OpenAI, etc.) Soliloquy
Privacy Text sent to third-party servers Runs entirely on your machine
Cost $0.18-15/1M chars Free forever
Offline No Yes
Usage Limits Quotas / rate limits Unlimited
Latency 200-500ms (network) ~50-100ms (local)
AI Integration Developer calls API from code AI agent decides when to speak
Setup API keys + billing One command, no config

What You Can Do

Once installed, just talk to Claude naturally:

  • "turn on auto speak" — automatically voice conversational responses
  • "read this file aloud" — listen to docs, chapters, or articles (text, markdown, PDF, EPUB)
  • "read this book" — EPUBs are treated as audiobooks: chapters announced, resume on next call
  • "pick up where we left off" — resume any book you've started
  • "jump to chapter 5" / "read the preface" / "next chapter" — navigate around
  • "speak aloud" — voice a specific response
  • "stop" — stop audio playback

Auto-Speak

The flagship feature. Auto-speak voices every Claude conversational response automatically using a background hook — no tool call needed, zero token overhead. It just works.

"Turn on auto speak"

From that point on, everything Claude says, you hear. Toggle it off just as easily:

"Turn off auto speak"

When you use read_aloud or speak explicitly, auto-speak steps aside and lets the explicit playback finish.

Speech Normalization

Soliloquy doesn't just read text literally — it understands what sounds natural:

  • Code blocks become "See the code below" instead of reading syntax aloud
  • Tables are summarized ("There's a table here with 5 rows")
  • Symbols are spoken naturally (arrows become "to", URLs are simplified)
  • Lists are enumerated ("First... Second... Third...")
  • Paragraph breaks produce natural pauses between sections

Technical content and markdown-heavy responses sound like a person reading them to you, not a robot parsing characters.

Audiobook Mode (Beta)

🧪 Beta feature. Works well on cleanly-authored EPUBs (O'Reilly, Manning, Standard Ebooks, most professional publishers). EPUB tagging varies wildly in the wild — please open an issue if a specific EPUB misclassifies chapters or sounds wrong.

Pass an EPUB to read_aloud and Soliloquy treats it as an audiobook. Each chapter is announced by its title, frontmatter (cover, preface, "About the Author") is skipped by default, and playback resumes from where you left off on the next call.

pip install 'soliloquy-tts[epub]'      # EPUB only
pip install 'soliloquy-tts[documents]' # PDF + EPUB

Talk to Claude naturally:

You say… What happens
"Read this book" Starts a fresh book, or resumes if you've read it before
"What chapters are in this book?" Shows the table of contents
"Where am I?" Reports your current chapter and progress
"Jump to chapter 5" Skip to that chapter (chapter=5)
"Read 'The Forest'" Match a chapter by its title (chapter="The Forest")
"Next chapter" / "previous chapter" Move ±1 chapter
"Restart this chapter" Replay from the chapter's first sentence
"Start over" Wipe the bookmark and restart from chapter 1
"Show me the frontmatter too" Include cover, preface, etc. (include_frontmatter=True)

How resume works

Bookmarks live as JSON files under ~/.soliloquy/library/, keyed by the SHA256 content hash of the source file. A book moved to a new folder keeps its place; two identical copies share one bookmark. Atomic writes (tempfile + rename) mean a crash mid-write can never corrupt your position.

The bookmark layer uses a hybrid update strategy that tracks actual audio playback — not synthesis-ahead. Your position is saved every few audio chunks during playback and again on stop, so resume replays at most one short batch of audio. You'll never skip ahead and miss content.

Smart frontmatter detection

Four cascading signals identify cover, dedication, preface, appendix, index, and similar non-body content:

  1. EPUB3 nav doc entries marked epub:type="frontmatter|backmatter"
  2. Spine entries with linear="no"
  3. Spine idrefs starting with semantic names (cover, titlepage, preface, appendix, ...)
  4. Chapter titles matching frontmatter patterns ("Preface", "Index", "Appendix A: …")

Professional publishers tag spine entries cleanly — heuristics handle them well. Hobby or scraped EPUBs sometimes mislabel title pages or backmatter as body chapters. When that happens, pass include_frontmatter=True to play everything in spine order, or use chapter="<title>" to jump straight to the right content by name.

Known limitations

  • EPUB only. PDF and text files read as one-shot only — page-level book mode for PDFs is a future iteration.
  • Chapter numbers aren't spoken. The internal chapter index is the EPUB spine position (an implementation detail), not the "story chapter N" a reader would recognize. Only the title is announced. The index is still used for navigation (chapter=5, bookmark_status, etc.).
  • No multi-language detection. All chapters use the configured lang.

For non-book use cases, read_aloud still works as a one-shot reader for .txt, .md, and .pdf files (PDFs require the [pdf] extra).

Requirements

  • macOS, Windows, or Linux
  • Python 3.10+
  • PortAudio (audio output library)
Platform Install PortAudio
macOS brew install portaudio
Windows Bundled with sounddevice (no action needed)
Linux sudo apt install libportaudio2

Note: First install downloads ~2GB of dependencies (PyTorch, model weights). First run also downloads the Kokoro-82M model from HuggingFace.

Optional: PDF and EPUB support

To read PDFs and EPUBs (including audiobook-mode resume on EPUBs), install the document extras:

pip install 'soliloquy-tts[documents]'   # both PDF and EPUB
pip install 'soliloquy-tts[pdf]'         # PDF only
pip install 'soliloquy-tts[epub]'        # EPUB only

With uvx, replace soliloquy-tts in your setup command (e.g. uvx 'soliloquy-tts[documents]').

Optional: macOS Menu Bar Control

On macOS, you can install rumps for a menu bar icon that lets you stop playback instantly — no need to go through Claude Code:

pip install rumps

Without it, everything still works — you just use the stop command through Claude Code instead.

Quick Start

Make sure PortAudio is installed (see above), then:

uvx soliloquy-tts

That's it. This registers the MCP server, configures auto-speak, and sets everything up. Restart Claude Code afterward and you're good to go.

Requires uv. Install it with brew install uv (macOS), sudo apt install uv (Linux), or see the uv docs.

What happens when you run it

  1. Registers Soliloquy as an MCP server with Claude Code
  2. Writes a hook script for automatic voicing
  3. Configures the Claude Code Stop hook

You only need to do this once. After that, Claude Code starts Soliloquy automatically in the background whenever you open a session.

With pip

pip install soliloquy-tts
soliloquy

Same setup flow. Run soliloquy from your terminal and it handles the rest.

How It Works

Soliloquy uses a hybrid architecture to share a single model across multiple Claude Code sessions:

  • First session loads the Kokoro model and starts a local backend server
  • Additional sessions detect the running backend and connect as lightweight proxies (near-instant startup, no extra memory)
  • If the backend exits, the next session automatically takes over

This is completely transparent — no configuration needed.

Reference

Tools

speak — Synthesize and play text aloud.

Parameter Default Description
text (required) Text to speak
voice af_heart Voice ID
speed 1.0 Speed multiplier (0.5 - 2.0)
lang en-us Language code

read_aloud — Read a file aloud directly. Supports plain text, markdown, PDF (with [pdf]), and EPUB (with [epub]). EPUBs become audiobooks by default.

Parameter Default Description
path (required) Path to the file to read
voice af_heart Voice ID
speed 1.0 Speed multiplier (0.5 - 2.0)
lang en-us Language code
pages (none) PDF page range, e.g. "1-3" or "5"
chapter (none) EPUB navigation: integer, title substring, "next", "prev"
restart False EPUB: start at chapter 1, reset bookmark
restart_chapter False EPUB: restart current chapter from the beginning
as_book (auto) Force book mode on/off (default: on for EPUB, off otherwise)
include_frontmatter False EPUB: include cover, preface, etc. in playback

bookmark_status — Show your current position in a book.

list_chapters — Show the table of contents for an EPUB. Pass include_frontmatter=True to also list cover, preface, etc.

stop — Stop audio playback immediately.

auto_speak — Toggle automatic voicing on or off.

list_voices — List all available voices.

Voices

28 voices across American and British English. Default is af_heart.

View all voices
Voice Accent Gender
af_heartAmericanFemale
af_alloyAmericanFemale
af_aoedeAmericanFemale
af_bellaAmericanFemale
af_jessicaAmericanFemale
af_koreAmericanFemale
af_nicoleAmericanFemale
af_novaAmericanFemale
af_riverAmericanFemale
af_sarahAmericanFemale
af_skyAmericanFemale
am_adamAmericanMale
am_echoAmericanMale
am_ericAmericanMale
am_fenrirAmericanMale
am_liamAmericanMale
am_michaelAmericanMale
am_onyxAmericanMale
am_puckAmericanMale
am_santaAmericanMale
bf_aliceBritishFemale
bf_emmaBritishFemale
bf_isabellaBritishFemale
bf_lilyBritishFemale
bm_danielBritishMale
bm_fableBritishMale
bm_georgeBritishMale
bm_lewisBritishMale

Languages

en-us (default), en-gb, ja, zh, es, fr, hi, it, pt-br

Library Usage (StreamingSession)

Soliloquy can also be used as a Python library for streaming TTS — no MCP server needed. Push text as it arrives (from an LLM, WebSocket, etc.) and Soliloquy handles buffering, batching, and gapless playback.

from soliloquy.streaming import StreamingSession

session = StreamingSession(voice="af_heart", speed=1.0)

# Push text as it arrives
session.push("Here's the first sentence.")
session.push("And here's another one.")
session.push("The model is still generating...")

# Signal end of input — flushes remaining text and waits for audio
session.finish()

# Or cancel immediately
session.stop()

StreamingSession adapts batch size to audio buffer health — synthesizing immediately when the buffer is low, and batching efficiently when it's healthy. All the same speech normalization, adaptive chunking, and gapless playback from the MCP tools, with a simple push-based API.

Uninstall

soliloquy --uninstall

This removes the MCP server registration, auto-speak hook, and all config files. Works with uvx soliloquy-tts --uninstall too.

Development

git clone https://gitlab.com/bw-stovall/soliloquy.git
cd soliloquy
python3.11 -m venv .venv
source .venv/bin/activate
pip install -e .[dev,pdf,epub]
pytest tests/ -v

License

MIT

Release files for soliloquy-tts 0.9.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for soliloquy-tts 0.9.1
File Size Uploaded
soliloquy_tts-0.9.1.tar.gz 82.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for soliloquy-tts 0.9.1
File Interpreter ABI Platform
soliloquy_tts-0.9.1-py3-none-any.whl Python 3 none any Details

Total release size: 128.6 kB

Release files / soliloquy_tts-0.9.1.tar.gz

Download URL soliloquy_tts-0.9.1.tar.gz
Size 82.1 kB
Tags Source
SHA-256 checksum
How to use checksums
a3d3334b801371943ad051342ce2f5bc1a3a909573e372bb88a693546ced9c89
BLAKE2b-256 checksum
How to use checksums
c3374c53f91639689456431e653d1ab040ca4e27b1d197cac0500c75bd1b962e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / soliloquy_tts-0.9.1-py3-none-any.whl

Download URL soliloquy_tts-0.9.1-py3-none-any.whl
Size 46.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ca1d164fe30d523a8e65d5dbc43a632fb8b30c4f2ef0b32566a82bf1c4e0f369
BLAKE2b-256 checksum
How to use checksums
bbb81a282e12cde9536738c388ea9ec96f2aec45d4611923e8076c9a98ae297f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

1.0.0

2 release files

This release

0.9.1 This release

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.3

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page