Cross-platform desktop eBook library manager built with Tauri 2 and SvelteKit. Local SQLite catalog, Calibre-style on-disk library layout, and USB/MTP Kindle sync (including Kindle Colorsoft).
- Create or open a library folder with
metadata.dband book files on disk - Import EPUB, PDF, AZW3, MOBI, TXT, and comics (CBZ/CBR)
- Extract metadata on import: title, authors, tags, series, description, identifiers, and cover (EPUB, PDF, MOBI/AZW3)
- Fill missing metadata and cover art from Open Library (manual fetch, plus auto after sparse imports)
- Read EPUB, PDF, TXT, DRM-free MOBI, and comics (CBZ/CBR) in a separate window with saved progress (MOBI is converted to EPUB for display)
- AZW3: import and Kindle send (Amazon store AZW3 is usually DRM-protected and is not opened in-app)
- Convert formats in-app: EPUB → MOBI/AZW3, TXT → EPUB (no Calibre)
- Search (FTS5), edit metadata, delete books
- Detect connected Kindles and other eReaders over USB/MTP or mounted volumes
- Convert EPUB to MOBI or AZW3 natively for Kindle USB send (no Calibre required)
- Record transfer history per device
- Node.js 20+
- pnpm
- Rust toolchain (for Tauri)
- Platform Tauri dependencies (guide)
pnpm install
pnpm tauri devpnpm tauri buildOr use the Makefile for production platform builds:
make build # current host
make build-mac # macOS universal (loads .env for Apple signing if present)
make build-windows # Windows x64
make build-linux # Linux x64 (Linux host)For a signed and notarized local macOS build, copy .env.example to .env, fill in the Apple values, then run make build-mac. See that file for variable notes.
Run make help for the full target list. Artifacts are under src-tauri/target/.../release/bundle/.
make test # Vitest + cargo test
make test-frontend # frontend unit tests
make test-rust # Rust unit/integration testsOr: pnpm test, pnpm test:rust, pnpm test:all.
Every pull request runs the test suite. When a PR is merged, or when you run the workflow manually (Actions → CI and Release → Run workflow), Actions also:
- Runs tests again
- Bumps the version from the PR title (or the manual bump choice):
- Title starts with
MAJOR→ major bump (1.2.3→2.0.0) - Title starts with
MINOR→ minor bump (1.2.3→1.3.0) - Title starts with
PATCH, or anything else → patch bump (1.2.3→1.2.4)
- Title starts with
- Creates a draft
vX.Y.ZGitHub Release (notes from commit subjects since the previous tag) - Builds production bundles for macOS (arm64 + x64, signed and notarized), Linux x64, and Windows x64 (NSIS setup.exe and MSI), then attaches them to that draft
- Publishes the release (immutable releases lock assets only after publish)
Example titles: MINOR add dark mode default, MAJOR redesign library schema, add filter sidebar (patch).
Manual runs: pick patch, minor, or major in the workflow form.
main requires PRs, so the default GITHUB_TOKEN cannot push the version bump. Create a PAT for a repo admin and store it as the Actions secret RELEASE_GITHUB_TOKEN:
- GitHub → Settings → Developer settings → Personal access tokens
- Classic: enable the
reposcope. Fine-grained: this repository, Contents Read and write - Repo → Settings → Secrets and variables → Actions → New repository secret → name
RELEASE_GITHUB_TOKEN
Repo Settings → Actions → General → Workflow permissions should still allow Read and write for PR checks and other jobs.
macOS release jobs sign with a Developer ID Application certificate and notarize via the App Store Connect API. Add these Actions secrets:
| Secret | Value |
|---|---|
APPLE_CERTIFICATE |
Base64-encoded .p12 (openssl base64 -A -in cert.p12 -out cert-base64.txt) |
APPLE_CERTIFICATE_PASSWORD |
Password used when exporting the .p12 |
APPLE_SIGNING_IDENTITY |
Full identity string from security find-identity -v -p codesigning |
APPLE_API_KEY |
App Store Connect API Key ID |
APPLE_API_ISSUER |
App Store Connect Issuer ID |
APPLE_API_KEY_CONTENTS |
Full contents of the downloaded .p8 private key |
See Tauri macOS code signing for creating the certificate and API key. Signed and notarized DMGs open normally; drag Grimoire into Applications.
Windows releases include both:
- NSIS (
*-setup.exe): interactive installs ask for the ebook library folder (defaultDocuments\Grimoire). Silent/passive installs use that default, or/LIBRARYPATH=D:\Books. - MSI (WiX): seeds the same default library path. Override with
msiexec /i Grimoire_*.msi LIBRARYPATH="D:\Books".
Both write %APPDATA%\grimoire\config.json only when that file does not already exist, so upgrades keep an existing library path.
When you choose a library folder, Grimoire writes:
MyLibrary/
metadata.db
Author Name/
Book Title/
Book Title - Author Name.epub
cover.jpg
App preferences (saved library path) live in the OS config directory under grimoire/config.json. Set the path in Settings; Grimoire opens that library automatically on startup.
Grimoire can look up missing fields and cover art via Open Library.
- Prefer ISBN when present; otherwise title + author
- Only fills empty values (Unknown authors, blank tags/notes/ISBN, missing cover)
- Trigger from the book page (Fetch from Open Library), the library context menu (Fetch metadata), or automatically after import when cover/author looks incomplete
- Use Choose cover on the book page to pick among Open Library edition covers
No API key is required.
Grimoire detects these families over USB MTP or mounted volumes:
| Family | Preferred formats | USB send |
|---|---|---|
| Kindle (Paperwhite, Colorsoft, Oasis, Scribe, and similar) | AZW3, MOBI, PDF | Yes (MTP) |
| Kobo | EPUB, KEPUB, PDF | Detection only |
| PocketBook | EPUB, PDF, FB2 | Detection only |
| reMarkable | PDF, EPUB | Detection only |
| BOOX / Onyx | EPUB, PDF | Detection only |
| Tolino | EPUB, PDF | Detection only |
| Nook | EPUB, PDF | Detection only |
Other USB devices that identify as an eReader or ebook device may appear as a generic eReader (EPUB, PDF). USB send is Kindle MTP only today. From Devices you can still browse and remove books on connected readers.
2024 Kindles (Paperwhite, Colorsoft, and similar) use MTP. Grimoire uses mtp-rs for transfers.
The Devices page keeps watching while the app is open:
- MTP hotplug: connect/disconnect shows a toast; Devices and Send update quietly (no forced navigation)
- Mounted volumes: polled every few seconds for Kobo (
.kobo), Kindle (documents+system), reMarkable markers, and volume names that match known brands
From Devices, open View books on a connected reader. Grimoire scans the device for ebook files (EPUB, PDF, AZW3, MOBI, and similar) and shows them in a grid or list. You can multi-select and remove books from the device. The view preference is remembered.
- Prefer an existing AZW3, then MOBI, then PDF
- If the book is EPUB-only, convert natively to dual-format MOBI (via
kindling-mobi) and store it in the library - Upload into the device
documentsfolder
Raw EPUB copied over USB often does not appear in the Kindle library. Native conversion handles that path for USB send.
macOS may lock the Kindle with ptpcamerad or Android File Transfer. If Grimoire cannot open the device:
- Quit Android File Transfer
- Run
pkill -9 ptpcamerad(or disable it vialaunchctlif you accept Photos.app side effects) - Retry from Devices or the book detail page
You may need udev rules so your user can access USB MTP devices without root. See the mtp-rs README for a sample rule.
Kindles usually appear through the Windows Portable Devices stack with no extra drivers.
src/- SvelteKit SPA UIsrc-tauri/- Rust backend (SQLite, import, conversion, MTP)src-tauri/migrations/- SQL schema migrations