Skip to content

Repository files navigation

Hardcover Sync

Hardcover Sync

A Calibre plugin for bidirectional sync with Hardcover.app.

Features

  • Sync reading status between Calibre and Hardcover (Want to Read, Currently Reading, Read, Paused, Did Not Finish)
  • Sync metadata including ratings, reading progress, dates started/finished, and reviews
  • Bidirectional sync - Push changes to Hardcover or pull from Hardcover to Calibre

Requirements

  • Calibre 6.0 or later (Qt6)
  • A Hardcover.app account with an API token

Installation

  1. Download the latest release .zip file
  2. In Calibre, go to Preferences → Plugins → Load plugin from file
  3. Select the downloaded .zip file
  4. Restart Calibre

Setup

Warning

Your API token is stored in cleartext in Calibre's plugin configuration. Keep your Calibre configuration directory secure and do not share your plugins/Hardcover Sync.json file.

  1. Create a personal access token with the permissions Hardcover Sync needs. The link preselects read:catalog, read:library, read:lists, read:me:content, write:library, write:reviews, and write:lists; review them before creating the token.
  2. In Calibre, go to Preferences → Plugins → Hardcover Sync → Customize plugin
  3. Enter the new hc_pat_… token and click Validate. Validation checks that the token can access the operations used by the plugin.
  4. Configure column mappings for the data you want to sync

If you replace a legacy JWT, revoke it from your Hardcover API settings after the new personal access token is working.

Recommended custom columns

Create these custom columns in Calibre (Preferences → Add your own columns):

Column Type Suggested Name
Status Text #hc_status
Rating Rating #hc_rating
Progress (pages) Integer #hc_progress
Progress (%) Float or integer #hc_progress_pct
Date Started Date #hc_date_started
Date Finished Date #hc_date_read
Review Long text #hc_review

You can use pre-defined Calibre columns as well (e.g. rating).

You can use either or both progress columns:

  • Progress (pages) - Integer column for page number (e.g., 150)
  • Progress (%) - Float or integer column for percentage (e.g., 50.0 or 50)

Hardcover stores page progress and calculates the percentage from the book's page count. When syncing to Hardcover with both columns populated, Progress (pages) takes precedence. Percentage progress is skipped with a warning when the linked Hardcover edition has no page count.

For a read-only column showing whether each book has a Hardcover identifier, see Tips & tricks.

Date column format

I use yyyy-MM-dd. Check the docs for the format string.

Usage

Menu structure

Hardcover (toolbar button)
├── Set Status →
│   ├── Want to Read
│   ├── Currently Reading
│   ├── Read
│   ├── Paused
│   ├── Did Not Finish
│   └── Remove from Hardcover
├── Sync from Hardcover...
├── Sync to Hardcover...
├── Link to Hardcover...
├── View on Hardcover
├── Remove Hardcover Link
├── Customize plugin...
└── Help

Linking books

Before syncing, books must be linked between Calibre and Hardcover:

  1. Select one or more books in Calibre
  2. Click Hardcover → Link to Hardcover...
  3. Search by ISBN (automatic) or title
  4. Select the matching Hardcover book

Syncing

Sync from Hardcover: Pull your reading data from Hardcover into Calibre

  • Fetches your Hardcover library
  • Shows a preview of changes with checkboxes
  • Only updates books that are already linked

Sync to Hardcover: Push your Calibre data to Hardcover

  • Select books to sync
  • Preview changes before applying
  • Can add books to your Hardcover library or update existing books

Sync is intentionally non-destructive: an empty mapped value is treated as “no update” rather than a request to clear the value on the other service. Clear values manually on both sides when needed.

Tips & tricks

Show Hardcover link status in the book list

You can add a read-only custom column that shows a green check when a book has a hardcover identifier and a red X when it does not:

  1. In Calibre, go to Preferences → Add your own columns and add a custom column.
  2. Configure these fields:
    • Lookup name: hardcover (Calibre will refer to the created column as #hardcover)
    • Column heading: Linked to Hardcover?
    • Column type: Column built from other columns
    • Show checkmarks: enabled
    • Template: {identifiers:identifier_in_list(hardcover,yes,no)}
    • Sort/search column by: Yes/No
  3. Click OK. Calibre will prompt you to restart.

Calibre custom column configured to show a check or X based on the Hardcover identifier

This column is computed from the identifier stored in Calibre; it does not verify that the identifier still resolves on Hardcover.

Bonus: Allow for "Ignored" Hardcover linking

Some books that you might have (omnibus volumes, educational papers, etc.) may not be on Hardcover, and if you're attempting to keep your collection synced as much as possible, having to weed through all of the "not synced" items can be frustrating if there are certain books you want to disregard.

Note

This is not a functional "ignore"; you can still select this book and attempt to link it. This is only a visual flag that you have chosen to ignore this, & to break it out of the default "yes/no" sorting.

If you want to mark a book as "Ignored" from syncing:

  1. Follow the steps above to add the custom column, or return to the Preferences → Add your own columns view & edit your existing column
  2. When you go to set or update the Template, click the Edit button next to the field
Screenshot 2026-09-09 at 10 24 51
  1. In the Template: box, paste the following, and press "OK:
program:
    if identifier_in_list(field('identifiers'), 'hardcover', '1', '') then
        'yes'
    elif str_in_list(field('tags'), ',', 'hardcover-sync-ignored', '1', '') then
        'ignored'
    else
        'no'
    fi
Screenshot 2026-09-09 at 10 31 40
  1. Find any book that you'd like to flag as "ignored", edit its metadata, and add a tag of hardcover-sync-ignored
Screenshot 2026-09-09 at 10 25 59

Development

Prerequisites

  • mise for tool management

Setup

# Install tools
mise install

# Install dependencies
uv sync

# Download Calibre source (for type hints)
just -f .calibre/justfile setup

Common tasks

just test           # Run tests
just build          # Build plugin zip
just install-plugin # Install to test Calibre instance
just calibre        # Launch isolated test Calibre
just lint           # Run linter and formatter
just typecheck      # Run Pyright on production code

Pre-commit hooks

This project uses prek for pre-commit hooks:

# Install hooks (run once after cloning)
uv run prek install
uv run prek install --hook-type commit-msg

# Run hooks manually
uv run prek run --all-files

Running tests

# Unit tests (mocked, no API token needed)
just test

# General integration tests (legacy JWT or PAT)
export HARDCOVER_API_TOKEN="your-token"

# PAT permission tests (optional)
export HARDCOVER_PAT_TOKEN="your-full-scope-hc_pat-token"
export HARDCOVER_RESTRICTED_PAT_TOKEN="your-PAT-without-write-reviews"

uv run pytest test/test_integration.py -v

Integration tests use read-only operations, skipped GraphQL mutations, and dry-run mode for mutations, so they won't modify your Hardcover library. The restricted PAT must include every Hardcover Sync scope except write:reviews.

Acknowledgments

The development environment and build tooling for this plugin is based on RobBrazier/calibre-plugins. Thanks to Rob Brazier for the excellent foundation including:

  • Calibre source download scripts for IDE support
  • Plugin bundling and packaging scripts
  • Test infrastructure with Calibre/Qt mocking
  • Isolated Calibre instance for development

He wrote the Hardcover metadata source plugin linked above. It's excellent.

The plugin icon uses icons from Material Design Icons (Apache 2.0 license).

License

GPL-3.0-or-later (same as Calibre)

About

A Calibre plugin to sync reading state with Hardcover

Topics

Resources

Code of conduct

Contributing

Stars

9 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages