Skip to content

Obsidian Plugin

@libris/obsidian-plugin mirrors a Libris library into an Obsidian vault so you can browse books, see KOReader-driven reading progress, and take notes per book using normal Obsidian features (wikilinks, tags, callouts, backlinks, Bases).

It is read-only in v1. KOReader pushes progress to Libris via kosync; the plugin pulls Libris state into the vault. Notes you write in Obsidian stay in the vault — they never sync back to Libris.

What it produces

<vault>/
└── Libris/
    ├── Library.base                   # Bases view: card grid + currently-reading
    ├── My Reading.base                # Bases view: top-rated, next-up, read this year, DNF
    ├── Reading.md                     # Dashboard: currently reading, recently finished, paused
    ├── Covers/
    │   └── {libris_id}.{ext}          # Cover bitmap, cached locally
    ├── Books/
    │   └── {Author}/
    │       └── {Title} ({Year}).md    # One note per book
    ├── Series/
    │   └── {Series Name}.md           # One per multi-book series
    └── Authors/
        └── {Author}.md                # One per multi-book author

Each per-book note has frontmatter (title, author, isbn, percentage, reading_status, …), a sentinel-delimited progress callout, the cover embed, the Libris description, and a ## My Notes section that the plugin never overwrites.

Series and author pages have a sentinel-delimited list of [[Book]] wikilinks (numbered by series_index for series, chronological for authors) and a user-owned ## Notes section.

The Reading.md dashboard lists currently-reading books, anything finished in the last 30 days, and anything paused. The block regenerates each sync — write your own notes above or below it.

Install

The plugin isn't in Obsidian's community registry yet. To install from source:

bash
# Build
git clone <libris repo>
cd libris
pnpm install
pnpm --filter @libris/obsidian-plugin build

# Symlink into your vault
ln -s "$(pwd)/apps/obsidian-plugin" "<vault>/.obsidian/plugins/libris"

# Enable in Obsidian: Settings → Community Plugins → Libris → toggle on

Configure

Open Settings → Community Plugins → Libris.

SettingValue
Server URLBase URL of your Libris instance, e.g. https://libris.example
API keyA bearer token from POST /api/auth/keys (see Libris dashboard)
Root folderWhere notes are written. Default: Libris

The API key is stored in <vault>/.obsidian/plugins/libris/data.json. Treat that file as a secret.

How sync runs

The plugin syncs in three places:

  1. Automatically when Obsidian's workspace becomes ready (i.e. on app startup), once per session.
  2. On demand via the command palette: Libris: Sync now.
  3. On demand via the ribbon icon (book icon).

A sync drains /api/library page-by-page. For each book it fetches the detail, cover, and progress; computes the highest percentage across devices (mirroring the MAX(percentage) the Libris UI shows); derives a reading status with the same thresholds as services/api-hono/src/lib/reading-status.ts (≥95% finished, idle >30 days paused); and writes the note.

Re-syncs are idempotent. Running sync twice in a row produces no diff.

What the plugin owns vs what's yours

The plugin rewrites a fixed set of frontmatter keys on every sync:

  • libris_id, libris_file_ids
  • title, author, series, series_index, year
  • isbn13, language, publisher, genres, cover
  • percentage, reading_status, last_progress_device, last_progress_at, synced_at

Everything else in frontmatter is yours and is preserved — your custom rating, your mood tags, your project links, anything.

The body has three sentinel-delimited blocks the plugin replaces verbatim each sync:

  • <!-- libris:progress:start --> … <!-- libris:progress:end -->
  • <!-- libris:cover:start --> … <!-- libris:cover:end -->
  • <!-- libris:description:start --> … <!-- libris:description:end -->

Below those is ## My Notes. Anything you write under that header stays untouched.

The tags array gets libris ensured (used by the Bases view). Your other tags are preserved.

Library.base

Libris/Library.base ships with two views:

  • Library — cards view with cover, file name, author, status icon, and %.
  • Currently reading — table grouped by author, filtered to books with reading_status: reading.

The plugin writes this file once on the first sync. After that you're free to customize it — the plugin won't overwrite your changes.

User-owned frontmatter conventions

The plugin preserves any frontmatter key it doesn't own. A handful of keys are conventions surfaced by the second Bases file (Libris/My Reading.base):

KeyTypeUsed by
my_rating1–5"Top rated" cards view (my_rating >= 4)
my_read_datedate"Read this year" view (filters by current year)
prioritystring"Next up" view (priority == "high")
did_not_finishboolean"Did not finish" view

Add them per-book to drive those views. The plugin never reads or writes them — they're yours.

Series + author pages

For any series with two or more books, the plugin generates Libris/Series/{Series Name}.md containing a numbered list of the member books (ordered by series_index) plus a user-owned ## Notes section. Same for authors at Libris/Authors/{Author}.md (chronological by publishedYear). Useful for series-level reflections, author-wide reading retrospectives, etc.

Both pages also gain a member_books: [libris_id, …] frontmatter list and the tags libris + libris/series (or libris/author).

Sync status sidebar

Run Libris: Open sync status (or click the activity icon in the ribbon) to open a panel showing the last sync time, book counts, errors, and a Sync now button. Updates live as syncs run.

Quick navigation commands

When the active note is a Libris book note (i.e. has a libris_id):

  • Libris: Open current book in Libris — opens {serverUrl}/library/{libris_id} in your default browser.
  • Libris: Open current book's series in Libris — opens {serverUrl}/series/{series}.

Troubleshooting

"Configure the Libris server URL and API key in plugin settings." — Settings tab is empty. Add both, then run Libris: Sync now.

Sync hangs on first run with hundreds of books. — Expected. Each book triggers three HTTP calls (detail, cover, progress) plus the cover write. A library of 500 books takes ~3-5 minutes. Subsequent syncs are much faster because covers are skipped when bytes match.

A book's progress shows zero in Obsidian but ~50% in the Libris UI. — Confirm KOReader has actually pushed for that file (check the Libris UI's progress page or GET /api/library/{id}/progress). The plugin reads exactly what the API returns.

A note disappeared after I renamed it in Obsidian. — The plugin tracks notes by libris_id in frontmatter, not by path. If your rename preserved the frontmatter (Obsidian default), the next sync will pick it up at the new path. If the file is gone entirely, the next sync recreates it at the canonical path.

A book deleted on Libris is still in my vault. — Intentional. The plugin won't delete vault notes. You can search for libris_id: and clean up manually, or wait until the orphan-handling feature ships.

Out of scope (v1)

These are not implemented and are not planned for v1:

  • Pushing progress, highlights, or notes back to Libris
  • Periodic background sync (auto runs on Obsidian startup only)
  • Mobile support (isDesktopOnly: true)
  • Reading EPUBs/PDFs inside Obsidian
  • Multiple Libris servers per vault