Files
bookorbit/koreader-plugin
neon 1e5fcedb2a fix(koreader): stop a rebuilt library silently dropping reading history
Deleting a library cascades away its books, files, page stats and reading sessions, and a rescan
mints new rows. The device's sync state is keyed by the file's partial md5, so an unchanged file
kept its cursors across that swap: the plugin asked only for events newer than a watermark earned
against rows the server no longer had, and nothing recorded before the swap was ever resent.
"Recheck all book matches" did not help, because it funnels back through setMatched.

Treat a changed book file id or book id as a fresh sync target and keep only the local file path.
Both ids matter: statistics hang off the file row while highlights, status, rating and review hang
off the book row, and an existing-folder merge re-parents a file to another book without changing
its id. Resending costs nothing because the page-stat dedup key makes a replay a server-side no-op.

Order both hash resolvers by book file id so content that exists as two files always resolves to
the same row. They previously took whichever row Postgres returned first, so they could disagree
with each other and, with the reset above, move a device's sync target under it.

Closes #1049
2026-08-21 16:38:51 +00:00
..

BookOrbit Sync plugin for KOReader

Syncs your KOReader reading life into BookOrbit:

  • Catalog browsing: a reading-first dashboard on the device with libraries, collections, SmartScopes, authors, series and search, built from four configurable sections you choose the sources of. Mosaic or list view, read-status/format filters, downloads and bulk downloads, "On device" indicators, and a "Read" action for books already on the device.
  • Progress sync: pulls progress on book open (with a conflict prompt), pushes periodically and on close/suspend.
  • Reading statistics: uploads KOReader's per-page time events; BookOrbit turns them into reading sessions and daily stats.
  • Two-way highlights: device highlights appear as native highlights on the web reader; highlights, edits and deletions made on the web come back to the device.
  • Status & ratings: reading/complete/abandoned status and star ratings sync both ways, newest-change-wins.

Only books BookOrbit already knows about are synced, matched by the same partial-MD5 file hash KOReader uses internally. Unmatched books on the device are re-checked automatically as your library changes.

  1. In BookOrbit web settings: Settings > KOReader, create sync credentials (KOReader sync permission required on your account).
  2. Click "Download preconfigured plugin". The zip embeds your server address and credentials.
  3. Unzip and copy bookorbit.koplugin/ into koreader/plugins/ on your device.
  4. Restart KOReader. The plugin configures itself on startup and removes the embedded credentials file.

Re-downloading later (e.g. after changing your password or server address) and reinstalling applies the new config, even over an existing login. Each download carries a generation stamp, so replaying an old zip after logging out won't log you back in.

Install (manual)

  1. Copy bookorbit.koplugin/ from the repository into koreader/plugins/ on your device.
  2. Restart KOReader.
  3. In BookOrbit web settings: Settings > KOReader, create sync credentials.
  4. On the device: Tools > BookOrbit (sits below Calibre) - set the server address, log in, and use "Open dashboard" to browse/download books.

Setup

  1. Tools > BookOrbit > "Auto sync current book" to sync the open book automatically. Leave the stock "Progress sync" plugin unconfigured to avoid double syncing.
  2. Optional: Settings > Sync > "Periodically sync every # pages" (default 10, 0 disables mid-session pushes).
  3. Optional: Settings > Dashboard > "Open dashboard on startup".
  4. Optional: Settings > Dashboard > Section 1-4 - pick each dashboard section's source: Stats, Continue reading, Discover, Browse, Highlight of the day, Recently added, In progress, Want to read, Up next in series, or a pick from the Libraries/Authors/Series/Collections/SmartScopes catalogs. Want to read and Up next in series need a server new enough to advertise the section capability; against an older server they render empty and stop being offered. "Tap Continue reading to open the book" (on by default) resumes an on-device book in one tap; hold for its actions.
  5. Optional: assign "BookOrbit: sync this book" / "sync all books" to gestures.

The plugin manages settings/reader_menu_order.lua and settings/filemanager_menu_order.lua to keep its menu entry pinned below Calibre across updates; delete those files to reset your menu order.

From the dashboard menu, the plugin update check is top-level; from the Tools menu, it lives under Settings > Plugin.

How syncing works

  • With auto sync on: progress pulls on open (with conflict prompts), pushes every N page turns (debounced, skipped offline), and the whole book state (progress, highlights, status, rating, reading time) uploads from live memory on close and suspend.
  • "Sync current book now": checks BookOrbit for newer progress first, then does the same snapshot on demand.
  • "Sync all books now" (manual only): a full-library sweep - matches new books, then uploads reading time, highlights, statuses and progress for everything.
  • Everything is incremental and resumable: watermarks, modification-time checks and change detection mean an interrupted sync just resumes, and resends are server-side no-ops.
  • Plugin state lives in settings/bookorbit_sync_state.lua. Deleting it is safe: the next sync re-uploads everything and the server deduplicates.

A first sync on a device with years of history uploads in batches of 500 events (roughly 400 requests per 200k events, a few minutes of background work), and is safe to interrupt.

Two-way highlight and bookmark sync

Requires server 0.4+; against an older server the plugin falls back to upload-only automatically. Bookmark sync additionally requires a server that advertises the bookmarkSync capability; on an older one the bookmark paths stay dormant and highlights sync exactly as before.

  • Device to web: highlight positions (crengine xpointers) convert to reader CFIs, verified against the highlighted text, so they render as native, editable highlights on the web.
  • Web to device: applied on book open (with auto sync on), on manual sync, and during the full sweep for closed books, with positions re-verified/re-anchored against the text.
  • Deletions go both ways through a trash/restore flow, so nothing is lost outright.
  • Identity is the highlight's creation datetime plus position, so extending a highlight on the device is recognized as a move, not a delete-and-recreate.
  • Styles map across formats (e.g. squiggly <-> underline, invert, named colors <-> hex).
  • Toggle via Settings > Sync > "Two-way highlights & bookmarks" (uploads keep working either way).

Position-only bookmarks (dogears) sync the same way:

  • Device to web: the dogear xpointer converts to a reader CFI and shows up in the web reader's bookmark list. Its title is the note you attached, else the chapter, else the page.
  • Web to device: applied on book open, on manual sync, and during the full sweep for closed books. The position is only placed when it resolves; an entry that does not is retried on the next exchange.
  • Deletions and device-side renames propagate; the web has no rename surface yet, so edits flow device to web only.
  • A dogear has no highlighted text to re-anchor against, so a converted position can sit slightly off where a highlight would have been repaired exactly.

Limitations

  • Web highlight changes reach a closed book only via a manual sweep or its next open.
  • Web-created PDF highlights aren't supported (device PDF highlights sync up but aren't drawn over the PDF).
  • Books with reading stats but no sidecar path sync reading time only, until the full sweep covers them.
  • PDF bookmarks don't sync in either direction (the web has no PDF bookmark surface).
  • A device clock far in the past can delay edit detection for web-modified highlights.
  • The full sweep is manual-only; books you never reopen only sync when you run it.
  • A cloned device with a different KOReader device_id double-counts reading time; clones keeping the same device_id deduplicate naturally.