feat: allow disabling built-in plugins + fix MCP server FTS5 crash#237
Conversation
Previously built-in plugins were hardcoded as always enabled with the
toggle disabled. Now:
- Toggle enabled for built-in plugins (removed disabled={isBuiltIn})
- Built-in enabled state loaded from plugin_registry DB table
- onToggle handler wired for built-in plugins (same as community)
- App.tsx filters built-in plugins by enabled state before passing
to PluginHost — disabled plugins won't load at runtime
- State re-checked on plugins:reload event
The DB infrastructure (plugin_registry table) and IPC handlers
(plugins:setEnabled/isEnabled) already existed but were unused.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR enables built-in plugin enablement/disablement in the desktop app by tracking state through Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as PluginCard UI
participant App as App Component
participant IPC as IPC Handler
participant Store as Plugin System
participant Toast as Toast Notification
User->>UI: Click toggle for built-in plugin
UI->>App: handleToggle(pluginId)
App->>Store: window.readied.plugins.setEnabled(pluginId, enabled)
Store->>IPC: Persist enablement to storage
IPC-->>Store: Persistence successful
App->>App: Update builtInEnabled map
App->>App: Trigger main window reload
App->>Toast: Show success toast
Toast-->>User: Confirmation displayed
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b2e08f4ced
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| const allPlugins = useMemo(() => [...builtInPlugins, ...discoveredPlugins], [discoveredPlugins]); | ||
| const allPlugins = useMemo(() => { | ||
| const enabledBuiltIn = builtInPlugins.filter(p => builtInEnabledMap[p.id] !== false); |
There was a problem hiding this comment.
Gate built-in plugins until enabled state is loaded
This filter defaults every built-in plugin to enabled while builtInEnabledMap is still empty, so PluginHost mounts disabled built-ins during initial render and only unloads them after the async listState() call finishes in the mount effect. In the startup path where a user has previously disabled a built-in plugin, its activate() logic still runs once per launch, which can cause unwanted side effects and contradicts the expected disabled behavior.
Useful? React with 👍 / 👎.
| setBuiltInEnabledMap(map); | ||
| })(); | ||
| }; | ||
| return window.readied.ipc.on('plugins:reload', handler); |
There was a problem hiding this comment.
Avoid clearing shared reload listeners on App cleanup
This subscription returns a cleanup from readied.ipc.on, and that API currently removes all listeners for the channel (removeAllListeners) rather than just this handler. During an App unmount/remount cycle (notably React StrictMode in development), cleanup here removes pluginRuntimeStore's own plugins:reload listener as well; because that store marks its listener as already attached, it does not re-register, so later reload events stop reloading runtime plugins.
Useful? React with 👍 / 👎.
sql.js (WASM) lacks FTS5, causing "no such module: fts5" when MCP write operations fire the notes_fts triggers. Since the MCP server runs as a standalone Node.js process (not inside Electron), native modules work without conflict. - Switch from sql.js to better-sqlite3 for full DB feature parity - Add FTS5 runtime check on startup (assertFts5Available) - Enable WAL mode for safe concurrent access with the desktop app - Remove saveDb() pattern (better-sqlite3 writes directly) - Add regression tests for FTS5 trigger execution (INSERT/UPDATE/DELETE) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…er cleanup (#239) ## Summary This commit was pushed to #237 after the squash-merge, so it didn't make it into develop. Cherry-picked here. - **P1: gate built-in plugins until enabled state loads** — `builtInEnabledMap` started as `{}` so `!== false` passed for every plugin, briefly activating disabled plugins on launch. Now starts as `null` and built-in plugins are excluded from `PluginHost` until `listState()` resolves - **P2: fix IPC listener cleanup** — `ipc.on()` cleanup used `removeAllListeners(channel)` which nuked other listeners on the same channel (e.g. `pluginRuntimeStore`). Changed to `removeListener` with the specific handler reference ## Test plan - [x] `pnpm typecheck` — clean - [x] `pnpm test` — all pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Release PR Merges `develop` into `main` to trigger a new release via semantic-release. ### Highlights since last release - **feat: allow disabling built-in plugins** + MCP server FTS5 fix (#237) - **fix: move @readied/* to devDependencies** — ASAR startup crash (#235) - **fix: exclude @readied/* from ASAR** (#233) - **feat: local HTTP API, quick capture, mermaid/math plugins** (#231) - **fix: replace removed lucide brand icons** (#229) - Multiple CI, type compat, and dependency fixes ### MCP server: sql.js → better-sqlite3 - FTS5 triggers now work (was crashing with `no such module: fts5`) - WAL mode for safe concurrent access with the desktop app - Runtime FTS5 check at startup with descriptive error ### Plugin system fixes (from code review) - Built-in plugins no longer briefly activate before enabled state loads - IPC listener cleanup no longer nukes unrelated listeners 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Built-in plugins can now be toggled on/off in settings; enabled/disabled states persist across sessions * Improved markdown editor URL auto-linking for more reliable link creation * **Bug Fixes** * Fixed URL auto-linking to correctly identify URLs when document content changes * **Tests** * Added comprehensive test suite for database trigger functionality * **Chores** * Migrated database backend for improved performance and stability <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
## Summary - **fix(mcp-server):** non-destructive FTS5 check + switch search to FTS5 MATCH (#241) - **fix:** unwrap getToken IPC result + use exact range for auto-link paste (#240) - **fix:** gate built-in plugins until enabled state loads + fix IPC listener cleanup (#239) - **feat:** allow disabling built-in plugins + fix MCP server FTS5 crash (#237) - **chore(deps):** sync postcss bump from main ## Test plan - [ ] CI passes (typecheck, lint, tests, build) - [ ] After merge, run Release workflow via `workflow_dispatch` 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Summary
sql.js(WASM, no FTS5) withbetter-sqlite3(native, FTS5 included). Write operations (create/update/trash notes) were failing withno such module: fts5because the FTS5 triggers in the database fired against a runtime that didn't support FTS5sql.jsapproach loaded the entire DB into memory, risking data loss on concurrent writes)builtInEnabledMapstarted as{}so!== falsepassed for every plugin, briefly activating disabled plugins on launch. Now starts asnulland built-in plugins are excluded fromPluginHostuntillistState()resolvesipc.on()cleanup usedremoveAllListeners(channel)which nuked other listeners on the same channel (e.g.pluginRuntimeStore). Changed toremoveListenerwith the specific handler referenceTest plan
pnpm test— all 17 suites passpnpm typecheck— clean across all packagespnpm build— builds successfullyreadied_create_note/readied_update_notework🤖 Generated with Claude Code