Skip to content

Add calibre-search extension#27295

Open
BrunoMiguelMonteiro wants to merge 4 commits into
raycast:mainfrom
BrunoMiguelMonteiro:ext/calibre-search
Open

Add calibre-search extension#27295
BrunoMiguelMonteiro wants to merge 4 commits into
raycast:mainfrom
BrunoMiguelMonteiro:ext/calibre-search

Conversation

@BrunoMiguelMonteiro
Copy link
Copy Markdown

@BrunoMiguelMonteiro BrunoMiguelMonteiro commented Apr 20, 2026

Description

Screencast

Checklist

- Apply Prettier formatting to all source files
- Add ESLint flat config and remove unused import for store validation
- Add store screenshots and fix author handle for Raycast Store submission
- Add README with commands, configuration, and installation instructions
- Exclude CLAUDE.md from version control
- Add "Add to Calibre Library" command and fix open-in-Calibre navigation
- Initial release: Calibre Library Raycast extension
@raycastbot raycastbot added new extension Label for PRs with new extensions platform: macOS labels Apr 20, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Congratulations on your new Raycast extension! 🚀

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

Once the PR is approved and merged, the extension will be available on our Store.

@BrunoMiguelMonteiro BrunoMiguelMonteiro marked this pull request as ready for review April 20, 2026 08:52
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 20, 2026

Greptile Summary

This PR adds a new calibre-search Raycast extension with two commands: Search Calibre (browse/search a Calibre library via direct SQLite access) and Add to Calibre Library (scan configured folders for ebook files and add them via calibredb). The extension includes cover thumbnail extraction for EPUB and PDF files, a comprehensive unit-test suite, and the standard Raycast extension scaffolding.

  • Search command reads metadata.db via useSQL, maps rows through a JOIN query that uses ' & ' as the GROUP_CONCAT separator to safely handle "Last, First" author names, and displays book detail with cover, metadata, and actions (open in Calibre, open file, synopsis, copy, show in Finder).
  • Add command scans up to three configurable directories for ebook files, renders a filterable list with per-file cover thumbnails, and adds selected books using async calibredb invocation — with a graceful fallback that hands off to the running Calibre GUI when its lock is held.
  • Thumbnail loading currently spawns a child process (unzip or qlmanage) for every ebook simultaneously on mount, and the directory scan runs synchronously inside useMemo, both of which can cause noticeable UI lag on large Downloads folders.

Confidence Score: 4/5

Safe to merge after addressing the synchronous scan and unbounded thumbnail spawning in the Add command; the Search command is clean.

The core logic — SQL query, row mapping, calibredb invocation, EPUB cover extraction — is correct and well-tested. The two concerns in add-to-library.tsx (blocking useMemo scan and spawning a process per ebook on mount) are performance/UX issues rather than correctness failures, but they can make the Add command feel frozen or unresponsive on first load with a populated Downloads folder.

extensions/calibre-search/src/add-to-library.tsx — the synchronous directory scan inside useMemo and the unbounded concurrent thumbnail process spawning both warrant a second look before merging.

Important Files Changed

Filename Overview
extensions/calibre-search/src/add-to-library.tsx Handles file scanning, thumbnail generation, and calibredb invocation; synchronous I/O in useMemo and unbounded concurrent process spawning are worth addressing
extensions/calibre-search/src/calibre.ts SQL query and row mapper look correct; uses ' & ' delimiter in GROUP_CONCAT to avoid comma collision with "Last, First" author names
extensions/calibre-search/src/index.tsx Main search command using useSQL; filtering, detail panel, and actions are implemented cleanly
extensions/calibre-search/src/utils.ts Pure utility functions with good test coverage; all edge cases (null, empty, malformed) handled correctly
extensions/calibre-search/src/ebooks.ts EPUB/OPF parsing helpers and calibredb argument builder; well-tested and correct
extensions/calibre-search/package.json Extension manifest is well-structured with $schema, metadata, and preferences; title-casing and category look appropriate
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
extensions/calibre-search/src/add-to-library.tsx:237-246
**Unbounded concurrent thumbnail processes on load**

`useEffect` calls `loadThumbnail` for every ebook simultaneously. Each uncached EPUB spawns a `unzip` process, and each uncached PDF/other spawns a `qlmanage` process. On a first load of a Downloads folder that contains 50+ ebooks, this creates a burst of 50+ concurrent child processes at once, which can spike CPU and memory noticeably. Consider processing thumbnails lazily (only for the currently-visible items) or batching them through a small concurrency pool.

### Issue 2 of 2
extensions/calibre-search/src/add-to-library.tsx:221-226
**Synchronous blocking I/O inside `useMemo`**

`useMemo` runs synchronously during React's render phase. `scanDirectories` calls `readdirSync` and `statSync` on every file in each configured directory — also synchronously. For a Downloads folder with hundreds of mixed files, this blocks the React render thread until all `stat` calls complete, causing a noticeable freeze on mount. Moving the scan into a `useEffect` + `useState` pair (or using `useAsync` from `@raycast/utils`) keeps the UI responsive while the scan runs.

Reviews (3): Last reviewed commit: "Fix author name truncation and align ext..." | Re-trigger Greptile

Comment thread extensions/calibre-search/src/add-to-library.tsx Outdated
Comment thread extensions/calibre-search/src/add-to-library.tsx
Comment thread extensions/calibre-search/CHANGELOG.md Outdated
Comment thread extensions/calibre-search/src/types.ts Outdated
Comment thread extensions/calibre-search/eslint.config.js Outdated
Comment thread extensions/calibre-search/package.json Outdated
- Update build artifacts
- Address Raycast store review feedback
@BrunoMiguelMonteiro
Copy link
Copy Markdown
Author

Addressed all Greptile feedback: replaced spawnSync with async execFileAsync, added error handler on qlmanage, removed manual Preferences interface, fixed eslint.config.js, Title Case on preference titles, and {PR_MERGE_DATE} in CHANGELOG.

@raycastbot
Copy link
Copy Markdown
Collaborator

This pull request has been automatically marked as stale because it did not have any recent activity.

It will be closed if no further activity occurs in the next 7 days to keep our backlog clean 😊

@raycastbot raycastbot added the status: stalled Stalled due inactivity label May 4, 2026
@BrunoMiguelMonteiro
Copy link
Copy Markdown
Author

All feedback from the Greptile review has been addressed in commit 4580d07:

  • spawnSync → async: replaced with execFileAsync (promisified execFile) so the UI stays responsive during calibredb calls
  • qlmanage error handler: added proc.on('error', () => {}) to prevent uncaught exceptions on spawn failure
  • Manual Preferences interface: removed from both types.ts and add-to-library.tsx; using auto-generated types via getPreferenceValues<Preferences>()
  • eslint.config.js: updated to use defineConfig from eslint/config
  • Preference titles: updated to Title Case (Add Books, Add Books (Optional))
  • CHANGELOG.md: updated to use {PR_MERGE_DATE} placeholder

Would appreciate a re-review when time allows. Thanks!

@raycastbot raycastbot removed the status: stalled Stalled due inactivity label May 4, 2026
@0xdhrv 0xdhrv self-assigned this May 16, 2026
Copy link
Copy Markdown
Contributor

@0xdhrv 0xdhrv left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @BrunoMiguelMonteiro 👋

I have added a comment for you to address.

I'm looking forward to testing this extension again 🔥

Feel free to contact me here or at Slack if you have any questions.


I converted this PR into a draft until it's ready for the review, please press the button Ready for review when it's ready and we'll have a look 😊

Comment thread extensions/calibre-search/package.json Outdated
@@ -0,0 +1,89 @@
{
"$schema": "https://www.raycast.com/schemas/extension.json",
"name": "calibre-search",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: better to match with title

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @0xdhrv
I have corrected the name. Thanks for pointing that out! ;)

@0xdhrv 0xdhrv marked this pull request as draft May 16, 2026 01:20
Comment thread extensions/calibre-search/src/calibre.ts Outdated
Comment thread extensions/calibre-search/src/calibre.ts Outdated
GROUP_CONCAT(DISTINCT x, separator) is invalid SQLite syntax. Drop
DISTINCT (redundant given Calibre's normalised schema) and use ' & '
as separator so "Last, First" author names (e.g. "Tolkien, J.R.R.")
are no longer truncated to just the surname when split.

Also renames extension slug from calibre-search to calibre-library to
match the display title, per store review feedback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@BrunoMiguelMonteiro BrunoMiguelMonteiro marked this pull request as ready for review May 16, 2026 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new extension Label for PRs with new extensions platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants