A fullscreen EPUB reader for your terminal, with KOReader-compatible progress sync.
Read your books where you live: the terminal. Keep your place in sync with your Kobo, Kindle, or any KOReader device through kosync.eu, the official KOReader server, or your own.
| Reading Pride and Prejudice | Table of contents |
|---|---|
![]() |
![]() |
| Your library | Settings |
![]() |
![]() |
| Theme presets (gruvbox) | |
![]() |
Screenshots show public-domain books from Project Gutenberg.
π A proper reading experience β clean typography with configurable column width, full justification, and an ASCII-only mode; positions stay anchored to the word you were reading across any terminal resize.
π KOReader progress sync β the full kosync protocol: binary (partial-MD5) and filename document matching, xpointer β position mapping with percentage fallback, automatic pull on open with prompt/silent/disabled strategies in each direction, push on close and per-page-interval, a 25-second debounce, visible sync status, and a persistent offline queue that drains when you're back online.
π Credentials done right β only the derived userkey is stored, in your OS keyring (Secret Service / Keychain / Credential Manager). Never on disk, and redacted from logs.
π±οΈ Keyboard first, mouse complete β every menu is fully clickable with hover highlighting, while the reading surface itself stays distraction-free.
β‘ Fast libraries β recursive scanning with a metadata cache keyed by path/size/mtime; big collections open instantly after the first scan.
π οΈ Batteries included β first-run wizard, help overlay (?), NO_COLOR
support, self-update (terminalreader update), a doctor command that checks
everything from config to live server auth, and optional logging with secret
redaction.
Linux / macOS β installs the latest release to ~/.local/bin
(override with TR_INSTALL_DIR):
curl -fsSL https://raw.githubusercontent.com/Kardzhilov/TerminalReader/main/install.sh | shWindows (PowerShell) β installs to %LOCALAPPDATA%\Programs\TerminalReader
and adds it to your user PATH:
irm https://raw.githubusercontent.com/Kardzhilov/TerminalReader/main/install.ps1 | iexFrom source (Rust 1.85+; on Linux install libdbus-1-dev and pkg-config
first):
cargo install --path crates/tr-tuiPrefer manual installs? Grab an archive for Linux (x86_64/aarch64), macOS
(x86_64/aarch64), or Windows from the
latest release.
Releases are cut automatically on every push to main; a commit mentioning
MAJOR or MINOR bumps that component, anything else is a patch.
terminalreader # home screen (first run opens the setup wizard)
terminalreader read book.epub # open a book directly
terminalreader library DIR # list EPUBs under DIR
terminalreader addLibrary DIR # persist a library directory
terminalreader hash book.epub # print KOReader-compatible document hashes
terminalreader doctor [book] # verify config, state, keyring, and sync server
terminalreader update # self-update (--check to only check)| Context | Key | Action |
|---|---|---|
| Anywhere | ? / F1 |
Help overlay |
| Home | Enter / s / q |
Open selection / settings / quit |
| Reader | Space PgDn β |
Next page |
| Reader | PgUp β |
Previous page |
| Reader | [ / ] |
Previous / next chapter |
| Reader | t |
Table of contents (type to filter) |
| Reader | / then n / N |
Search the book, next / previous match |
| Reader | m / M |
Add a bookmark / open bookmarks |
| Reader | v, arrows, Enter |
Select visible text and copy it |
| Reader | s / p |
Push / pull sync progress now |
| Reader | x |
Toggle sync for this book |
| Reader | Esc / q |
Save position and go home / quit |
Reader keys are remappable in the [keys] section of config.toml.
Everything is also mouse-clickable, with hover highlighting; in the reader the
mouse can turn pages, scroll, open images and notes, and confirm external links.
Open Settings and use 1 through 5 to toggle line scrolling, wheel scrolling,
cycle the wheel step, toggle click-to-turn, and invert the page-turn halves.
The same values can be edited directly:
[navigation]
line_scroll = true
wheel_scroll = true
wheel_step = 3
click_to_turn = true
invert_click_zones = falseText selection uses OSC 52 clipboard writes. Terminal clipboard support must be enabled; terminal multiplexers such as tmux may require clipboard passthrough.
Open Settings (s), then:
uβ set the server (default:https://kosync.eu)lto log in, orrto register a new accountcβ pick the document matching method; binary (the KOReader default) syncs identical files, filename syncs by name. This must match your other devices.
| Key | Setting | What it does |
|---|---|---|
c |
Matching | How books are identified on the server: binary (identical file) or filename |
f |
Forward sync | When the server is ahead of you: prompt, silently jump, or ignore |
b |
Backward sync | When the server is behind you: prompt, silently jump, or ignore |
t |
Auto sync | Pull position on open, push on close and quit |
g |
Push every N pages | Also push mid-session after every N page turns |
e |
Push every N minutes | Also push mid-session on a timer |
n |
Device name | The name other devices see in pull prompts |
Automatic pushes are debounced (25 s) and coalesced per book. Failed pushes
are queued on disk and retried automatically β even across restarts. Press
x in the reader to exclude a single book from sync, or start with
--offline to disable all syncing for a run.
Press h in Settings to cycle through preset colorways: gruvbox,
gruvbox-light, dracula, nord, solarized, solarized-light, catppuccin,
tokyo-night, and one-dark. The custom preset uses the [theme] section of
config.toml instead:
[theme]
preset = "custom" # or any preset name above
accent = "green" # cyan, blue, green, magenta, red, yellow, white, or gray
light = true # adjust secondary colors for light terminal backgroundsSet the NO_COLOR environment variable to disable colors entirely.
| What | Where (Linux) |
|---|---|
| Config (TOML: library, reading, sync) | ~/.config/terminalreader/config.toml |
| State (positions, recents, cache, queue) | ~/.local/state/terminalreader/ |
| Credentials (userkey only) | OS keyring |
Logs (opt-in via --log-file/config) |
wherever you point them |
macOS and Windows use the equivalent platform directories.
cargo test --workspace # unit tests
cargo clippy --workspace --all-targets -- -D warnings # lints (pedantic)
cargo +nightly fuzz run epub_open # fuzz the EPUB parser
cargo +nightly fuzz run chapter_parse # fuzz the chapter XHTML parser
cargo +nightly fuzz run xpointer_parse # fuzz progress stringsLive server round-trip tests (opt-in, never run in CI):
TR_SYNC_TEST_SERVER=https://kosync.eu \
TR_SYNC_TEST_USER=user TR_SYNC_TEST_PASSWORD=pass \
cargo test -p tr-kosync --test live -- --ignoredRegenerate the README screenshots (uses vhs and public-domain EPUBs):
cargo build --release -p terminalreader
sh docs/make-demo-library.sh
vhs docs/demo.tapeManual verification checklist (Linux/macOS)
- First run shows the wizard; Enter adds the directory, Esc skips, and the wizard does not reappear on the next start
- Library scan is fast on the second open (scan cache hit); touching an
EPUB (
touch book.epub) rescans only that file - Reading preferences: max width caps the column,
jjustifies,mswitches rules/image boxes to ASCII; all persist across restarts - Resize the terminal while reading: the top-of-screen word stays anchored, below 60Γ16 the resize notice appears and recovery is clean
-
NO_COLOR=1 terminalreaderrenders without color -
?/F1shows the help overlay on every screen; any key closes it -
--log-filewrites logs and never contains the userkey/password - Doctor reports config, libraries, keyring, queue, and server auth
Sync interoperability checklist (real server + KOReader device)
- Register + login against kosync.eu (or self-hosted) from Settings
-
terminalreader hash book.epubmatches the document id shown by the server dashboard / KOReader for the identical file - Read on a KOReader device, push, then open the same book here: the pull prompt appears with the device name and jumps to the right paragraph
- Read here, quit, then open on the KOReader device: KOReader offers the forward position
- Disable networking, turn pages, quit: queue persists; next start with network, the queue drains (doctor shows 0 pending)
- KOReader for the sync protocol and inspiration
- kosync.eu for the free community sync server
- Project Gutenberg for the public-domain books in the screenshots
- ratatui for the TUI framework





