title: "@insurgently/library-hub-api"
built: 2026-10-30
source: api/README.md
html: https://insurgently.com/projects/library-hub/technical/agents/READMEIndex of these files: llms.txt
Types and a few small helpers for reading books from Library Hub in your own Obsidian plugin.
Library Hub keeps a book collection in a vault: Calibre and other providers, book notes, shelves, a reader. Its API lets another plugin list books and shelves, get a book's file or its text, open the reader at a passage, and change shelves with undo. This package is that API's contract: the types, the version it describes, and the code that finds the plugin.
It has no dependencies and imports nothing at runtime. Your bundler keeps what you use.
Install
npm install --save-dev @insurgently/library-hub-api
Use a tilde, so you take patch fixes only, and raise the minor when you're ready for what it adds.
Quick look
import { getLibraryHub, onLibraryHubReady, hasMethod, type LibraryHubApi } from '@insurgently/library-hub-api';
const WANTED = '0.8.0';
export default class MyPlugin extends Plugin {
libraryHub: LibraryHubApi | null = null;
onload() {
// now if Library Hub is loaded, and again each time it loads (the user can turn it off and on)
onLibraryHubReady(this.app, this, WANTED, (api) => (this.libraryHub = api));
}
async chapters(book: string) {
const found = getLibraryHub(this.app, WANTED, { by: 'My Plugin', for: 'for its reading lists' });
if (!found.libraryHub) return new Notice(found.message);
const text = await found.libraryHub.bookText(book); // a Calibre id, a note, a file, an ISBN…
return text.chapters.map((c) => `${c.n}. ${c.title} (${c.location})`);
}
}
A chapter's location is what openBook takes, so you can send the reader back to it later:
await libraryHub.openBook(book, { location: chapter.location, quote: 'a sentence from the passage' });
How it behaves
- Versions.
getLibraryHub(app, wanted)checks the installed API against the version you built for: same major, and a minor at least as new. Gate on the lowest minor you need. A method newer than your gate says@sincein its comment: check it withhasMethod(api, 'bookText')first. - Reloads. Library Hub fires
library-hub:readyeach time it loads.onLibraryHubReadylistens for it through your plugin, so the listener goes when your plugin unloads. - Errors. Every method rejects with an
Errorwhosecodeis aLibraryHubErrorCode(server-off,book-missing,needs-conversion…) and whose message says, in plain words, what went wrong and what to do. Branch on the code. Show the message. - Books. A
BookRefnames a book: a Calibre id, a note's path or name, a book file, an ISBN, a Calibre uuid, or a provider's id. Numbers work wherever they did before. - Text.
bookTextgives a book's chapters with their text, alocationfor each, offsets in code points, and a hash of the whole text that changes only when the text does.bookChaptersis the same without the text. Converting an AZW3 or MOBI adds a file to the user's Calibre library, so it only happens when you pass{ convert: true }, and the user is asked first. - Tools. The table of Library Hub's operations as model tools is at
@insurgently/library-hub-api/tools. Library Hub registers them itself; you only need it to map them somewhere else. - Old names.
getBooks,onBooksReady,BooksApiand theBOOKS_*constants, from before the plugin was renamed, still work and are deprecated. Deprecated names go at 1.0, not before.
The full reference is dist/index.d.ts, with a comment on every declaration.
Versions
The package's version is the API's version. It's published after the Library Hub release that serves it, so you can't build against an API nobody has yet. CHANGELOG.md says which release that is.
MIT licensed.