- Identity: applied entries carry bookhoard_dedup_key (served by the server) and echo it back in pushes, so a pull→push cycle updates the original server row instead of minting a duplicate (device locators never matched web locators under the computed key — every round-trip duplicated every annotation). Matching in applyServerAnnotations is key-first; a keyed entry that is absent is genuinely new, so pos0 fallback applies to legacy keyless entries only — a different annotation that merely shares a position can no longer be updated or, for tombstones, cross-deleted (demonstrated: a deleted duplicate's tombstone used to pos0-match a live highlight sharing the spot and remove it). Tombstone matching is likewise key-only for keyed entries; legacy pos0 fallback is restricted to the same annotation kind. - Classification (v2): the drawer field is the only reliable highlight discriminator — KOReader auto-fills text="in Chapter X" on page bookmarks, so text-presence turned every echoed bookmark into a junk highlight on the web. Bookmarks now take their label from note. - Colors: no color is imposed on applied entries; devices render their own default. The web color only changes when the user edits the highlight on the device (the edit sets a device color name, which the server maps and stores).
Bookhoard KOReader Plugin
Sync your reading progress, bookmarks, highlights, and notes between KOReader and your Bookhoard server.
Features
- Reading progress sync — push/pull progress across all your KOReader devices
- Annotation sync — bookmarks, highlights, and notes
- In-plugin device registration — no need to type long tokens on an e-ink screen
- Configurable sync behavior — silent, prompt, or disable for forward/backward progress
- OPDS catalog helper — quickly set up wireless book browsing/downloading
- Offline tolerant — syncs when connectivity is available
Requirements
- KOReader 2024.01 or later
- A running Bookhoard server accessible from your device (local network or public URL)
Installation
Copy the bookhoard.koplugin/ directory into KOReader's plugin folder on your device:
Kindle:
/mnt/us/koreader/plugins/bookhoard.koplugin/
Kobo:
/.adds/koreader/plugins/bookhoard.koplugin/
PocketBook:
/applications/koreader/plugins/bookhoard.koplugin/
Alternatively, clone this repo directly into the plugins directory:
git clone <repo-url> /path/to/koreader/plugins/bookhoard.koplugin
Restart KOReader after installation.
Setup
1. Configure server URL
Open KOReader → menu (≡) → Tools → Bookhoard sync → Server URL
Enter your Bookhoard server address (e.g. http://192.168.1.100:8765).
2. Register your device
Tap Register device in the plugin menu. The plugin will display an approval URL. Open that URL on your phone or computer, log in to Bookhoard, and approve the device. The plugin polls automatically and completes registration within a few seconds of approval.
3. Enable auto sync (optional)
Toggle Automatically keep documents in sync in the plugin menu. This will sync progress on page turns, document close, suspend/resume, and network changes.
Note: On most devices, you should set Network → Action when Wi-Fi is off to turn on for auto sync to work without constant WiFi prompts.
Usage
Reading progress
Progress syncs automatically when auto sync is enabled. You can also manually:
- Push progress — upload your current position to the server
- Pull progress — download the latest position from the server
- Sync now — push and pull in one action
Annotations
Bookmarks, highlights, and notes are synced when you close a document. Enable/disable each type in What to sync in the plugin menu.
OPDS catalog (wireless book delivery)
Tap Setup OPDS catalog in the plugin menu to get your OPDS URL. Add it as an OPDS catalog in KOReader's home screen (+ → OPDS Catalog) to browse and download books wirelessly from your Bookhoard library.
Sync behavior
Configure how the plugin handles progress conflicts:
- Sync to a newer state — what to do when the server has a later position (silent/prompt/never)
- Sync to an older state — what to do when the server has an earlier position (silent/prompt/never)
File structure
bookhoard.koplugin/
├── _meta.lua Plugin metadata
├── main.lua Plugin logic, events, menu
└── BookhoardAPI.lua HTTP client for Bookhoard API
How it works
- The plugin hooks into KOReader's reader events (page turn, document open/close, suspend/resume)
- On push, it collects progress data (percentage, xpointer, page, chapter) and annotations, then sends them to the Bookhoard API
- On pull, it fetches the latest progress from the server and navigates to that position
- Book matching uses SHA-256 hashing (primary), file path, and title/author — the server handles all conflict resolution
License
Same as Bookhoard.