You are three hundred pages into a long novel, somebody walks into the room, and you have no idea who they are.
Every place you could look to find out will tell you something you haven't reached. A wiki article is written from the ending. A character list on a retail page names who survives to be worth naming. Searching the name finds a forum thread about what they do in the last act. So you either read on and stay lost, or you spoil the book to stop being lost — and a lot of people just put it down. That's the problem this is for.
The blurb was never going to save you. Measured over 113 fiction nominees from the 2025 Goodreads Choice Awards, a synopsis names a median of two people; over 53 novels measured whole, a book has introduced nineteen by a tenth of the way in and finishes with sixty.
It builds the book's cast as you read it, from your own copy, and shows you nothing past your bookmark.
Point it at a book you own. It reads the file, works out who appears in which chapter, and gives you an index with a bookmark on it. Move the bookmark to chapter 40 and you see the book as it stands at chapter 40 — who you have met, who you haven't seen for a while, who tends to be in the room with whom, where the book has been. Chapter 41 doesn't exist in the view.
The spoiler rule is structural, not a filter. Every view is built from the chapters behind your position, so there's no later data sitting in the page waiting to be revealed by a bug. That property is asserted by a test that runs on every commit.
Early days. It works on the sixteen books below and on any DRM-free epub you own. It's also convinced that Moby Dick is a place until you tell it otherwise, and nobody has read a whole book with it yet.
From a release — the .deb is on the releases page:
sudo apt install ./ariadne_*_all.debAs a Flatpak — the bundle is on the releases page beside the .deb:
flatpak install ./ariadne_0.1.0.flatpakOr build one yourself with make flatpak to install it locally, or make bundle for the single file.
Needs org.gnome.Platform//50 and org.gnome.Sdk//50. It asks for your home directory so you can browse to a book without going through the file portal every time. It asks for no network at all.
From a clone:
make venv && make installThis puts ariadne on your PATH and a launcher entry in your applications menu. make help lists everything else, and make uninstall removes all of it.
Pick one or the other.
make installputs a wrapper in~/bin, which on most setups comes before/usr/binonPATH— so with both present,ariadneis the wrapper and the packaged binary is never reached.which -a ariadnesettles it.
Python 3.12 or newer, and nothing else — the engine needs only the standard library, and tests/test_layering.py proves it by importing every engine module with the toolkit blocked.
The GTK parts come from your system rather than from pip, so they may not be there. Run:
ariadne --doctorIt says what is missing and gives you the command to install it. Everything else works fine without them — pages, --inspect, --about, --refusals, the whole command line.
ariadne ~/Books/some-book.epub --appOr open Ariadne from your applications menu and pick a book.
The window shows what the page shows, and here you can also correct it. When it lists Prince Andrew and Prince Andrew Bolkónski as two people, click one and tell it they are the same man. Notes, merges and warnings go into a small file of your own, and there are fifty steps of undo.
Across the top is the bookmark, and it is also the chapter axis. Every strip and band below it is drawn to that same scale, so a line dropped through your position lands on the same chapter everywhere on screen. Drag it, or click any chapter on any strip. [ and ] step one chapter; Ctrl+G, or the position in the title bar, jumps to one you type.
Down the left: the cast, where the book has been, a map of who shares chapters with whom, a pace chart, and your warnings. The cast has four cuts across the top of it — everyone, people, places, and the ones you have not seen for a while. Click any name and a panel opens with everything known about them so far, and nothing after.
It doesn't guess at any of this. Two names might be one person or they might be two, and in some books that's the plot.
In ~/.local/share/ariadne/books/, one small JSON file per book. ariadne --doctor prints the path and how many books are in it.
They used to live next to the book, and that broke on the books people actually own. A novel on a removable drive, on a read-only share, or opened through the Flatpak file portal — which hands over the one file you picked and nothing around it — is somewhere Ariadne cannot write. Every save failed quietly and the window said it had saved.
A book is found by what's in it, not where it is. The filename is the book's title and a hash of its contents, and only the hash decides which book it is. Divergent.epub, 01 - Divergent - Veronica Roth (2011).epub and [1] divergent_RETAIL.epub are one file with one set of rulings — move your library, rename a file, or copy it to another disk and they follow. The name comes from the book's own title rather than your filename, because a filename is a shelving convention and it changes; whatever name a book gets first is the one it keeps. Editing the book is a different matter: a re-download or a metadata change makes it a different file, and the old rulings stay under the old one.
If you already have a .ariadne.json next to a book, it's read once and moved into the store. Nothing is written next to your books again. --decisions PATH still puts one wherever you want it.
One row per place, chapters running left to right, in the order the book got to them. Reading down the list is reading the journey.
It isn't a map of the world and won't become one. Bald Hills and Thrushcross Grange aren't on any map, and there are two Ithacas. What this draws is where the book spends its time.
Each row starts as a guess. The guess is right about four times in five, so you keep or bin each one — Moby Dick is a whale.
How much of the chapter is dialogue, how many people are in it, how many names are new, and how long it runs. Move the cursor and all four move together, so you can see that chapter 140 was quiet and crowded at the same time.
They run on the same axis as the bookmark, so the lines stop where you are and the rest of the book is empty space you can see the size of.
There's no score anywhere on it. A slow chapter might be exactly what the author wanted.
ariadne ~/Books/some-book.epub -o some-book.htmlAn epub, a Word document, a folder of Markdown, or plain text. It takes about a second, even for War and Peace.
What comes out is one HTML file. No install, no account, nothing to sign up for, and it works offline. It contains no text from the book at all — names, counts and chapter numbers — so you can send it to a friend reading the same thing.
ariadne <file> --inspect # what it found, without writing anything
ariadne <file> --about # what you are in for, before you startOf 59 books tried, it handles 48. The other 11 it turns down and tells you why, usually because it can't work out where the chapters start.
It also won't tell you who is speaking a line of dialogue, decide whether something was written by a machine, match a book against other authors to guess who wrote it, or give a book a score.
ariadne --refusalsEach of those has a reason and a number behind it. Attributing dialogue, for instance, works on 6.6% of lines — which isn't a rough answer, it's a wrong one nine times out of ten.
ariadne book.epub --warn "24=someone does not make it through this chapter"At chapter 23 it says something is coming and keeps the text folded shut until you open it.
Ariadne finds none of these itself. Tagging books by what happens in them is a fight it has no business joining, and a false positive costs somebody a book they would have been fine with. The warning is yours, it sits in your own file, and you can hand it to someone else reading it.
src/ariadne/
core/ the refusal, the tunable numbers, the quoted-span pattern
ingest/ files in, chapters out
model/ chapters in, the index out — and the clipping every view uses
decisions/ the reader's own rulings, in a sidecar keyed to the book
position/ where the reader is
analysis/ what can be said about a book without spoiling it
ai/ the two commands that need an account
invariant.py the property that must never regress
render/ the page
app/ the desktop reader
cli/ the command line
Each layer may use the ones above it and none below. The engine is everything above render, and it runs on a machine with no GUI toolkit at all.
Neither of those is a promise in a file. tests/test_layering.py reads the imports, fails on a folder nobody declared, and imports the whole engine in a subprocess with GTK blocked.
- From nothing to reading without being lost — never used it. Install, point it at a book, and correct what it got wrong.
| Getting started | Install it, open a book, and what to do first |
| Why Ariadne exists | The problem it was built for, and what that decided |
| CONTRIBUTING.md | How to change it without breaking the one rule |
| SECURITY.md | What it reads, what leaves your machine, and what is still open |
| CHANGELOG.md | What changed |
MIT. See LICENSE.



