https://github.com/thoughtful-toby/calibre-book-cards
Calibre plugin — AI-powered book summary cards with export to Notion, Obsidian, and TTS audio
https://github.com/thoughtful-toby/calibre-book-cards
ai calibre calibre-plugin ebook notion obsidian text-to-speech
Last synced: 3 months ago
JSON representation
Calibre plugin — AI-powered book summary cards with export to Notion, Obsidian, and TTS audio
- Host: GitHub
- URL: https://github.com/thoughtful-toby/calibre-book-cards
- Owner: thoughtful-toby
- License: mit
- Created: 2026-04-10T14:24:23.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-04-10T19:24:05.000Z (3 months ago)
- Last Synced: 2026-04-10T21:25:34.041Z (3 months ago)
- Topics: ai, calibre, calibre-plugin, ebook, notion, obsidian, text-to-speech
- Language: Python
- Size: 51.8 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# Book Cards — Calibre Plugin
**AI-powered book summary cards for your entire library**
[](https://github.com/thoughtful-toby/calibre-book-cards/releases)
[](LICENSE)
[](https://calibre-ebook.com/)
[](https://www.python.org/)
[](https://buymeacoffee.com/thoughtful.toby)
Generate structured summaries of your ebooks — including mental models, cross-references, contrarian takes, and a best quote — then export to **Notion**, **Obsidian**, and a Calibre custom column. Optionally produce a **spoken audio summary** for every book.
[Download Latest Release](https://github.com/thoughtful-toby/calibre-book-cards/releases) · [Report Bug](https://github.com/thoughtful-toby/calibre-book-cards/issues) · [Request Feature](https://github.com/thoughtful-toby/calibre-book-cards/issues)
---
## Features
- **Multi-LLM support** — OpenAI, OpenRouter (200+ models), or Anthropic Claude
- **Parallel text extraction** — EPUB and PDF are read simultaneously; best result wins
- **Configurable extraction depth** — extract 5,000 to 200,000 characters per book (default: 14,000)
- **Fully editable master prompt** — control every field the AI extracts, directly in the Settings dialog
- **Rich Notion pages** — structured page body with headings, bullet lists, callouts, and block quotes
- **Obsidian vault integration** — YAML frontmatter, `[[wikilink]]` cross-references for Graph view, cover image, audio embed
- **Calibre custom column** — stores HTML-rendered cards with embedded JSON for programmatic access
- **TTS audio summaries** — OpenAI TTS, ElevenLabs, or macOS `say` (zero-cost offline)
- **Batch processing** — generate cards for your entire library with duplicate detection
- **Progress queue** — live status view while processing multiple books
- **Result viewer** — expandable card view with JSON copy and batch re-export
---
## Requirements
| Requirement | Notes |
|---|---|
| **Calibre** | 6.x or 7.x (Qt5 and Qt6 both supported) |
| **LLM API key** | OpenAI **or** OpenRouter **or** Anthropic — at least one required |
| **macOS** | 12+ only needed for `say` TTS; all other features work on Windows, macOS, and Linux |
> **No external Python packages required.** The plugin uses only Python stdlib and Calibre's bundled Qt.
---
## Installation
### Option A — Download release
Download `BookCards.zip` from the [Releases](https://github.com/thoughtful-toby/calibre-book-cards/releases) page.
### Option B — Build from source
```bash
git clone https://github.com/thoughtful-toby/calibre-book-cards.git
cd calibre-book-cards
make pack # Creates ../BookCards.zip
make install # Packs + installs in one step
```
### Install in Calibre
1. Open Calibre → **Preferences → Plugins → Load plugin from file**
2. Select `BookCards.zip`
3. Restart Calibre
4. A **Book Cards** button appears in the toolbar
---
## Quick Start
1. Click **Book Cards ▼ → Settings…** and enter your LLM API key
2. Enable at least one export target (Notion / Obsidian / Calibre column)
3. Select one or more books → click **Book Cards** → done
---
## Configuration
All settings are stored in Calibre's `JSONConfig` — nothing is written outside Calibre's config directory.
### 1 — LLM Provider
| Setting | Description |
|---|---|
| **Provider** | `openai` / `openrouter` / `anthropic` |
| **API key** | Per-provider key field |
| **Model** | Dropdown per provider; free-text entry for OpenRouter |
**OpenAI models:** `gpt-4o` · `gpt-4o-mini` · `gpt-5.4` · `gpt-5.4-mini` · `gpt-5.4-nano` · `o3-mini`
**OpenRouter examples:** `openai/gpt-4o` · `meta-llama/llama-3-70b-instruct` · `google/gemini-pro`
**Anthropic models:** `claude-sonnet-4-6` · `claude-opus-4-6` · `claude-opus-4-5` · `claude-haiku-4-5`
### 2 — Master Prompt
The full system prompt is **editable in the UI**. The JSON schema inside the prompt controls what the AI extracts. Available placeholders:
| Placeholder | Replaced with |
|---|---|
| `{title}` | Book title |
| `{author}` | Author name(s) |
| `{text}` | Extracted book text (up to `max_chars`) |
#### Customising the prompt
The default prompt extracts: `title`, `author`, `year`, `one_liner`, `core_thesis`, `key_arguments` (5), `mental_models` (3–5), `contrarian_takes`, `applicability_tags`, `cross_references` (3–5), and `best_quote`.
To add or remove fields:
1. Open **Settings → Master Prompt**
2. Edit the JSON template — add keys, change array sizes, adjust instructions
3. Click **Save** — changes take effect on the next generation
A **Reset to Default** button restores the built-in prompt at any time.
> **Tip:** If you want richer output (more mental models, more cross-references), increase the counts in the prompt's "Rules" section *and* increase `Max chars per book` so the LLM has more source material.
### 3 — Text Extraction
| Setting | Description |
|---|---|
| **Max chars per book** | How many characters of book text are sent to the LLM. Range: 5,000 – 200,000. Default: 14,000 (~25 pages). Higher values produce richer cards but cost more per API call. |
The extraction engine reads EPUB and PDF formats in parallel. EPUB is preferred when both exist. PDF falls back through four strategies (Calibre pdftotext → pdfminer → pypdf → ebook-convert).
### 4 — Export Targets
| Setting | Description |
|---|---|
| **Notion API key** | Internal Integration Token from [notion.so/my-integrations](https://www.notion.so/my-integrations) |
| **Notion database ID** | 32-character ID from the database page URL |
| **Obsidian vault path** | Root folder of your vault |
| **Sync to Notion** | Toggle |
| **Sync to Obsidian** | Toggle |
| **Sync Calibre column** | Toggle — writes to `#book_card` custom column |
| **Output language** | `auto` (matches source) · `en` · `de` · `fr` |
### 5 — Audio Summary (TTS)
| Setting | Description |
|---|---|
| **Enable TTS** | Master toggle |
| **Provider** | `openai` / `elevenlabs` / `system` |
| **Voice / Model** | Provider-specific voice and model selection |
| **Save folder** | Leave empty for auto-detection |
| **Auto-play** | Plays via `afplay` immediately after generation |
| **Embed in Obsidian** | Prepends `![[audio/Title.aiff]]` to the note |
| Provider | Cost | Quality | Offline |
|---|---|---|---|
| OpenAI TTS | ~$0.009/book | ★★★★☆ | No |
| ElevenLabs | 10k chars/month free | ★★★★★ | No |
| macOS `say` | Free | ★★★☆☆ | Yes |
---
## Book Card JSON Schema
```json
{
"title": "The Innovator's Dilemma",
"author": "Clayton M. Christensen",
"year": "1997",
"one_liner": "Great companies fail not despite doing everything right, but because of it.",
"core_thesis": "Disruptive innovations initially underperform...",
"key_arguments": [
"Sustaining vs. disruptive innovation are fundamentally different",
"Good management practices cause failure in disruption",
"Disruptive technologies overshoot mainstream needs over time",
"Organisations have capabilities independent of people",
"Independent units are the only way to pursue disruption"
],
"mental_models": [
{"name": "The Innovator's S-Curve", "description": "Technology follows S-shaped adoption..."},
{"name": "Resource-Process-Values Framework", "description": "What an org can and cannot do..."},
{"name": "Value Network Theory", "description": "The context within which a firm identifies needs..."}
],
"contrarian_takes": [
"Listening to your best customers is dangerous during disruption",
"Market research is useless for non-consumption markets"
],
"applicability_tags": ["strategy", "innovation", "deep-tech"],
"cross_references": [
"The Lean Startup by Eric Ries",
"Zero to One by Peter Thiel",
"Crossing the Chasm by Geoffrey Moore"
],
"best_quote": "The logical, competent decisions of management..."
}
```
**Valid `applicability_tags`:** `blended-finance` · `structured-finance` · `venture` · `policy` · `deep-tech` · `strategy` · `innovation` · `economics` · `leadership` · `history`
---
## Notion Setup
Create a database with these properties (names are **case-sensitive**):
| Property | Type |
|---|---|
| `Name` | Title |
| `Author` | Rich text |
| `Year` | Rich text |
| `One-Liner` | Rich text |
| `Core Thesis` | Rich text |
| `Key Arguments` | Rich text |
| `Mental Models` | Rich text |
| `Contrarian Takes` | Rich text |
| `Best Quote` | Rich text |
| `Tags` | Multi-select |
| `Cross References` | Rich text |
| `Status` | Select |
**Connect your integration:**
1. [notion.so/my-integrations](https://www.notion.so/my-integrations) → **New integration** → copy the token
2. In your database: **⋯ → Connections → Add connections** → select your integration
3. Paste the token and database ID into the plugin Settings
---
## Obsidian Output
Each book creates `{vault}/Books/{Title}.md`:
```markdown
---
title: "The Innovator's Dilemma"
author: "Clayton M. Christensen"
year: "1997"
tags: ["strategy", "innovation", "deep-tech"]
status: unread
source: calibre
date_added: 2026-04-10
---
![[covers/The_Innovators_Dilemma.png]]
> Great companies fail not despite doing everything right, but because of it.
## Core Thesis
Disruptive innovations initially underperform...
## Key Arguments
- Sustaining vs. disruptive innovation are fundamentally different
- ...
## Mental Models
- **The S-Curve**: Technology performance follows an S-shaped adoption curve...
## Contrarian Takes
- Listening to your best customers is actively dangerous...
## Best Quote
> The logical, competent decisions of management...
## Cross References
- [[The Lean Startup]] by Eric Ries
- [[Zero to One]] by Peter Thiel
```
Cross-references use `[[wikilinks]]` so they appear in Obsidian's **Graph View**.
---
## Project Structure
```
calibre-book-cards/
├── __init__.py # InterfaceActionBase — plugin metadata
├── action.py # InterfaceAction — toolbar, menus
├── config.py # Settings dialog + JSONConfig defaults
├── ui.py # QThread worker, ProgressDialog, ResultView
├── extractor.py # Parallel EPUB + PDF text extraction
├── card_generator.py # Multi-provider LLM calls (urllib)
├── notion_pusher.py # Notion API integration
├── obsidian_exporter.py # Markdown + YAML file writer
├── tts_generator.py # TTS: OpenAI / ElevenLabs / macOS say
├── plugin-import-name-book_cards.txt
├── Makefile # pack / install / clean / test-env
└── images/book.png # Toolbar icon
```
---
## Troubleshooting
| Symptom | Fix |
|---|---|
| *"API key missing"* | Settings → enter key for the active provider |
| Card is empty `{}` | Try a more capable model; check Calibre debug console |
| No text extracted | Book needs an EPUB or PDF format in Calibre |
| Notion 404 | Share the database with your integration |
| Notion 400 | Property names must match exactly (case-sensitive) |
| Obsidian file not created | Re-select vault folder in Settings |
| `say` voice not found | Run `say -v '?'` and pick an installed voice |
---
## Privacy
- **API keys** are stored in Calibre's JSONConfig (local, user-only access)
- **Book text** (up to your configured `max_chars`) is sent to the LLM provider you choose — no other party
- **Cover images** stay local (Obsidian vault only) — nothing is uploaded
---
## Support
If Book Cards saves you time or helps you think more clearly about what you read, consider buying me a coffee:
---
## Contributing
Contributions are welcome! Please open an [issue](https://github.com/thoughtful-toby/calibre-book-cards/issues) first to discuss what you'd like to change.
1. Fork the repo
2. Create your feature branch (`git checkout -b feat/amazing-feature`)
3. Commit your changes
4. Push to the branch (`git push origin feat/amazing-feature`)
5. Open a Pull Request
---
## License
[MIT](LICENSE) © Tobias Temmen
---
Built with [Calibre](https://calibre-ebook.com/) · [OpenAI](https://platform.openai.com/) · [OpenRouter](https://openrouter.ai/) · [Anthropic](https://www.anthropic.com/) · [ElevenLabs](https://elevenlabs.io/) · [Notion API](https://developers.notion.com/)
If you find this useful, give it a ⭐ on GitHub!