macOS
A real window with a real File menu. Open a document from disk, read the clipboard with a keystroke, and keep the whole thing running with the network unplugged.
- Requires
- macOS 11+
- Chips
- Apple silicon · Intel
- Format
- .dmg
- Version
- 1.0.0
One engine, six places to meet it. The web app needs nothing but a browser. The desktop and Android apps give it a home, a file menu and a share sheet. A headset gives it a room and a fixation point that finally stops moving. A watch gives it the one screen that was never too small for it. The extension turns the page you're already on into a stream. Nothing you read leaves your device in any of them.
Pick the one that matches where your reading actually piles up. Five of them share a lexicon, a motion grammar and a resolver, file for file — what differs is only how the text reaches them. The sixth is the watch, and it is the one to read the table about before you install it.
A real window with a real File menu. Open a document from disk, read the clipboard with a keystroke, and keep the whole thing running with the network unplugged.
The same desktop build, packaged as an installer or a single portable .exe you can carry on a stick and run without touching the registry.
Share an article to it from any app and it opens straight into the stream. One word at a time is what a phone screen was always best at — no line to track, no pinch to zoom.
The whole technique asks for a point that never moves. On a phone the point moves because your hand does. Ask for the room and everything else clears away, leaving one word pinned where you put it. If visual crowding is what stands between you and the page — it is measurably larger for many dyslexic readers — this is the least crowded presentation we know how to build. The evidence, honestly.
One word at a time is the only reading interface a watch face was ever big enough for. Send a passage across from your phone, then read it with the crown under your finger and the phone left behind.
The page you're already looking at, minus the furniture. It finds the article, throws away the nav and the newsletter box, and streams what's left.
Signed installers aren't up yet. The desktop, Android and Chrome builds are complete and run today — you build them from the source in this repository, and the commands are at the bottom of this page. Notarised Mac builds, a signed Windows installer and Play Store listing are the next thing after that.
The XR and Wear builds are new, and neither has been on a device. Both are complete in the repository — manifest, gradle, native source and a README each — and neither has been through a compiler, let alone onto a wrist or a head. Each one ships a table of what was checked against the platform documentation and what still needs real hardware to confirm. Treat them as source you can build, not as software somebody has already run.
Most of what anyone reads in a day arrives as a web page wrapped in forty other things. The extension's real work isn't streaming words — it's deciding which words on the page were the article, and being right about it.
Press Alt R, click the toolbar icon, or right-click the page. Select a passage first and it reads only that. Nothing runs on any page until you ask — the extension can't see a page it hasn't been pointed at.
Candidate blocks are scored on paragraph density, link density and the names their authors gave them — the same family of signals a reader-mode uses. Navigation, share bars, cookie walls and related-story rails score themselves out.
The text is handed to the reader in memory and deleted the instant it arrives. It is never written to disk and never sent anywhere. Close the tab and there is nothing left to delete.
On a normal page your eye skips the subscribe box without noticing. In a stream you can't skip anything — every stray word is shown to you, one at a time, and the thread of the argument breaks while it happens. So the extractor is tuned for precision over recall: it would rather drop a pull-quote than admit a newsletter form.
Some pages won't give it up — heavy single-page apps, PDFs rendered in canvas, sites that block extensions entirely. When the article scoring fails, it falls back to the visible text of the page and tells you that's what it did, rather than pretending.
Highlight anything and that's what streams. The fastest path through a long page is often to pick the four paragraphs you actually came for.
Structure is kept and punctuated so the stream pauses where a section starts, instead of running the heading into the first sentence.
Read a page without opening it. Access to that site is requested at the moment you click, and only for that site.
The popup shows the word count and what it'll cost you in minutes before you commit. Pace and pairing mode carry over from last time.
Open the stream in a new tab, or in a separate small window you can park beside the source.
Chrome forbids extensions from loading code at runtime, so the neural voice and PDF import can't run here. The system voice does. Both work in full on desktop and Android.
Five of the six run the identical resolver, lexicon and motion grammar — that part isn't a marketing claim, it's literally the same file, and the same hundreds of thousands of words resolve to a picture on every one of them. A coverage guarantee that only holds on the desktop is no guarantee at all to the reader who depends on it. The sixth is the watch: it runs Kotlin rather than a browser, so it runs a port instead — the tokenizer, the pacing and the fixation point crossed over, and the pictures did not. Everywhere else what changes is only what the host operating system permits. All of it is below, including the column with the most gaps in it.
| Capability | Web | macOS | Windows | Android | XR | Watch | Chrome |
|---|---|---|---|---|---|---|---|
| Icon pairing, all five resolver tiersCurated, compound, derived, library, procedural | |||||||
| All nine pairing modes and the motion grammar | |||||||
| Comprehension checks and session export | |||||||
| System voice | |||||||
| Neural voice — KittenTTSChrome forbids extensions loading code at runtime | |||||||
| PDF and DOCX importSame restriction — plain text and Markdown work everywhere | |||||||
| Reads the page you're on | |||||||
| Share sheet targetSend an article to it from any app | |||||||
| Native file menu and open dialog | |||||||
| Read the clipboard with one keystroke | |||||||
| Runs with the network offTier-4 library icons need one fetch each, then cache forever | |||||||
| Pins the stream to the roomFull Space — the fixation point stops moving because you stop moving it | |||||||
| Paced with a physical dialThe crown, in 25 wpm steps — the only platform here with one | |||||||
| Takes a passage from your phoneOver Bluetooth, between two devices you already paired — not a server | |||||||
| Account required | |||||||
| Bytes of your reading uploaded | zero | zero | zero | zero | zero | zero | zero |
This isn't a policy — a policy is a promise about what a company chooses not to do with data it holds. There is no company holding anything. There's no backend to send it to and no account to attach it to.
PDFs, contracts, coursework and web pages are parsed on the device that opened them. The desktop app reads from your disk; the extension reads from the tab you pointed it at; neither has anywhere to send the result. The watch is the only one that writes anything down, because a passage sent from your phone has to survive the app being closed — so it keeps exactly one, in private storage, with device backup switched off so that it cannot be copied to anybody's server on the way past.
When a word falls outside the curated set, the library tier asks an open icon API for a match. That request contains a single word — no sentence, no document, no URL, no identifier — and the answer is cached permanently. Turn it off and the procedural tier covers the gap.
No analytics, no crash reporting, no update pings, no accounts. Your speed and recall history lives in local storage on your own machine, and the export button hands it to you as a file rather than a dashboard.
Until the signed installers land, this is the honest path — and it stays the fastest one for anyone who'd rather read the source than trust a binary.
cd apps/desktop && npm install && npm run dist:mac — produces a .dmg for Apple silicon and Intel in dist/. Unsigned builds trip Gatekeeper on first launch; right-click → Open once.
cd apps/desktop && npm install && npm run dist:win — produces an NSIS installer and a portable .exe. Unsigned builds show a SmartScreen warning; More info → Run anyway.
cd apps/android && npm install && npm run sync && npm run build:debug — produces a debug APK. Android Studio and a JDK are the prerequisites; the README covers signing for the Play Store.
cd apps/androidxr && npm install && npm run sync && npm run build:debug — the Android path again, plus a Kotlin layer for Full Space. Needs an Android Studio Canary and the Android XR system image. minSdk is 34, so this APK deliberately will not install on a phone.
cd apps/wear && gradle wrapper --gradle-version 8.11.1 && ./gradlew assembleDebug — no Capacitor and no web payload; this one is native. An emulator is enough to read on, but the inbox needs a paired phone running the Android build.
cd extension && node scripts/sync-reader.mjs, then load the folder unpacked at chrome://extensions with developer mode on. No build step, no bundler, no dependencies.
Nothing to build. web/trainer.html is one self-contained file — open it from disk, or serve the folder with any static server. This is the version every other one wraps.
Every other platform here wastes almost all of its display: one word, one fixed point, darkness at the edges. That emptiness is what the technique costs. A watch face is the first screen where it stops being a cost, because there is no emptiness left to pay with — the word simply fills the thing.
The Wear OS build is the only one that is not the web app in a shell. A watch gives no guarantees about WebView, and bundling 58 MB of neural voice onto that battery would be absurd — so the reading engine was ported into Kotlin instead. Same tokenizer, same dwell multipliers, same fixation thresholds, with a table in the source mapping every constant back to the line of the web app it came from. What could not cross is the pictures, and that is the thing to know before you install it.
The app: reader, inbox, manifest, gradle and README, all of it in apps/wear. Plus a live watch-scale face on this site running the same delivery and rhythm, at the real 396 × 484 aspect.
Nothing here has been through a Kotlin compiler, and nobody has worn it. The README carries a table of what was checked against the platform documentation and what still needs a watch on an arm.
Icon pairing, both voices, document import, the Gym, comprehension checks. A 450px round face has room for a word or a picture — and shrinking the word to fit a glyph beside it would defeat the only reason to read on a wrist.
A watch cannot be typed into. The passage goes from the phone app over Bluetooth, between two devices you already paired, and once it has landed the phone can stay at home.
There is no always-on mode, deliberately. A stream that carries on into a dimmed screen is not reading, it is words you have already missed — so lowering your wrist is a pause.
If the rhythm cannot be read at 40mm at a glance, it gets abandoned rather than shipped quiet. That test needs hardware, and hardware is what it has not had.
The web app is the whole thing, running in the tab you already have open. Install one of the others when you know you want it in your day, rather than to find out.