A calibre plugin to synchronize metadata from KOReader to calibre
Python
365
268 commits
updated Apr 28, 2026
A calibre plugin to synchronize metadata from KOReader to calibre.
KOReader creates sidecar files that hold read progress and annotations. This plugin reads the data from those sidecar files and updates calibre's metadata based on them. It is inspired by the Kobo Utilities plugin, that synchronizes reading progress between the original Kobo firmware ("Nickel") and custom columns in calibre.
Note that at the moment the sync is primarily one-way—from the KOReader device to calibre, and only works for USB and wireless devices. For best experience please use the latest KOReader release
Releases will also be uploaded to plugin thread on the MobileRead Forums. If you are on there as well, please let me know what you think of the plugin in that thread.
Pick and choose the metadata you would like to sync and create the appropriate columns in calibre. The plugin makes this easy, simply select the create new columns option in the config dropdowns.
These are your options:
{:.0%}.There are additional settings for:
Add KOReader Sync to main toolbar when a device is connected, if it isn't there already.
Right-click the KOReader Sync icon and Configure.
Map the metadata you want to sync to the newly created calibre columns.
Click OK to save your mapping.
From now on just click the KOReader Sync icon to sync all mapped metadata for all books on the connected device to calibre.
Note: Some field are depreciated and removed from plugin since they are
changed/removed from sidecar_contents data structure:
first_bookmark removedlast_bookmark removedbookmarks renamed to annotationsrating KOreader uses 5-point but calibre 10-point scale (whole starts, not half stars)date_sidecar_modified seems to be present in calculated only if connected via
cable (not wireless)This plugin supports use of a KOReader Sync
Server
(Progress sync in the KOReader app) in order to update current percent read
(both float and int) and location you last stopped reading at wirelessly.
You must also have the MD5 hash column enabled.
Add the server and user credentials in the plugin config to use this function.
The user password is stored as a hash, not plain text.
You can have calibre fetch updated data on a daily schedule.
<bookname>.sdr folder from the
device before attempting to push the sidecars back to KOReader for any books
you would like to overwrite the current metadata with Calibre's metadata.This plugin has been tested successfully with:
KOBO and KOBOTOUCH drivers)KOBOTOUCHEXTENDED driver)SMART_DEVICE_APP driver (e.g., KOReader wireless connection)POCKETBOOK_IMPROVED, POCKETBOOK632, POCKETBOOK626, or POCKETBOOK622 driversKINDLE2)TOLINO)FOLDER_DEVICE)USER_DEFINED driverThis plugin is not compatible with:
MTP_DEVICE (Android devices connected via MTP)If you encounter any issues with the plugin, please submit them here.
auto_connect_to_folder. Point that to
the dummy_device folder in this repository. (I have included royalty free
EPUBs for your and my convenience.)DRY_RUN to True in __init__.py.PYDEVD to True in __init__.py.You might need to
change sys.path.append in action.py.SUPPORTED_DEVICES list in config.py.
Adding a new type here is the first step to adding support, but make sure all
features are tested thoroughly before releasing a version with an added deviceUse make to load the plugin into calibre and launch it:
make dev
For Linux users with a Flatpak installation of Calibre, use the FLATPAK=1
flag. This is necessary because Flatpak runs Calibre in a
sandboxed environment,
requiring specific commands to interact with it:
make dev FLATPAK=1
Note:
FLATPAK=1is only supported on Linux. On Windows and macOS, please install Calibre natively and runmakewithout this flag.
| Target | Description |
|---|---|
test | Run unit and integration tests using pytest (includes Calibre environment mocks) |
lint | Run static analysis using pylint (enforces 9.5/10 score and zero Errors) |
dev | Load plugin source directly into Calibre and launch in debug mode |
pre | Patch internal version with -pre and build a community pre-release ZIP |
bump-patch | Increment the patch version in .version (e.g., 0.8.0 -> 0.8.1) |
bump-minor | Increment the minor version in .version (e.g., 0.8.0 -> 0.9.0) |
bump-major | Increment the major version in .version (e.g., 0.8.0 -> 1.0.0) |
prep-release | Create a release-prep-<version> branch, update files, and commit |
release | Tag the current version and push to trigger GitHub Release, do this after updated version already pushed to main |
md_to_bb | Convert input.md to output.forumbb (BBCode) for MobileRead forum posts |
| Target | Description |
|---|---|
install | Install ZIP into Calibre without launching the GUI |
zip | Create plugin ZIP file in dist/ directory |
load | Install ZIP from dist/ and launch Calibre in debug mode |
build | Full build workflow: update versions from .version and create ZIP |
dev_version | Update all code files with the current version from .version |
clean | Remove all build artifacts and temporary files |
clean_dev | Clean up development-specific temporary files |
tag | Create and push git tag for current version |
The project uses a structured workflow to ensure both rapid updates and stable releases:
develop): This is the primary work-in-progress branch.
main): This branch contains the stable, production-ready code.
develop into main when a milestone is reached.make release on this branch automatically cleans the version string, tags the commit, and triggers the official GitHub Release.The project enforces high code quality standards through automated checks:
make test. We use pytest along with a mocking layer (tests/conftest.py) that simulates the Calibre environment. This allows you to test plugin logic without having Calibre installed.make lint. We use pylint with a custom configuration (.pylintrc).
These checks run automatically on every Pull Request via GitHub Actions.
The project uses GitHub Actions to automate releases. When a tag v* is pushed, a GitHub Release is created automatically with the built plugin ZIP.
.version OR run make bump-patch / make bump-minor.make prep-release. This creates a new branch (e.g., release-prep-x.x.x), updates all version strings in the code, and commits them.main.main branch, run make release. This will tag the commit and push it.calibre-customize -a "KOReader_Sync_vX.X.X.zip", where X.X.X
refers to the version you downloadedcalibre-debug -gkoreader to see what
it didPython
91.5%
Makefile
4.8%
Lua
3.7%
A calibre plugin to synchronize metadata from KOReader to calibre
Python
365
268 commits
updated Apr 28, 2026
A calibre plugin to synchronize metadata from KOReader to calibre.
KOReader creates sidecar files that hold read progress and annotations. This plugin reads the data from those sidecar files and updates calibre's metadata based on them. It is inspired by the Kobo Utilities plugin, that synchronizes reading progress between the original Kobo firmware ("Nickel") and custom columns in calibre.
Note that at the moment the sync is primarily one-way—from the KOReader device to calibre, and only works for USB and wireless devices. For best experience please use the latest KOReader release
Releases will also be uploaded to plugin thread on the MobileRead Forums. If you are on there as well, please let me know what you think of the plugin in that thread.
Pick and choose the metadata you would like to sync and create the appropriate columns in calibre. The plugin makes this easy, simply select the create new columns option in the config dropdowns.
These are your options:
{:.0%}.There are additional settings for:
Add KOReader Sync to main toolbar when a device is connected, if it isn't there already.
Right-click the KOReader Sync icon and Configure.
Map the metadata you want to sync to the newly created calibre columns.
Click OK to save your mapping.
From now on just click the KOReader Sync icon to sync all mapped metadata for all books on the connected device to calibre.
Note: Some field are depreciated and removed from plugin since they are
changed/removed from sidecar_contents data structure:
first_bookmark removedlast_bookmark removedbookmarks renamed to annotationsrating KOreader uses 5-point but calibre 10-point scale (whole starts, not half stars)date_sidecar_modified seems to be present in calculated only if connected via
cable (not wireless)This plugin supports use of a KOReader Sync
Server
(Progress sync in the KOReader app) in order to update current percent read
(both float and int) and location you last stopped reading at wirelessly.
You must also have the MD5 hash column enabled.
Add the server and user credentials in the plugin config to use this function.
The user password is stored as a hash, not plain text.
You can have calibre fetch updated data on a daily schedule.
<bookname>.sdr folder from the
device before attempting to push the sidecars back to KOReader for any books
you would like to overwrite the current metadata with Calibre's metadata.This plugin has been tested successfully with:
KOBO and KOBOTOUCH drivers)KOBOTOUCHEXTENDED driver)SMART_DEVICE_APP driver (e.g., KOReader wireless connection)POCKETBOOK_IMPROVED, POCKETBOOK632, POCKETBOOK626, or POCKETBOOK622 driversKINDLE2)TOLINO)FOLDER_DEVICE)USER_DEFINED driverThis plugin is not compatible with:
MTP_DEVICE (Android devices connected via MTP)If you encounter any issues with the plugin, please submit them here.
auto_connect_to_folder. Point that to
the dummy_device folder in this repository. (I have included royalty free
EPUBs for your and my convenience.)DRY_RUN to True in __init__.py.PYDEVD to True in __init__.py.You might need to
change sys.path.append in action.py.SUPPORTED_DEVICES list in config.py.
Adding a new type here is the first step to adding support, but make sure all
features are tested thoroughly before releasing a version with an added deviceUse make to load the plugin into calibre and launch it:
make dev
For Linux users with a Flatpak installation of Calibre, use the FLATPAK=1
flag. This is necessary because Flatpak runs Calibre in a
sandboxed environment,
requiring specific commands to interact with it:
make dev FLATPAK=1
Note:
FLATPAK=1is only supported on Linux. On Windows and macOS, please install Calibre natively and runmakewithout this flag.
| Target | Description |
|---|---|
test | Run unit and integration tests using pytest (includes Calibre environment mocks) |
lint | Run static analysis using pylint (enforces 9.5/10 score and zero Errors) |
dev | Load plugin source directly into Calibre and launch in debug mode |
pre | Patch internal version with -pre and build a community pre-release ZIP |
bump-patch | Increment the patch version in .version (e.g., 0.8.0 -> 0.8.1) |
bump-minor | Increment the minor version in .version (e.g., 0.8.0 -> 0.9.0) |
bump-major | Increment the major version in .version (e.g., 0.8.0 -> 1.0.0) |
prep-release | Create a release-prep-<version> branch, update files, and commit |
release | Tag the current version and push to trigger GitHub Release, do this after updated version already pushed to main |
md_to_bb | Convert input.md to output.forumbb (BBCode) for MobileRead forum posts |
| Target | Description |
|---|---|
install | Install ZIP into Calibre without launching the GUI |
zip | Create plugin ZIP file in dist/ directory |
load | Install ZIP from dist/ and launch Calibre in debug mode |
build | Full build workflow: update versions from .version and create ZIP |
dev_version | Update all code files with the current version from .version |
clean | Remove all build artifacts and temporary files |
clean_dev | Clean up development-specific temporary files |
tag | Create and push git tag for current version |
The project uses a structured workflow to ensure both rapid updates and stable releases:
develop): This is the primary work-in-progress branch.
main): This branch contains the stable, production-ready code.
develop into main when a milestone is reached.make release on this branch automatically cleans the version string, tags the commit, and triggers the official GitHub Release.The project enforces high code quality standards through automated checks:
make test. We use pytest along with a mocking layer (tests/conftest.py) that simulates the Calibre environment. This allows you to test plugin logic without having Calibre installed.make lint. We use pylint with a custom configuration (.pylintrc).
These checks run automatically on every Pull Request via GitHub Actions.
The project uses GitHub Actions to automate releases. When a tag v* is pushed, a GitHub Release is created automatically with the built plugin ZIP.
.version OR run make bump-patch / make bump-minor.make prep-release. This creates a new branch (e.g., release-prep-x.x.x), updates all version strings in the code, and commits them.main.main branch, run make release. This will tag the commit and push it.calibre-customize -a "KOReader_Sync_vX.X.X.zip", where X.X.X
refers to the version you downloadedcalibre-debug -gkoreader to see what
it didPython
91.5%
Makefile
4.8%
Lua
3.7%