Add a book and ask it something#
Fifteen minutes, most of which is waiting for a chapter to be read aloud. By the end you will have a book rendering, an index you can search, and a page on your phone that plays it.
This assumes you have installed somnia and that
somnia search finds things.
Pick a book#
somnia reads Project Gutenberg. Search the local catalog for a Gutenberg id —
the gid is the only handle anything else uses:
$ somnia search "black beauty"
271 Black Beauty — Sewell, Anna
The page can do this too, once you have one: books › in the top left corner, then workshop › from its right-hand corner, reaches the same local catalog and queues what you press — and so does asking out loud. This is the same act by three routes, and all three end up in the same queue.
Render it#
$ somnia add 271
Black Beauty is next to be rendered.
2026-08-06 21:04:11 INFO rendering chapter 1/49: 01. My Early Home
2026-08-06 21:09:38 INFO rendering chapter 2/49: 02. The Hunt
...
This takes a while — Kokoro was measured at 3.87× realtime on the box somnia renders on and 1.06× on a 2-vCPU VPS, so a six-hour book is anywhere from ninety minutes to six hours depending on the machine — but you do not wait for it. Each chapter is written to the library folder and indexed the moment it finishes, so chapter one is listenable within a few minutes and the rest arrives while you sleep. The page will show you how far it has got, on that same Workshop screen.
Each chapter opens by saying which one it is — Chapter 2. The Hunt — so a boundary reached half asleep is a boundary rather than a skip. That line is built from the heading, not read off it: a numeral is turned into a number and a heading set in capitals is taken out of them, because both are read very badly aloud.
Leave it running in a tmux session. Better, run the worker as a unit and
never type this again: books are rendered one at a time from a queue, so
asking for one from a terminal, or by voice later, both come to the same place.
Keep a long render running has the unit,
and somnia queue shows you the line.
One rule: never re-render a book with a different voice. Every timestamp in the
database — chapter marks, index entries, the place you fell asleep — is tied to
the audio that was actually produced. Which voice a book is read in is chosen
when you ask for the book and not before: the page opens a picker on the add
press, with a sample of each, and somnia add --voice names one from a
terminal. There are six. A render that died is picked back up in
the voice it started in, so finishing one needs no decision at all.
Search what has been rendered#
$ somnia find 271 "the horse is beaten in the street"
[2:47h d=0.284] 32. A Horse Fair
A poor old brown horse was there... he was being beaten about the head
while the crowd looked on.
d is the distance — smaller is closer. Concrete events, characters and places
search well; atmosphere (“the bit that felt strange”) does not, and that is a
known limitation rather than a bug.
somnia find searches the whole book. The agent, in the next step, does not.
Ask it in words#
source ~/somnia.env
somnia ask "which chapter is the one with the horse fair?"
The key lives in ~/somnia.env rather than in the command, which keeps it out
of your shell history and out of ps — it is the same file the systemd units
read. Give no question and you get an interactive prompt; a blank line ends it.
The first thing you will probably see is the agent telling you that the passage is further on than you have got, and offering to take you there. That is the spoiler guard working. It bounds every search at the furthest point somnia has actually played — and from the command line, nothing has played anything, so the bound is the first minute of the book. Say yes and it will search the whole thing.
The guard is why the agent exists in this shape at all: a question at 2am must never be answered with something you have not heard yet.
Play it from your phone#
somnia serve
That serves the page, the agent behind it, and the book itself, on
127.0.0.1:8721. Leave it on localhost. There is no login of any kind; the
only thing protecting it is that nothing but tailscale serve can reach the
port. Publish it, and install it on the phone, by following
Serve the page that plays the book.
Once it is on your phone, a night looks like this:
The page opens the book you were last in, at the place you left it, and does not start it. Opening the app to ask a question is not the same as asking for the book.
Press play, then lock the phone. From there the book is driven from the lock screen, the notification and anything paired over Bluetooth.
Tap sleep to walk the timer through 15, 30, 45, 60 minutes and the end of the chapter. It counts listening time, so pausing to ask a question does not spend it, and it ends in a twenty-second fade.
Half asleep, hold the talk button and say “go back to where the horse gets hurt”. The book goes there and plays from there. There is nothing to press afterwards.