v3.5.0 — local write daemon, opt-in HTTP transport, and palace-cleanup tooling
This cycle adds two new ways to run MemPalace's write path and a set of tools for keeping a palace clean. An opt-in local daemon serializes background mines, diary saves, and hook ingests through a single process instead of racing for the palace handle, and an opt-in HTTP transport lets the MCP server run behind a long-lived HTTP client/proxy — loopback-default, with a Host/Origin DNS-rebinding guard and an optional bearer token. Three new MCP tools land alongside: mempalace_checkpoint (batch a whole session into one save), mempalace_delete_by_source (surgically purge mined benchmark/eval contamination — drawers and their index entries), and a source_file filter for scoped search. New transcript parsers (Continue.dev, Gemini CLI, Pi) and miner coverage for C#/PHP/Swift/Kotlin/Java widen what you can mine, and a batch of large-palace performance and reliability fixes round out the release.
Features
- Opt-in local daemon for queued writes.
mempalace daemonserializes all palace writes through one local process so background work stops racing the palace handle. Opt-in and local-only. (#1826) - Opt-in HTTP transport for the MCP server.
mempalace-mcp --transport httpserves JSON-RPC atPOST /mcp(withGET /healthz) for proxy/long-lived deployments. stdio remains the default; the HTTP path binds127.0.0.1, pinsHostand rejects non-loopbackOrigin(DNS-rebinding guard), and supports an optionalMEMPALACE_MCP_HTTP_TOKENbearer token. (#1801, #1806) mempalace_checkpointbatch-save tool. Files multipleadd_drawercalls plus an optional diary entry in a single MCP round-trip, verbatim, reusing the idempotent add/dedup path. (#1851)mempalace_delete_by_sourcebulk-cleanup tool. Exact-match, dry-run-by-default deletion of every drawer and its closet/AAAK index entries for asource_file— the recourse when benchmark/eval files get mined into a real wing. The dry run reports the blast radius; the commit writes a WAL audit entry. (#1722, #1729)- Optional
source_filefilter formempalace_search. Scope a search to an exact stored path; threaded through every search path so it never silently drops a match. (#1815, #1817) - New transcript parsers — Continue.dev sessions (#731), Gemini CLI / AI Studio (#204), and Pi agent JSONL (#169).
- Wider miner language coverage — C#/.NET, PHP (#1819), Swift/Kotlin (#1368), and Java project detection incl. rootless subprojects (#1720).
- Final mine on Claude plugin
SessionEndso the last exchanges are captured at session close. (#1814, #1820)
Performance
- Overview/status and
graph_statsanswered from the SQLite aggregate — fixes large-palace timeouts. (#1748, #1379) - Embedder caps ONNX-runtime intra-op threads so a background mine no longer pins every core. (#1068)
- SQL-pushdown pagination for
sqlite_exact(#1842) andpgvector(#1840), plus single-scroll bulk metadata for Qdrant (#1832).
Bug Fixes
- pgvector tolerates hostile transcript bytes — a lone surrogate (#1833) or NUL byte (#1829) no longer aborts the whole mine.
- Diverged-index recovery points at
repair --mode from-sqlite, not a re-mine — re-mining silently dropped MCP-added drawers and diary entries. (#1843, #1847, #1849) - Stale ChromaDB HNSW divergence routes to the SQLite fallback instead of failing the read. (#1816, #1822)
- The MCP server refuses a second writer for the same palace rather than racing the HNSW handle. (#1818, #1823)
- Windows hook miner spawns with
CREATE_NO_WINDOW— no console flash. (#1783, #1848) - Percent-encoded SQLite read-only URIs so spaced/special-char palace paths open.
CI
test-windowsretries only the transient ChromaDB HNSW compaction flake (--only-rerun); Linux/macOS keep zero reruns so real regressions stay loud. (#1854)
A big thank-you to everyone who contributed this cycle — many of these features and fixes came from the community, including several first-time contributors. Everyone is credited below.
What's Changed
- fix(migrate): roll back swap from pre-migrate backup on failure by @eldar702 in #1028
- feat(miner): add PHP ecosystem file extensions by @ManuelReschke in #1819
- feat(miner): add support for Swift and Kotlin file extensions by @EVSalomon in #1368
- fix: detect Java project manifests by @jsiu93 in #1720
- feat(normalize): add Continue.dev session parser by @sjhddh in #731
- feat: add Gemini CLI / AI Studio session import support by @FBISiri in #204
- feat: add Pi agent JSONL session normalizer by @adv3nt3 in #169
- feat(miner): add C# and .NET file extensions to READABLE_EXTENSIONS by @Davez69gto in #952
- feat: opt-in local daemon for queued MemPalace writes by @igorls in #1826
- fix(daemon): address post-merge review feedback on #1826 by @igorls in #1828
- chore(deps-dev): bump ruff from 0.15.15 to 0.15.18 by @dependabot[bot] in #1827
- perf: sqlite fast-path for overview tools + embedder thread cap (#1748, #1379, #1068) by @igorls in #1836
- perf(mcp): sqlite fast path for graph_stats (#1379) by @igorls in #1837
- fix: percent-encode sqlite read-only URIs for spaced/special-char paths by @igorls in #1838
- fix(pgvector): strip NUL bytes so a transcript NUL no longer aborts the mine (#1829) by @mvalentsev in #1831
- fix(pgvector): replace lone surrogates so a transcript surrogate no longer aborts the mine (#1833) by @mvalentsev in #1834
- fix(mcp): route _sqlite_graph_stats through sqlite_read_uri by @igorls in #1839
- fix(backends): push sqlite_exact get(limit, offset) pagination into SQL (#1841) by @mvalentsev in #1842
- fix(pgvector): push get(limit, offset) pagination into SQL (#1830) by @mvalentsev in #1840
- test(backends): live-substrate conformance module for pgvector by @jphein in #1769
- fix(tests): run fact_checker main via subprocess to clear runpy warning by @trek-e in #1798
- fix: use CREATE_NO_WINDOW so Windows hook miner spawns don't flash a console (#1783) by @eldar702 in #1848
- fix(chroma): route stale hnsw divergence to sqlite fallback by @fatkobra in #1822
- fix(repair): point index-read failures to repair --mode from-sqlite (#1843) by @mvalentsev in #1847
- fix: point diverged-index recovery at from-sqlite, not re-mine (#1843) by @undeadindustries in #1849
- chore(deps): bump docker/login-action from 3 to 4 by @dependabot[bot] in #1788
- chore(deps): bump docker/build-push-action from 6 to 7 by @dependabot[bot] in #1787
- chore(deps): bump docker/metadata-action from 5 to 6 by @dependabot[bot] in #1786
- fix(backends): single-scroll bulk metadata fetch for Qdrant; bump scroll page size (#1796) by @fatkobra in #1832
- fix(mcp): refuse second writer for same palace by @fatkobra in #1823
- feat(search): add an optional source_file filter to mempalace_search (#1815) by @mvalentsev in #1817
- feat: add mempalace_checkpoint batch save tool by @undeadindustries in #1851
- fix(claude-plugin): run final mine on SessionEnd by @fatkobra in #1820
- feat(mcp): add mempalace_delete_by_source bulk-cleanup tool (#1722) by @arnoldwender in #1729
- feat(mcp): add opt-in HTTP transport by @fatkobra in #1806
- ci(test-windows): retry the transient ChromaDB HNSW compaction flake by @igorls in #1854
- chore(release): 3.5.0 by @igorls in #1853
- Release v3.5.0 — promote develop to main by @igorls in #1855
New Contributors
- @ManuelReschke made their first contribution in #1819
- @EVSalomon made their first contribution in #1368
- @jsiu93 made their first contribution in #1720
- @FBISiri made their first contribution in #204
- @Davez69gto made their first contribution in #952
Full Changelog: v3.4.1...v3.5.0