close
Skip to content

Releases: DeusData/codebase-memory-mcp

v0.10.8

Choose a tag to compare

@github-actions github-actions released this 19 Aug 02:42
Immutable release. Only release title and notes can be modified.
46ae198

v0.10.8

Note on v0.10.7: this release supersedes v0.10.7, which was lost to a release-pipeline
publishing error (published under the tag 0.10.7 instead of v0.10.7; package installers
resolve the v-prefixed tag, and release immutability makes the name unrecoverable). The npm
and PyPI 0.10.7 packages are deprecated/yanked for that reason — their binaries were fine,
their download URLs were not. v0.10.8 carries the identical code content plus the pipeline
hardening that prevents a recurrence.

A community-heavy patch release: 19 pull requests merged since v0.10.6, most from
contributors. Thank you all!

Graph correctness

  • Cypher aggregates no longer undercount (#1196). Both truncation mechanisms are fixed:
    unlabeled scans stopped collecting candidates at max_rows before aggregation ran
    (#1323, @Enferlain), and relationship-expansion buffers were capped so aggregation never
    saw rows beyond an internal growth limit (#1698). count()/collect() now see the
    complete match set; max_rows limits only the rows returned, as documented.
  • Python aliased from-imports resolve to the real definition (#1371, @Joseph-MingEn).
    from .gate import execute as bridge_execute now produces a CALLS edge to execute
    itself rather than losing the call, and aliased base-class imports land on the real class
    node. On our django benchmark this recovered 26 INHERITS and 42 OVERRIDE edges with zero
    losses elsewhere, and left TypeScript graphs byte-identical.
  • Cross-language suffix matching for qualified-name lookups (#1647, @rudi193-cmd).
  • search_graph stops returning semantic-only ghosts — results backed by nothing but a
    similarity edge no longer surface as if they were definite matches (#1319, @JJordan0C).
  • List-valued fields extract correctly instead of collapsing to their first element
    (#1325, @Enferlain).
  • Index responses report persisted coverage truthfully (#1326, @Enferlain): an
    incremental run that does not revisit a file with recorded parse gaps no longer reports
    those gaps as vanished — the response now composes its skipped/parse-partial summaries
    from the stored coverage state, falling back to per-run data only if that read fails.

Windows

  • Non-ASCII search content no longer degrades to ? (#1704). The search_code raw scan
    pipes PowerShell output, and PowerShell 5.1 encodes that pipe in the console OEM
    codepage — so Cyrillic, CJK, or accented content turned into question marks depending on
    which console the server inherited. The pipe is now pinned to UTF-8 unconditionally.
  • search_code understands UTF-8 output paths and gains a context column for matches
    (#1253, @anfedoro).
  • Code search is bounded and cancellable — abandoning a query no longer leaves an
    orphaned scan running (#1608, @ertankucukoglu).

Platforms & tools

  • FreeBSD support (#1467, @PR9000).
  • list_projects pagination: a lean default response plus offset/limit and
    include_details for the full view (#1181, @tmonestudio).
  • Extensionless shebang scripts detect their language (#1203, @ibaldr89).
  • Index-mode capability rebuild (#1263, @astandrik).
  • is_test detection for tests/ directories (#1308) and a diff-aware clang-tidy
    hook
    (#1310, both @Yyunozor).

Release pipeline (the v0.10.7 lesson, hardened)

  • Release gates fail closed on cancelled jobs: a timed-out gate can no longer cascade into
    a silently skipped test matrix (#1719).
  • Malformed version inputs are refused preflight — a bare, non-v-prefixed version can never
    again publish an unresolvable tag (#1719).

Internal

  • Test harnesses use isolated daemon runtimes so suite runs cannot touch the account
    daemon (#1695, @astandrik); LF checkout contracts for shell entrypoints and git hooks
    (#1314 @mlandolfi90, #1699 with @xumian520); the stdin-gate regression tests no longer
    depend on the registry shipping a zero-argument tool (#1704).

Security Verification

Every binary published below was scanned by VirusTotal before smoke and soak testing, and the verdict for the exact shipped bytes is linked per product (decisive engines: 61–68).
Every shipped binary was clean.

Product Shipped binary VirusTotal verdict
linux-amd64 cb6dc545a8cb714799461ba7d8c223dbca7d02ca46ea5a4215c1beb450fd8e09 clean
linux-arm64 e861b4ae831a24ab69e82bb9c4ca8c70029af55b9a074ef0ed2565a53c0de24c clean
linux-amd64-portable 1175645cb30560e7e47d78611cd1bcb509478eaf6d4e51f72fe18327ee9c1351 clean
linux-arm64-portable 0bf1b3cf3659f6dcdb01bb6313a93dcbcb53e2cd1a52820f024df7a0cf48f44e clean
darwin-amd64 1d5b79257d91973809ee70482781db3d1a78f62fc1cd5d18a5ab0608451d16d4 clean
darwin-arm64 2412e017268bef8f847f38d1b0f79f63185b38c27fe6fba637067bfc87c0eedf clean
windows-amd64 b4b403b1d7c4def3785f148b93f345ce8427858f4f5489ce28580c4387a336a6 clean
windows-arm64 67b0341ee62f07f850d3954e4f387855f90ea8c6c4b7ed41b8a62d61344373a4 clean

Selection is tuple-local and defaults to stripped. The selected executable SHA-256 was verified again after packaging; archive containers were not redundantly submitted to VirusTotal. Their hashes remain available in checksums.txt.

Durable evidence: candidate provenance, candidate VirusTotal results, selection decisions.

0.10.7

0.10.7 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 18 Aug 18:22
Immutable release. Only release title and notes can be modified.
afebf00

Warning

Broken for npm/PyPI installs — superseded by v0.10.8. A publishing error released this under the tag 0.10.7 instead of v0.10.7. The npm/PyPI package installers resolve their downloads via the v-prefixed tag, which cannot be created retroactively (release immutability tombstones the name). Direct downloads from this page work normally — the binaries themselves are fine and fully verified. Use v0.10.8 or newer for package-manager installs, or scripts/setup.sh.

What's Changed

  • fix(extract): converge Function/Method is_test with the tests/ path filter by @Yyunozor in #1308
  • fix(hooks): scope pre-commit clang-tidy to staged changes (#1264) by @Yyunozor in #1310
  • fix(mcp): isolate semantic-only JSON search by @JJordan0C in #1319
  • fix(search): preserve compound requested fields by @Enferlain in #1325
  • fix(cypher): scan all unlabeled query candidates by @Enferlain in #1323
  • fix(registry): drop suffix_match CALLS across language boundaries by @rudi193-cmd in #1647
  • fix: rebuild index when mode adds capabilities by @astandrik in #1263
  • fix(daemon): add native FreeBSD process-image identity and /home log-path alias by @PR9000 in #1467
  • fix(mcp): restore scalable project discovery by @tmonestudio in #1181
  • fix(discover): detect extensionless scripts by shebang by @ibaldr89 in #1203
  • fix: preserve UTF-8 in search_code source by @anfedoro in #1253
  • fix(build): force LF line endings for shell scripts by @mlandolfi90 in #1314
  • fix: unbreak main — stdin-gate #1359 guards + Windows search_code UTF-8 pipe by @DeusData in #1704
  • fix(test): isolate harness daemon runtimes by @astandrik in #1695
  • fix(python): resolve aliased from-import CALLS to real def by @Joseph-MingEn in #1371
  • fix(cypher): expansion materializes every matched row — the cap falsified aggregates (#1196) by @DeusData in #1698
  • fix(mcp): bound and cancel Windows code search by @ertankucukoglu in #1608
  • fix(build): LF contract for extensionless git hooks + a line-ending guard by @DeusData in #1699
  • fix(index): preserve persisted coverage summaries by @Enferlain in #1326

New Contributors

Full Changelog: v0.10.6...0.10.7

Security Verification

Every binary published below was scanned by VirusTotal before smoke and soak testing, and the verdict for the exact shipped bytes is linked per product (decisive engines: 60–68).
Every shipped binary was clean.

Product Shipped binary VirusTotal verdict
linux-amd64 9f24d35e42d511c9d5de8f2f3a2c503bfce7e920901f94d0cff837d1371312cd clean
linux-arm64 ee517a1b83cda7232bf9f0e2d02807a25207937796bde26dd1dd518be8fb7dd1 clean
linux-amd64-portable e9772b28473c11016e59d4dc272b8290deb1efe633c17eb942676f1595b5011e clean
linux-arm64-portable a516c044a59c2e8be40366c84aab2a04c2d112298f496f8204f498cbea7883ba clean
darwin-amd64 2d5b042b59189645e6975bd3e9772ec760a8368164223fdb85c55a9c67f1d2d2 clean
darwin-arm64 24c8b6ee8711e465db359c2ed3ba87c9c350a105f2e77f7d3e4c72b098cd43af clean
windows-amd64 2d55ab63c05011a6c00939fc79e17ae0432c4b1fe7675b6dcc86e242a1be437b clean
windows-arm64 c5d26ab2e4f59d7e7bc9fbfaa3e08c92127b5ea75c2b7942087edb8a49828fca clean

Selection is tuple-local and defaults to stripped. The selected executable SHA-256 was verified again after packaging; archive containers were not redundantly submitted to VirusTotal. Their hashes remain available in checksums.txt.

Durable evidence: candidate provenance, candidate VirusTotal results, selection decisions.

v0.10.6

Choose a tag to compare

@github-actions github-actions released this 17 Aug 14:12
Immutable release. Only release title and notes can be modified.
f9e95e3

codebase-memory-mcp v0.10.6

Two stories in one release: the 0.10.x indexing slowdown is gone, and the install
failures that survived v0.10.5 are fixed
— including every construct from the configs you
sent us. If cbm got slower for you since 0.9.0, or install still refused your Hermes,
goose, OpenCode, or Codex config, this is the release to take.

The indexing regression program (#1669)

Since 0.10.0, indexing large repos had drifted from slower to unusable — java 6× worse,
C# 2.6×, TypeScript 2×. The cause was not one bug but a family: per-file work that scaled
with the whole corpus. All of it is fixed, measured on the same host against the same
corpora as the reports:

  • Java 477 s → 86 s (elasticsearch): cross-file resolution rebuilt a registry of every
    definition in the corpus per file. It is now built once and shared, with a per-file
    overlay for local symbols.
  • C# 1211 s → 450 s (dotnet/runtime), now with 48% more edges than 0.9.0: three
    corpus-proportional scans eliminated, plus an import-context bug that had been silently
    suppressing C# usage edges — one 147 KB generated file went from 490 s to 6.8 s.
  • TypeScript 37 s → ~24 s (microsoft/TypeScript): the expression-type evaluator
    re-evaluated shared subexpressions once per enclosing alternative — 2^n on tsc-compiled
    spread chains. A per-node memo makes it one evaluation per node; the pathological file
    from the TS conformance suite dropped from 20 s to effectively zero.
  • Linux memory blowup fixed (#1654): v0.10.4 could OOM a 36 GB machine indexing a tree
    v0.9.0 handled in 13 minutes. mimalloc's Linux arena-commit default is restored.
  • It stays fixed: a new complexity guard suite runs in CI on every platform and trips
    on counter ratios (never wall time) if any pipeline pass goes superlinear again, and
    CBM_PROFILE=1 now prints per-pass timings from any production binary.

Install: the constructs from your real configs

Hermes (#1631, reported by @iandol and Galaxy-VN, root-caused with an isolated repro by
@rg6304): four pieces of ordinary YAML made install fail permanently — empty flow
collections (plugins: [], tool_choice: {}), block sequences at column 0, double-quoted
strings continued with a trailing \, and mid-word apostrophes (LET'S GO in a persona
string opened a "quote" that never closed). All four are accepted now; quotes and
anchors are indicators only where a value begins, the same rule the * fix used in
v0.10.4. Both reporters' full configs — 15 KB each — install end-to-end with every
original byte preserved.

Entries we wrote ourselves are recognised again. Older cbm versions wrote command:
unquoted; the goose block gained a required field; your entry was then declared "foreign"
forever. An entry under our key that matches a shape any previous release wrote — or
whose command is our binary at a moved path — is repaired in place. Truly foreign entries
are still refused byte-untouched.

goose (#1673 + #1675): the extension block now carries the name field goose's parser
requires — before this, goose silently dropped the entry and the "successful" install was
invisible. envs: {} in a sibling no longer aborts the write (community fix by
@pcristin — a model contribution, merged as-is). Old blocks repair on upgrade.

OpenCode / annotated MCP entries (#1630, #1582): when a client adds keys to our entry
("enabled": true and friends), repairs now replace only the command value — comments and
client keys survive verbatim. And ownership comparison is separator-insensitive: an entry
storing C:\...\codebase-memory-mcp.exe is the same binary as the installer's
C:/.../codebase-memory-mcp.exe. @gotspatel's posted config was the file that cracked
this one after persistence across four releases.

Windows-authored configs with a UTF-8 BOM (#1656): PowerShell's Set-Content writes a
byte-order mark, and every YAML edit failed on such files regardless of content — the
reporter proved content-independence with a 26-byte file, and those 26 bytes were their
23-byte control plus exactly the BOM. It is treated as a prologue now: skipped for
structure, preserved on write.

Codex (#1633, closing @spam0115's residual from #1580): the hook reconciler accepts
the managed hook pair v0.10.2 wrote (including the Windows CRLF+BOM variant) and rewrites
it in place; refusals now name their reason instead of failing generically.

Windows: the DACL stops fighting you

The runtime directory's security descriptor was re-stamped on every process start,
whether or not anything was wrong. #1601 counted eleven no-op "Security change" USN
records against a single file in a day; #1620 lost atomic publishes to the rewrite window.
The re-stamp now fires only when the directory is not already in the exact owner-only
state — and directories damaged by the pre-v0.10.3 DACL regime (the empty-DACL logs
folder @patxisan found, which explained a month of unreadable 0-byte worker logs across
six reports) are detected and repaired in place. (#1416, #1601, #1620)

Also shipped: CBM_RUNTIME_DIR is forwarded in generated Codex configs (#1664 — a
relocated daemon was invisible to Codex-spawned servers), a missing final newline is no
longer reported as a partial parse, and update no longer names an installer that is not
there (#1653).

Credits

@iandol · Galaxy-VN · @rg6304 · @gotspatel · @spam0115 · @pcristin · @Carnival-z ·
@tmonestudio · @patxisan · @roosteer — the configs, ACL dumps, and minimal reproductions
in this release's issues did most of the diagnostic work. Thank you.

Security Verification

Every binary published below was scanned by VirusTotal before smoke and soak testing, and the verdict for the exact shipped bytes is linked per product (decisive engines: 60–68).
Every shipped binary was clean.

Product Shipped binary VirusTotal verdict
linux-amd64 749bd2c37c2ad891392e0872b9e1fb0df7432f04c7ca0f49d11d00b24c5f2ec8 clean
linux-arm64 e41cba76e58005edd4d21e19cbe1faf2c8f684c56fe78141c9956a9c632c9d26 clean
linux-amd64-portable 8eea4ec828cd0cfa1c406cda5640a8dfa5381878b4d96b106cdc53aff3733508 clean
linux-arm64-portable c783294c009186c1c91c79d3611ef991af4db7816dbad13a922538513af97cac clean
darwin-amd64 34851da132369455b35530879c13e95360429251ab5e9604bc301beb25c9bcc5 clean
darwin-arm64 8fdbdb2ec81f9526b34e71dffd46589b0e06fd5d60773732fd256c684d0251f4 clean
windows-amd64 3099e91c29d8507c94bfb7ed431a1f89459ad9afdcea413cbab23c9ec3cfd972 clean
windows-arm64 f5f0585308d7f6130386857e1747a338abe194cb9b082c37d81acf43b8f18e9d clean

Selection is tuple-local and defaults to stripped. The selected executable SHA-256 was verified again after packaging; archive containers were not redundantly submitted to VirusTotal. Their hashes remain available in checksums.txt.

Durable evidence: candidate provenance, candidate VirusTotal results, selection decisions.

v0.10.5

Choose a tag to compare

@github-actions github-actions released this 15 Aug 13:12
Immutable release. Only release title and notes can be modified.
7719563

codebase-memory-mcp v0.10.5

An install-and-startup release. If v0.10.4 refused to install for you, refused to write your
config, or told you something that turned out not to be true, this is the one to take.

Several of these are cases where cbm refused its own work — an installer directory our own
binary then rejected, a config entry we wrote ourselves and later called foreign, an error
message that named the wrong directory and sent people to inspect a file that was fine.

Windows: installs that refused themselves

The installer was creating a directory our own binary then rejected. install.ps1 made its
staging directory with New-Item, which inherits whatever %TEMP% carries. The downloaded binary
validates its own directory and refuses inherited cross-account mutation grants — so we handed our
own check a directory we had just made wrong. Measured on a Windows VM: a fresh staging directory
came up unprotected with five inherited ACEs; it now carries a single owner-only entry.

That is the acl-grants-cross-account-mutation to S-1-5-21-… failure. Reported by @RoccoZero,
@aecesr, @Kiborgik and @nasodaengineer, whose corrections stopped us fixing the wrong
thing twice — @Kiborgik warned that keying on the sandbox group's name would miss a synthesized-SID
variant, and @nasodaengineer disproved an off-by-one-RID theory by showing the ACE really was present
on the inherited DACL. @spam0115 independently wrote a working installer whose decisive line was
the same icacls /inheritance:r, and handed it back to us rather than keeping it.

Sandboxed applications no longer block the daemon. The ancestor walk refused any
mutation-granting entry on %LOCALAPPDATA%, including AppContainer identities left by ordinary
installed software. On reported machines the blocking entry resolved to a shipping desktop
application — nothing a user could reasonably remove. Ancestor components now tolerate AppContainer
package and capability identities; the private runtime directory keeps demanding the exact current
user, unchanged. Approach and the ancestor-only boundary follow @mlandolfi90's work.

Startup: when the daemon could not be reached

  • The rendezvous directory can be relocated in a shipped build via CBM_RUNTIME_DIR. Previously
    the only relocation hook was compiled out unless test seams were enabled — so a test build
    started where the product build did not, and when the default ancestry was unacceptable
    every invocation failed, config list included, leaving no way to reach the settings surface
    and fix it. (#1537, #1574, #1621)

    @tmonestudio and @Carnival-z each proposed exactly this, independently, before we built it
    @tmonestudio in #1574 with the ancestry walked and the offending component named, @Carnival-z in
    #1621 after finding that CBM_CACHE_DIR moves the cache but never the rendezvous. Both had opened
    pull requests reaching the same conclusion this change implements; the merged commit credits
    @tmonestudio by name for the approach and the variable name.

  • Refusal messages now name the directory that actually refused. The ancestor walk validates the
    directory it is already in, but printed the name of the child about to be entered — so #1537 was
    told .cache was at fault when the home directory was refusing, and #1621 was told
    cbm-daemon-501 when /private/tmp was. Both reporters inspected exactly what we named, found it
    clean, and said so. They were right, and we kept pointing at it for weeks. The message now
    names the containing directory and says explicitly not to check the one it used to blame.

Errors that name what actually refused

Three fixes, one complaint: our messages did not say enough to act on.

  • secure CLI coordination could not be created (endpoint) now prints the validation detail —
    the directory and the rule that refused. Four separate reporters hit that message; one built an
    instrumented binary to discover a single ACE was the cause.
  • A refused agent-config write says what the target is — whether it exists, and what kind of file
    it is. Nine distinct fail-closed conditions previously collapsed into one indistinguishable failure.
  • Neither prints errno. It is called from 119 sites and can be stale, which is exactly how an
    earlier release handed a reporter a fabricated "file not found" for a permission decision.

Config files we wrongly refused to touch

  • An MCP entry your client annotated is no longer treated as foreign (#1630, #1582). OpenCode
    writes "enabled": true beside the command and type we write; our ownership check demanded an
    exact key-set match, so a three-key entry with two recognised keys was classified as somebody
    else's and left alone — we refused to touch an entry we had written ourselves. In one reporter's
    file every MCP server carried the key, so this is OpenCode's normal shape, not an unusual hand-edit:
    anyone who has ever toggled a server on or off in the UI was hit.
  • YAML values containing * or & are no longer mistaken for aliases and anchors (part of #1631).
    Prose asterisks, a glob inside a description, a kaomoji — all were refused as if they began a node.
    The test is now positional. Root-caused by @rg6304, who reproduced it in isolation, read the
    source, and corrected our hypothesis: the constructs we had guessed appear nowhere in the failing
    file. This is one of four constructs in that report; the rest are still open.

Data loss and diagnosis

  • uninstall --help no longer performs a real uninstall (#1038). It removed the binary and every
    agent configuration for someone asking what the command does. The guard is checked before argument
    parsing, so a -y elsewhere on the line cannot auto-confirm the destruction being prevented.
  • A crashed worker's log now survives and names its run (#1145, #1130, #1132, #1450, #1133, #1070).
    Six reports ended at the same dead end: the supervisor prints the log path and the file is 0 bytes,
    so the one diagnostic that would explain the failure was silenced by the failure itself.
  • cli <tool> no longer blocks forever reading standard input (#1359) for a tool that declares no
    arguments. --json and --progress are stripped before the stdin fallback is reached, so
    cli list_projects --json hung too — the reporter's correction that "no flags" was not the trigger
    was right.

Reliability

  • Spawn retries no longer grow without bound (@moffermann). The clamp we shipped could never
    fire, while the doubling it was meant to bound ran free — a future budget increase would have meant
    a 40-second wait where the retry exists to avoid exactly that. Both current budgets are unchanged.
  • Two concurrent sessions can no longer be handed the same temporary directory
    (@ertankucukoglu) — a process-global buffer in the Windows temp-directory helper.
  • Instrumented test builds now know they are instrumented (@moffermann). Four places asked
    that question four different ways, so some sanitizer lanes measured instrumented code against
    native timing budgets.

Correctness

  • check_index_coverage no longer reports every path as unavailable when a repository has more
    than 2,000 ignored files (@SunneeYang). A truncated catalog was treated as proof that no
    per-path answer existed, including for paths with a current hash record.
  • Go routes built by string concatenation now resolve (@AmirF194). A handler registered with
    base + "/orders" produced no usable route path; the literal half is now recovered, and a path
    assembled from a variable is still left unresolved rather than fabricated.
  • Cypher queries repeating a variable-length node no longer double it (@jstar0), matching the
    unification the fixed-length path already did.
  • A Windows publish failure says what actually failed. The atomic publish discarded the Win32
    error and reported a bare errno, and one path returned PERSIST_FAILED with no log line at all —
    which is how a reporter with an ACL problem was told to check that their repository path existed.
  • Cross-repo intelligence works again on any project that has ever recorded a parse miss
    (@vitaliy-shatskiy, #1609). Indexing writes an internal <name>::missed row into the same
    database, and the validation required exactly one row over all of them — so such a project was
    rejected as "not indexed", both as source and as target, with no workaround available to the
    operator. The same defect was fixed for list_projects in #1044; this site never learned it.

Performance

  • Windows code search prefilters simple suffix globs (@ertankucukoglu), so a *.ext filter no
    longer scans and then discards. The pattern reaching the shell stays behind an allowlist, and the
    original post-scan filter is retained as a second guard.
  • A failed search launch no longer leaks its compiled path filter (@ertankucukoglu).
  • search_code can report per-phase timings on request (@ertankucukoglu) — scope_ms,
    scan_ms and enrich_ms, behind debug: true. Default output is unchanged, and the measurement
    itself is skipped unless asked for, so nothing is paid for by callers who do not want it.

Updating from 0.9.x is possible again

If you are on 0.9.x and update has been refusing to install, this is the release that fixes it
(#1134). v0.10.0 consolidated to one archive per platform, so the codebase-memory-mcp-ui-* names
that 0.9.x updaters ask for stopped existing and those updaters 404'd. We fixed that by publishing
byte-identical copies under the legacy names — but that step runs after checksums.txt is
generated and signed, so the aliases never appeared in it, and an updater that verifies the name it
asked for refused what it could not check:

warning: codebase-memory-mcp-ui-darwin-arm64.tar.gz not found in c...
Read more

v0.10.4

Choose a tag to compare

@github-actions github-actions released this 14 Aug 07:08
Immutable release. Only release title and notes can be modified.
c0bd4bb

codebase-memory-mcp v0.10.4

An install-and-diagnostics release. If v0.10.3 refused to install or start for you — particularly on Windows, or on a machine where you installed cbm through a package manager — this is the one to take.

Most of what follows came from people who filed precise reports and, in several cases, root-caused the bug before we did.

Windows: elevated accounts could not install or start at all

Running as an Administrators-group account meant install failed with activation transaction I/O failed: owner-not-current-user, or the MCP server exited during startup with nothing in the log but a closed transport.

The cause was ours and specific: we compared a file's owner against the token's user SID, but Windows stamps newly-created objects with the token's owner SID — which for any member of the Administrators group defaults to BUILTIN\Administrators. So the installer created its own staging file and then refused it, seconds later, as belonging to someone else. No amount of rebooting or closing processes could help, because nothing was running.

We now also accept the SID Windows actually stamps on what we create. This is narrower than "trust any administrator": a file owned by a genuinely different account is still refused. Reported by @spam0115 and @gotspatel, and it is very likely the cause of the long-running #1416 as well.

Installing no longer touches things it doesn't own

Two changes for people whose setup we were trampling:

A binary installed by mise, Homebrew, nix, asdf or cargo is left alone. Previously install dropped a second copy into ~/.local/bin — shadowing the managed one depending on PATH order — and appended to your shell rc file. Now it configures the agents and leaves the binary and your PATH untouched, update refuses honestly and names the command that will work (mise upgrade, brew upgrade), and PATH is only modified when we actually placed the binary. Reported by @SC-CTS.

You can choose which clients get configured. install wrote MCP config, agents, skills and hooks for every detected client, and reverting the ones you didn't want was pointless because the next install recreated them. --clients=claude,codex now restricts it, and --clients on its own lists every supported token. Reported by @PsyTech-Rob.

Errors that tell you what actually happened

Three fixes in a row here, all from the same complaint: our messages were confidently wrong.

  • An activation refusal no longer points at evidence it doesn't show. v0.10.3 correctly stopped blaming "active CBM sessions" for failures no session caused, but then told you to check errors that were never printed. It now names the directory and the rule that refused.
  • A server that cannot start says why. Client-path startup failures wrote to stderr only, which no MCP client surfaces — so a specific, nameable refusal reached you as "transport closed unexpectedly". Those failures now arrive as a JSON-RPC error carrying the reason.
  • The UI listener can be turned off without editing JSON. ui_enabled governs a loopback HTTP port, and the only way to disable it was hand-editing config.json; it was invisible to config list and rejected by config set. Both it and ui_port are now first-class config keys. Reported by @PsyTech-Rob, who spent two debugging sessions finding the switch.

Codex, OpenCode and config-file repair

  • A duplicated install no longer breaks Codex permanently (@astandrik). An owned inline hook assignment is reconciled into the canonical block instead of being ignored and re-added alongside; foreign hook entries are preserved untouched, and genuinely ambiguous TOML is refused without modifying the file at all.
  • OpenCode installs land in the file OpenCode actually reads (@iandol). Correction (2026-08-14): this is only half true and we should not have claimed it outright. The targeting is fixed — we now write whichever of opencode.json / opencode.jsonc already exists, instead of always creating a .json file OpenCode ignores. But the write itself still fails on v0.10.4 with error: agent_config agent=OpenCode op=mcp_install, reported on both Linux and Windows. Tracked in #1630. This is the second release running in which we have described this fix as complete; sorry, and thank you to the reporters who kept saying it was not.
  • An orphan marker we wrote heals itself. An earlier install could leave a closing # <<< marker with no opener, after which every install failed that client outright. Removal now strips the stray line. A write still refuses on an imbalance — with one marker there is no defensible region to replace.

Query correctness and platform support

  • OPTIONAL MATCH stopped silently dropping rows (@SEPURI-SAI-KRISHNA). Once the hop buffer saturated, the no-match rows — exactly what WHERE x IS NULL exists to surface — were discarded. Not a crash, not a memory error: quietly fewer results, with nothing to indicate the answer was incomplete.
  • FreeBSD resolves its own executable path (@PR9000), which the install and ownership checks depend on, plus a build fix for platforms outside the main three.

Security

The release pipeline now pins and verifies the external tooling it downloads before executing any of it, rather than trusting whatever the upstream project publishes at build time. Verification covers every platform the job may run on, from a single pinned reference.

Reported by Andrew Hundt (#1245).

Reliability

Subprocess spawns survive a busy machine. v0.10.3 started retrying a spawn the kernel refused with "try again", but only for about 30ms — enough for a momentary dip, not for a machine that stays process-starved for hundreds of milliseconds at a stretch, which is exactly when it happens. The retry now backs off exponentially to roughly half a second before giving up. A genuinely exhausted machine still fails fast rather than hanging, and real errors — a missing binary, a permission denial — fail immediately as before.

And the release pipeline no longer publishes its registry entry before the release is public — the bug that made v0.10.3's own registry step fail with a 404 against its own assets.

Upgrade

  • Binary installs: download below, or re-run install.sh / install.ps1.
  • Package managers: update through them as usual — cbm will now leave that binary alone.
  • npm / PyPI: as usual.
  • No index, cache, or config migration.

Contributors

Code in this release came from:

  • @astandrik — Codex hook reconciliation, with fail-closed handling that leaves an ambiguous config byte-identical rather than guessing
  • @PR9000 (Pedro Ramos) — native FreeBSD executable-path resolution, plus a build fix for platforms outside the main three
  • @SEPURI-SAI-KRISHNA — the OPTIONAL MATCH row-loss fix, including the analysis that separated "in bounds" from "correct"
  • Andrew Hundt — the release-pipeline hardening above, co-authored

And these reports found bugs we could not have found ourselves, several of them root-caused by the reporter before we looked:

@spam0115 and @gotspatel (Windows elevated accounts) · @SC-CTS (package-manager installs) · @PsyTech-Rob (four separate findings in one install cycle) · @listepo (the diagnostics that identified a refusal we had been guessing at) · @iandol (OpenCode config targeting)

Thank you — particularly to those of you who kept reporting through several releases of install trouble.

Full changelog: v0.10.3...v0.10.4

Security Verification

Before smoke and soak testing, VirusTotal completed 24 executable scans: stripped and unstripped candidates for each of the 8 release products. Every scan had at least 50 decisive engines (observed range: 59–68).
3 candidate(s) had only the documented single Microsoft machine-learning !ml result; no other decisive engine reported malicious or suspicious.

Product Stripped candidate Unstripped candidate Shipped
linux-amd64 clean clean stripped (09db4f424c1fca97b5d06feb75ca6540629a5b67309e39a9a551e745b081023b)
linux-arm64 Microsoft !ml clean debug-stripped (e0cd04812093d420a889397a603959c9a35ea3c78dea67c44db80e25a04d29b8)
linux-amd64-portable clean clean stripped (df1b97b0f5266924072a0c020027a14fa1890fa7457183c2106ff7eab4b62122)
linux-arm64-portable Microsoft !ml clean debug-stripped (8427e22d1445b1e4a9a883034c12c18eb78c30e6ba183235ca79e153641a39e9)
darwin-amd64 clean clean stripped (9ae79b267fe60438ffbba046bb5ed9e36b2b0f0c04e32970ee6995d616a8ccc6)
darwin-arm64 ...
Read more

v0.10.3

Choose a tag to compare

@github-actions github-actions released this 13 Aug 01:12
Immutable release. Only release title and notes can be modified.
0c64de9

codebase-memory-mcp v0.10.3

A fixes-only release, and most of it arrived as finished work from the community: six contributed pull requests are in here, alongside repairs for two regressions we shipped ourselves in v0.10.2.

Two things worth knowing before you upgrade. If you run more than one MCP client against the same project, this release closes a bug that could silently destroy a healthy index — start with the first section. And if installing or updating has been failing for you, three separate causes are fixed here: a permission rule that refused ordinary home directories, an error message that reported the wrong reason entirely, and Codex losing your cache directory. Several of those failed silently or blamed the wrong thing, which is why they survived multiple releases.

Concurrent instances no longer quarantine each other's databases

The worst bug in this release, fixed by @LynxBay. When two cbm instances raced on the same project — two editors, an editor plus a CLI call, a daemon and a stray session — the loser of the lock race could conclude the database was corrupt and quarantine it: renamed away, rebuilt from scratch, hours of indexing gone. The database was healthy; the integrity check just couldn't tell "damaged" from "busy" (#1206).

The same check had the opposite blind spot too: a database with genuinely torn pages passed as long as its top-level bookkeeping looked right, so real damage went unnoticed until queries misbehaved (#1037).

Integrity now returns a three-way verdict. Only confirmed corruption quarantines; a lock race says "project is busy; retry after indexing" and leaves the data alone; and a deep quick_check catches page-level damage the shallow probe missed. Both directions carry regression tests.

Graph determinism, twice

Two contributions from @Studnicky close two long-standing sources of run-to-run drift — the "same repo, slightly different edge counts" behavior tracked in our known issues since the 0.9.1 RC:

  • When the same logical edge is produced twice with different attributes (an LSP-resolved call and a textual match, say), the survivor was whichever arrived last — a function of thread scheduling. The merge is now a total order: higher confidence wins, ties break deterministically, and the outcome is independent of arrival order by construction.
  • CONFIGURES candidate collection sorted nothing before applying its cap, so which candidates survived depended on worker merge order. Candidates are now ordered by a pure content key first — notably not by node id, which looks stable but is itself handed out in merge order.

Windows: daemon files created with an empty ACL

@Kiborgik diagnosed and fixed a subtle one (#1351): the daemon's private directory combined a protected DACL with a non-inheritable ACE, which on Windows means children inherit nothing — every file created inside was born with an empty ACL and unreadable even by its owner. Directories now carry a properly inheritable owner-only ACE, so the strict security posture is kept and the files actually work. A companion fix from the same contributor closed a trap where a machine named like its user granted permissions to an empty principal; testing that on a non-domain-joined machine surfaced the mirror-image trap, so our build tooling now identifies the account by SID and stops resolving names altogether.

Repairs for two v0.10.2 regressions

Both reported within hours — thank you for the fast signal.

  • update --ui stopped working (#1544, @ehendrix23). v0.10.2 removed the obsolete ui/standard chooser and the flags that drove it, so a command living in scripts and muscle memory became a hard error. Both flags are accepted again — they do nothing, say so once, and genuinely unknown flags still fail.
  • The generated Pi extension broke Pi entirely (#1550, @musichen). Pi loads an extension by calling its default export; ours exported a named function instead, and a Pi extension that fails to load takes every pi command down with it, pi doctor included. The extension now default-exports its factory. Fixed independently by @musichen and @henri-edh as well, whose sharper description of Pi's loader is the comment now in our source.

Structured output stops dropping evidence

trace_path(include_evidence: true) promised per-hop strategy and confidence columns, and delivered them — in tree format only. With format: "json" both fields silently vanished, which hit exactly the callers most likely to want them: the ones consuming structured output programmatically (#1542, @asemraza). The JSON path now carries both fields with the same semantics, nulls standing where the tree format prints -.

Subprocess spawns survive a busy machine

Chasing a CI flake uncovered a real robustness gap: when the kernel refuses a process spawn with "try again" — a momentarily full process table on a loaded machine — cbm treated it as a permanent failure. A git probe or LSP server would refuse to start for a reason invisible to the user. Transient spawn failures now retry briefly; real errors (missing binaries, permissions) still fail immediately with unchanged semantics.

Install and activation: the refusal nobody could act on

Follow-up to #1537 (@listepo), and it turned out to be two defects stacked on each other.

The daemon refused to run when any ancestor of its cache directory was group-writable — the same rule we removed on the installer side in v0.10.2, in the sibling check that decision covers but that never got changed. A group-writable ~ or ~/.cache is ordinary (WSL2 ships 0775, so do several distro skeletons and any machine with a shared primary group), so for those users the daemon was permanently unusable, with nothing to close and nothing a reboot would fix. World-writable ancestors are still refused — any local user could swap a path component — and the private directory itself is still forced to owner-only, which is what makes admitting the ancestor safe.

Underneath that, the error message was inventing its own evidence: the refusal path set no error code, so the reporting fell back to printing whatever errno happened to hold, and handed the reporter ENOENT for a permission decision. They went looking for a missing file that was there the whole time. The message now names the directory and the rule that refused it.

Also in this area: the activation guard reported every refusal as "active CBM sessions could not be stopped", including failures where nothing is running at all. Those are now separate messages, the second says plainly that nothing needs closing, and neither remedy assumes a codebase-memory-mcp binary is still on PATH — advice that was unusable at exactly the moment it printed, right after uninstall.

Also fixed

  • Codex saw no cbm tools when CBM_CACHE_DIR was set (#1562, @anton-matosov). Codex passes only explicitly-listed variables into an MCP subprocess, so the server it spawned read the default cache while the daemon used the configured one; they disagreed and the connection closed during initialization. The generated config now forwards the variable.
  • The installed skill file failed to load in strict YAML readers (#1554, @xezzon). Its description contained Triggers on: unquoted, and a colon-space in an unquoted YAML scalar means "nested mapping" — so parsers rejected the whole document and the skill silently never loaded.
  • search_code echoed a negative limit back as the result count (#1511, fix by @lukiod), which reads to an agent as an answer rather than a rejected argument.
  • OpenCode installs went into the wrong file (@iandol). Correction: this was listed here in error. The fix merged a few hours after the v0.10.3 tag was cut, so it is not in this release — it ships in v0.10.4. If your OpenCode config is a .jsonc file, upgrading to v0.10.3 will not have helped, and we are sorry for the wasted time.
  • Release archives are validated before extraction (#1510, @cyphercodes): an exact member set, with symlinked members refused outright.

Upgrade

  • Binary installs: download below, or re-run install.sh / install.ps1 — re-running the installer is the update.
  • npm / PyPI: update through your package manager as usual.
  • No index, cache, or config migration.

Full changelog: v0.10.2...v0.10.3

Security Verification

VirusTotal completed 17 distinct extracted byte objects covering 56 exact extracted archive members.
The extraction manifest binds those associations to 14 downloadable archives by SHA-256 provenance. Downloadable .tar.gz/.zip release containers were not submitted to VirusTotal.

16 of 17 scanned objects returned 0 malicious and 0 suspicious verdicts with 57–68 decisive engine results (required minimum: 50).
1 object(s) carry a single Microsoft machine-learning detection (!ml), which this project treats as a known false positive and publishes rather than hides. Every other engine returned clean. See Antivirus False Positives for the evidence and for how to verify these artifacts yourself: objects/scan-c05a4598b3bb23d82efbde5e6bc01989297156ed153dadbd281ba8886c96f2d6--codebase-memory-mcp

Durable public evidence: associations, exact scan set, per-extracted-object results and report links, evidence checksums.

Archiv...

Read more

v0.10.2

Choose a tag to compare

@github-actions github-actions released this 11 Aug 17:08
Immutable release. Only release title and notes can be modified.
b377c62

codebase-memory-mcp v0.10.2

An install-and-upgrade release. If v0.10.0 or v0.10.1 refused to install, refused to update, or your MCP client showed a server that connected to nothing — this is the fix, and every one of those failures came from a user report filed in the last 24 hours.

The pattern behind all of them: gates that were right in principle refused ordinary, legitimate setups, and then didn't say why. Each one below keeps the protection that matters, drops the part that was refusing real users, and now names exactly what it refused and how to proceed.

npx (and every ephemeral install path) works again

Running cbm through npx codebase-memory-mcp produced a server that answered nothing: the client waited 30 seconds and exited with zero bytes on stdout, which agents surfaced as -32000: Connection closed. Every npx invocation hit this, deterministically.

The daemon verifies a connecting client's binary image, and it was treating two very different outcomes as one failure: "this image hashes differently than mine" (the tamper case the check exists for) and "this image cannot be examined at all" — which is what an ephemeral npx cache path always produces. The second is now admitted: the handshake immediately before it has already proven semantic version, build fingerprint, and protocol/store/feature ABI, so refusing on top of that traded a real compatibility proof for an unavailable one. A genuine fingerprint mismatch still rejects, hard, and the admission is logged out loud so the weaker check is never invisible.

Separately and unconditionally: a client that cannot reach the daemon now says so in JSON-RPC, naming the reason, instead of exiting silently. Thanks to @wassolles, who arrived with the reproduction, the admission path already read, and three candidate fixes — the one we shipped was theirs.

Installing into an ordinary Linux home works again

install.sh failed with error: failed to stage install candidate: activation transaction I/O failed — a message that sent people hunting disk errors and filesystem types for what was, in fact, a permission policy: the installer required no group-write bit on the install directory and every parent above it. WSL2 ships ~ and ~/.local at 0775, as do several distro skeletons and any site using a shared primary group.

World-writable parents are still refused — any local user could swap a path component mid-install. Group-writable parents are now warned about and accepted, while the install directory itself stays strictly owner-private: that is where the binary lands, and group write there would let another account replace the executable between verification and launch. Refusals now name the directory, its mode, and which rule refused.

Root-caused by @AmirF194 in a clean container, down to the exact predicate and line; independently confirmed by @shochdoerfer and @iandol.

Updating from 0.9.x works again

v0.10.0 consolidated to one archive per platform with the graph UI always embedded, but update still asked which variant you wanted — where "ui" could only 404, and "standard" quietly was the UI build. The chooser and its flags are gone.

Binaries already installed in the field can't be fixed retroactively, so releases now also publish ui-*-named copies of each archive. Every 0.9.x updater that asks for the old name gets the same bytes and completes normally, with nothing required from you. Reported by @iandol.

macOS install diagnostics

install.sh no longer prints No such xattr: com.apple.quarantine — a harmless line (a curl-downloaded archive simply carries no quarantine attribute) that was mistaken for the cause of an unrelated failure, to the point of becoming a bug report's title. And when installation is genuinely blocked by a running session, the error now points at codebase-memory-mcp daemon status to list the processes actually holding it, instead of asserting that sessions exist and leaving you to find them. Reported by @listepo.

Upgrade

  • Binary installs: download below, or re-run install.sh / install.ps1 — re-running the installer is the update.
  • npm / PyPI: update through your package manager as usual.
  • From 0.9.x: the old updater works again as of this release; if it already failed for you, re-running the installer is the fastest path.
  • No index, cache, or config migration.

Full changelog: v0.10.1...v0.10.2

Security Verification

VirusTotal completed 14 distinct extracted byte objects covering 32 exact extracted archive members.
The extraction manifest binds those associations to 8 downloadable archives by SHA-256 provenance. Downloadable .tar.gz/.zip release containers were not submitted to VirusTotal.

13 of 14 scanned objects returned 0 malicious and 0 suspicious verdicts with 55–66 decisive engine results (required minimum: 50).
1 object(s) carry a single Microsoft machine-learning detection (!ml), which this project treats as a known false positive and publishes rather than hides. Every other engine returned clean. See Antivirus False Positives for the evidence and for how to verify these artifacts yourself: objects/scan-cac31c5358f3a1dcccc4d4ccbe2591f6fbae58949d23bb341429a6197e93a64b--codebase-memory-mcp

Durable public evidence: associations, exact scan set, per-extracted-object results and report links, evidence checksums.

Archive SHA-256 provenance (from the extraction manifest):

Downloadable archive SHA-256 provenance
codebase-memory-mcp-darwin-amd64.tar.gz bb6cb47aea9e50e2193cdd917d5dbafa63b7d9c1cbe74bab5ec9bf4faa67e295
codebase-memory-mcp-darwin-arm64.tar.gz fa3ee085485fd9c16d1c1bd8a102df518862dabd2d6a09e4c6d8dfb3cd2a7eb4
codebase-memory-mcp-linux-amd64-portable.tar.gz 4ead161715fe959ef8a0e38946d63b1728d31e5fb1762a85dbb4b8c4abfbe481
codebase-memory-mcp-linux-amd64.tar.gz 6e3bb7353be21407a78e67b5465e53e3afb1a4a213e7a561606900ac08dcfdd6
codebase-memory-mcp-linux-arm64-portable.tar.gz dcd6f31f4004c25e7945b355ae23a5a381acb2a620301bca93e1ddb159b672fd
codebase-memory-mcp-linux-arm64.tar.gz b70148686cec55c31673fc0cebc0caf7f664f4ae29f7ba7f07b9617c2e5eaf85
codebase-memory-mcp-windows-amd64.zip 8f08e5c5b480e625adf9d4560765a860d493a690df6ded5b94127283ec5b660a
codebase-memory-mcp-windows-arm64.zip b77b81975021b879ca53cdd94c60b48cc5de102194b52117938a2187a42f89c6

v0.10.1

Choose a tag to compare

@github-actions github-actions released this 11 Aug 10:05
Immutable release. Only release title and notes can be modified.
564d32c

codebase-memory-mcp v0.10.1

A fast-follow fix release. If you use cbm through an MCP client — Claude Code, Codex, or any other spec-compliant client — upgrade now: in v0.10.0, the default output format of the core discovery tools rendered as an empty {} in exactly those clients. The graph was fine, the daemon was fine, the data was in the reply — but the part of the reply your client actually reads was empty. CLI usage was unaffected, which is precisely why this escaped the release gates.

Enormous thanks to @Navier8, whose #1522 reported this within hours of the v0.10.0 release — with a reproduction quality we wish every bug report had: same binary, same index, format-by-format call tables that localized the fault to the MCP response path before we had even read the code. The report named two bugs; the verification sweep it triggered found a third. All three are fixed here, and all three shipped in v0.10.0 sharing one failure shape: an empty result with a success status — the worst possible failure mode for an LLM client, which cannot distinguish "empty" from "nothing found" and silently draws wrong conclusions instead of seeing an error.

What was broken, and what changed

1. Tree-format tool replies rendered as {} in MCP clients (the default format — the primary path). A v0.10.0 wire-size optimization stopped duplicating tool payloads into structuredContent, leaving an empty object in its place — while every tool still declared a permissive outputSchema. The MCP spec tells clients: when a tool declares an output schema, structuredContent is the result. So search_graph, trace_path, query_graph, get_architecture, search_code, and detect_changes all returned {} to schema-honoring clients on every platform. The contract is now truthful end to end: no tool declares an outputSchema (tool output legitimately varies by the format parameter, so no static schema was ever honest), JSON-object payloads carry their parsed structuredContent, error envelopes keep their machine-readable structuredContent.error, and text-shaped payloads simply carry no structuredContent key — which also preserves the v0.10.0 win of never shipping the payload twice.

2. Seven or more pipelined requests killed the MCP server outright. Found while verifying the tool surface for this release: writing 7+ requests to the server in one burst — which is exactly what an agent issuing parallel tool calls does — overflowed an 8-frame input queue, and the overflow handler tore down the whole session: exit code 1, zero bytes of output, every already-computed response lost. A full queue is now backpressure: the reader simply stops accepting input until the worker catches up, and every request gets its answer. Verified with bursts of 7, 24, and 64.

3. config get answered every question with an empty string and exit 0. Unset keys printed nothing (while config list happily showed their defaults), and so did misspelled keys — a typo was indistinguishable from a correctly-read setting. config get now prints the stored value or the key's real runtime default, and unknown keys are an error (exit 1, with the known keys listed) on get, set, and reset alike.

Why the gates missed it — and what guards it now

The honest part: our own test for the structuredContent change pinned the broken behavior as correct, at both the unit level and in the shipped-binary smoke suite — a reminder that a test asserting the wrong contract is worse than no test. The release pipeline was green because the pipeline agreed with the bug. That class is now closed from three directions: the unit suite enumerates the entire tool table and binds all three envelope branches (absent / parsed object / error) for every registered tool, the frontend suite asserts that over-capacity pipelined input is answered without loss, and the smoke suite drives the real shipped binary the way a schema-honoring MCP client does — asserting a default-format reply can never render as {}, that no tool advertises an outputSchema, that a 24-deep pipelined burst gets 24 answers, and that config get returns real values. Every one of these was verified red against v0.10.0 before the fix and red again with the fix reverted.

Upgrade

  • Binary installs: download below, or re-run install.sh / install.ps1 — re-running the installer is the update.
  • npm / PyPI: update through your package manager as usual.
  • No index, cache, or config migration; v0.10.0 graphs are fully compatible.

Full changelog: v0.10.0...v0.10.1

Security Verification

VirusTotal completed 14 distinct extracted byte objects covering 32 exact extracted archive members.
The extraction manifest binds those associations to 8 downloadable archives by SHA-256 provenance. Downloadable .tar.gz/.zip release containers were not submitted to VirusTotal.

13 of 14 scanned objects returned 0 malicious and 0 suspicious verdicts with 58–67 decisive engine results (required minimum: 50).
1 object(s) carry a single Microsoft machine-learning detection (!ml), which this project treats as a known false positive and publishes rather than hides. Every other engine returned clean. See Antivirus False Positives for the evidence and for how to verify these artifacts yourself: objects/scan-3380cf3b868d749c63f564e7c6b81381a140942ec42253f785e158ab5144064f--codebase-memory-mcp

Durable public evidence: associations, exact scan set, per-extracted-object results and report links, evidence checksums.

Archive SHA-256 provenance (from the extraction manifest):

Downloadable archive SHA-256 provenance
codebase-memory-mcp-darwin-amd64.tar.gz 4948d92c5b5a906faee0fd11ffcbb8606a72004eece92f4b5a28e1294b306ab8
codebase-memory-mcp-darwin-arm64.tar.gz 9b6350b4e51cecd49126dc1b145ce81ac0df7aea35d87d7e8fe987683ad6b641
codebase-memory-mcp-linux-amd64-portable.tar.gz 97c6580a13d772d040e936584f3c5234586ab03f31a77354af8a763851a39a7f
codebase-memory-mcp-linux-amd64.tar.gz 57cb5e5945a5371e43db3f2184d5b08ddd679d65e285cb2c976e665eac2fb22f
codebase-memory-mcp-linux-arm64-portable.tar.gz ad457b306fa5bf5a1b97d160eeb867260a7946018097222a622fb14e896c6c72
codebase-memory-mcp-linux-arm64.tar.gz 5cb8a073c0e31956698a60ed4bd41c5398096ce3270b1438e7919d0cb06f558b
codebase-memory-mcp-windows-amd64.zip b9169d35f7d10485c449a2a8d6900a999ef5184fb93ab89b449dbe6e8f8c72a1
codebase-memory-mcp-windows-arm64.zip 9cedb3c4f01bf0846a712ff246ed1cd29d74ea7f7cda195d67dfaf7424f5a81b

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 10 Aug 17:43
Immutable release. Only release title and notes can be modified.
61b3b1b

codebase-memory-mcp v0.10.0

⚠️ Please use v0.10.1 instead. v0.10.0 shipped a critical MCP-client regression (#1522): the default output format of the core discovery tools rendered as an empty {} in spec-compliant MCP clients such as Claude Code. Everything below describes this release accurately — but the fix release supersedes it and is the one to install.

A milestone release since v0.9.0 — cbm's backend has been rearchitected around a shared coordination daemon, tool output was rebuilt into a compact tree format (~99% fewer output tokens on large results), the long-standing Windows memory ratchet is fixed and verified, and a new coverage system makes the graph's blind spots visible — introducing cbm's 15th tool, check_index_coverage, and a missed-code skeleton rendered right beside the code galaxy in the graph UI. Since the release candidate, the graph gained a new evidence-backed CALL_REFERENCE edge class, the Linux binaries' allocator override was found silently inactive and switched genuinely on, and every daemon/installer/Windows issue reported against the RC is fixed. Add three new community-contributed language surfaces, Swift cross-package resolution, a Nix extraction overhaul, and a broad community-driven correctness batch across the query engine, store, and extractors.

781 commits · 183 merged PRs · 42 contributors · 40+ community-reported issues fixed (v0.9.0…v0.10.0)

From release candidate to v0.10.0

This is the final release of what shipped as v0.9.1-rc.1 on 2026-07-30. It graduates as v0.10.0, not v0.9.1: a new backend execution model, a new tool, a new output format, and a new edge class are not a patch release, and the version number should say so. There will be no v0.9.1 final — this is it.

To everyone who ran the RC in their daily workflows: thank you — it worked exactly as hoped. The 1.5 weeks since the RC brought 335 commits across 76 PRs, and the most valuable of them started as your field reports. Daemon conflict handshakes that left a client hanging on "pending" (#1383), an installer that removed existing Claude Code hooks instead of adding its own (#1387), hook-augment silently emitting nothing (#1388), Windows install/uninstall refusing to stop active sessions (#1416), focus-stealing console windows from the detached daemon (#1427), a query response size that could kill the MCP server with no diagnostics (#1375), multi-key ORDER BY dropping LIMIT (#1334) — every one of these was reported against rc.1 by an RC user and is fixed in this release.

The coverage ask stands. The coverage system makes the gap between your code and the graph measurable — help us shrink it. Ask your agent to run check_index_coverage across your repositories (or click the missed skeleton's report-an-edge-case callout in the UI) and paste the resulting summary into a GitHub issue or discussion: miss classes, affected languages and file kinds, counts. That's aggregate numbers, not source code — everything stays on your machine unless you choose to paste it. Every real-world coverage summary points us at a concrete parser edge case, resolver gap, or language quirk we can fix — your repos are the test corpus we can't clone.

⚠️ Behavior changes

  • New edge class: CALL_REFERENCE — and CALLS now means exactly one thing. The graph now distinguishes invoking a callable from passing it as a value (app.register(pluginFn, opts)). CALLS is reserved exclusively for invocations; CALL_REFERENCE is emitted only when deterministic parser/LSP/registry evidence proves the exact callable value (occurrence-exact spans, lexical binding state, resolved symbol identity); ambiguous, shadowed, or dynamically rebound occurrences remain USAGE. Queries that assumed every callable relationship was a CALLS edge should account for the new label — and gain a precision they didn't have before: a CALL_REFERENCE edge is proof, not a guess.

  • One archive per platform — the UI is always included. The ui-* / non-UI variant split is gone: every platform now ships a single archive with the graph UI embedded, and the npm/PyPI packages include it by default (the CBM_VARIANT=ui opt-in from the RC is obsolete). Fewer artifacts, no wrong-variant downloads, one composition to verify.

Highlights

  • The coordination daemon — a backend milestone. Until now every cbm session was an island: each MCP server, CLI call, and hook opened the store on its own and knew nothing about its neighbors. As of this release, all of them coordinate through a per-user daemon — build/version conflict handshakes, indexing admission control, and a shared graph UI. New daemon start|stop|status CLI; a warm daemon removes per-command startup cost — measured 40–58% faster CLI commands on an 8.5M-node graph (~2.6 s saved per call). Hardened by RC field reports: every rejection path now answers the client with a reason instead of leaving it waiting. Beyond the immediate wins, this is the foundation the next releases build on: centralized controls for multi-agent workflows and local-only reporting/observability infrastructure — everything stays on your machine; nothing is sent anywhere.
  • Evidence-backed call graphs. The new CALL_REFERENCE edge class (see behavior changes) closes a long-standing precision gap: higher-order patterns — plugins registered by value, callbacks, handler tables — are now first-class graph relationships backed by deterministic evidence, while CALLS stops absorbing guesses. Optional include_evidence output shows why an edge exists: the resolution provenance behind it.
  • Tree-format tool output — TOON-compact, prefix-grouped rows with exactly-once pagination, real detect_changes impact reporting, and graph cycle detection. Measured ~99% fewer output tokens vs v0.9.0 on large query results — and MCP responses no longer duplicate their payload in structuredContent, roughly doubling the usable response budget on top.
  • Windows memory ratchet fixed (#581) — and the Linux override switched on. The allocator override silently compiled out under MinGW, so the CRT kept freed pages committed and long-lived daemons ratcheted memory for months. mimalloc now genuinely owns Windows allocations, thread heaps release at thread exit, and an out-loud ownership audit makes any future regression announce itself at startup. Verified on release artifacts: a 10-minute pure-query soak that measured 53× committed-heap growth on v0.9.0-era builds now measures 1.06×. The same audit then caught the mirror image on Linux: shipped Linux binaries had never actually routed ordinary malloc through mimalloc — as of this release they do.
  • One install, 43 coding agents — the installer automatically (or conditionally, where a client's documented markers are present) configures 43 agent and client surfaces — Claude Code, Codex CLI, Gemini CLI, Cursor, Zed, VS Code, Windsurf, Cline, Aider, Goose, Amp, Copilot CLI, Sourcegraph Cody, and 30 more — with pi and OpenCode extensions now generated straight from the tool registry. Experimental tool profiles (--tool-profile=analysis|scout) expose restricted inspection surfaces for lightweight scout agents. And it no longer touches what isn't its own: existing hooks are preserved even when a script rewrite is refused.
  • Honest coverage — the missed graph — what did not make it into the graph is now first-class, headlined by check_index_coverage — the 15th cbm tool: parse-coverage signals per file, deliberately-ignored files reported as a by-design class, coverage folded into index_status with notes on get_code_snippet, and a queryable miss graph persisted in the store. In the UI, the missed code renders as a skeleton beside the code galaxy — click-to-focus, with a report-an-edge-case callout.
  • New language surfaces — Perl LSP-tier semantic resolution, InterSystems IRIS ObjectScript support, and Mojo wiring — all three community-contributed — plus Swift cross-package IMPORTS resolved through Package.swift manifests and a two-part Nix extraction overhaul (function-rooted files no longer drop their definitions; attrpaths modeled with scoped qualified names).
  • Query engine robustnesscoalesce() and multi-arg scalar functions in WHERE, correct var-length path semantics with an advertised depth clamp, DISTINCT-before-LIMIT, the full multi-key ORDER BY list honored with LIMIT intact, composite/escaped property returns, a wall-clock execution deadline for runaway queries, and tools/list pagination for non-paginating clients.
  • Store & artifact integrity — a four-report series from one community member exposed torn WAL-mode exports, swallowed SQLITE_CORRUPT, stale WAL replay over fresh DBs, and invalid JSON on async edges; all four are fixed. Reindex publication is now atomic end to end — staged, verified, and quarantined on failure rather than replacing a good database with a broken one.
  • CI, completely wrapped up — local CI, PR CI, dry runs, and releases all execute the same canonical leg scripts, enforced by a venue-parity contract that turns any drift into a red build. Parallel per-suite test execution with a zero-loss gate, release-gating soak legs, per-run isolation, artifact attestation, and VirusTotal scanning of the real archive artifacts as a standard pre-release step.

What's changed

Coordination daemon & concurrency

This is the largest backend change since the project began: cbm's execution model moved from independent per-session processes to a coordinated per-user backend. Concurrent sessions coordinate through the daemon (daemon start|stop|status, permanent or session-managed) with authenticated IPC, build-fingerprint/version/cache-root conflict detection, phy...

Read more

v0.9.1-rc.1

v0.9.1-rc.1 Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 30 Jul 03:15
Immutable release. Only release title and notes can be modified.
ee9833d

codebase-memory-mcp v0.9.1-rc.1

A milestone release since v0.9.0 — cbm's backend has been rearchitected around a shared coordination daemon, tool output was rebuilt into a compact tree format (~99% fewer output tokens on large results), the long-standing Windows memory ratchet is fixed and verified, and a new coverage system makes the graph's blind spots visible — introducing cbm's 15th tool, check_index_coverage, and a missed-code skeleton rendered right beside the code galaxy in the graph UI. Add three new community-contributed language surfaces and a broad community-driven correctness batch across the query engine, store, and extractors.

438 commits · ~90 merged PRs · 25+ contributors · 30+ community-reported issues fixed (v0.9.0…v0.9.1-rc.1)

Why this one is a release candidate

This release changes cbm at a deeper level than a normal point release: the backend now runs through a coordination daemon (a fundamental shift in how every session, CLI call, and hook executes) and the memory/allocator layer was reworked on Windows. Both are extensively tested — the full CI gate, cross-platform soak legs, and benchmark verification all ran green on this exact build — but changes of this nature earn real-world mileage before a final tag.

Please run the RC in your day-to-day workflows and report anything that feels off — especially in multi-agent setups: several agents or editors hitting the same projects concurrently, long-running agent loops, parallel indexing, daemon start/stop cycles. Those concurrency paths are exactly what the new backend exists for, and field reports from them are the most valuable input for the final release. Nothing is too small to file.

A second ask: send us your coverage summaries. The new coverage system makes the gap between your code and the graph measurable — help us shrink it. Ask your agent to run check_index_coverage across your repositories (or click the missed skeleton's report-an-edge-case callout in the UI) and paste the resulting summary into a GitHub issue or discussion: miss classes, affected languages and file kinds, counts. That's aggregate numbers, not source code — everything stays on your machine unless you choose to paste it. Every real-world coverage summary points us at a concrete parser edge case, resolver gap, or language quirk we can fix, and each one fixed makes graph analysis more precise for everyone — your repos are the test corpus we can't clone. This is the single highest-leverage thing an RC user can send us.

And an apology on timing. We previewed this RC in discussion #1144 targeting mid-July, and it took clearly longer than we said. The reason is the nature of what's in it: the daemon was a genuine architecture shift, not a feature, and the memory work had to be verified rather than assumed — both had to be done right rather than quickly, and for a stretch they consumed nearly all capacity, which also slowed PR reviews and issue responses. A third, less visible reason: recurring antivirus false positives on release artifacts blocked several otherwise-green release runs in the final stretch. They never shipped — our gate requires zero detections — and this release scans clean; the full story is in Antivirus false positives on release binaries below. To everyone who contributed, reported, and waited (and nudged us — deservedly): thank you for the patience. The full explanation lives in that discussion thread.

Highlights

  • The coordination daemon — a backend milestone. Until now every cbm session was an island: each MCP server, CLI call, and hook opened the store on its own and knew nothing about its neighbors. As of this release, all of them coordinate through a per-user daemon — build/version conflict handshakes, indexing admission control, and a shared graph UI. New daemon start|stop|status CLI; a warm daemon removes per-command startup cost — measured 40–58% faster CLI commands on an 8.5M-node graph (~2.6 s saved per call). Beyond the immediate wins, this is the foundation the next releases build on: centralized controls for multi-agent workflows (scheduling, budgets, priorities across concurrent agents) and local-only reporting/observability infrastructure — everything stays on your machine; nothing is sent anywhere.
  • Tree-format tool output — TOON-compact, prefix-grouped rows with exactly-once pagination, real detect_changes impact reporting, and graph cycle detection. Measured ~99% fewer output tokens vs v0.9.0 on large query results — the difference between a result that fits in an agent's context and one that doesn't.
  • Windows memory ratchet fixed (#581) — the allocator override silently compiled out under MinGW, so the CRT kept freed pages committed and long-lived daemons ratcheted memory for months. mimalloc now genuinely owns Windows allocations (link-time wrap + static-CRT override), thread heaps release at thread exit, and an out-loud ownership audit makes any future regression announce itself at startup. Verified on release artifacts: a 10-minute pure-query soak that measured 53× committed-heap growth on v0.9.0-era builds now measures 1.06×, cross-checked green on macOS/Linux/Windows.
  • One install, 43 coding agents — the installer now automatically (or conditionally, where a client's documented markers are present) configures 43 agent and client surfaces — Claude Code, Codex CLI, Gemini CLI, Cursor, Zed, VS Code, Windsurf, Cline, Aider, Goose, Amp, Copilot CLI, Sourcegraph Cody, and 30 more — so cbm drops into whatever agent stack you already run. Alongside it, experimental tool profiles (--tool-profile=analysis|scout) expose restricted inspection surfaces so lightweight scout agents get a smaller, cheaper tool set (the first slice of the evidence-tier work previewed in #1144).
  • Honest coverage — the missed graph — what did not make it into the graph is now first-class, headlined by check_index_coverage — the 15th cbm tool and the first new tool since the core surface stabilized: parse-coverage signals per file, deliberately-ignored files reported as a by-design class, coverage folded into index_status with notes on get_code_snippet, and a queryable miss graph persisted in the store. In the UI, the missed code renders as a skeleton beside the code galaxy — click-to-focus to inspect exactly which files and regions the index couldn't fully parse, with a report-an-edge-case callout to send them our way. Agents (and you) can now see the boundary of what the graph knows — and every edge case you report makes it smaller.
  • New language surfaces — Perl LSP-tier semantic resolution, InterSystems IRIS ObjectScript support, and Mojo wiring — all three community-contributed.
  • Query engine robustnesscoalesce() and multi-arg scalar functions in WHERE, correct var-length path semantics with an advertised depth clamp (no more fabricated 100-hop paths from a self-loop), DISTINCT-before-LIMIT, composite/escaped property returns, a wall-clock execution deadline for runaway queries, and tools/list pagination for non-paginating clients.
  • Store & artifact integrity — a four-report series from one community member exposed torn WAL-mode exports, swallowed SQLITE_CORRUPT, stale WAL replay over fresh DBs, and invalid JSON on async edges; all four are fixed, plus atomic cache publish on the writer.
  • CI, completely wrapped up — the entire test infrastructure was unified: local CI, PR CI, dry runs, and releases now all execute the same canonical leg scripts, enforced by a venue-parity contract that turns any drift into a red build. Parallel per-suite test execution with a zero-loss gate, release-gating soak legs, and artifact attestation included. For users this means one thing: faster, more confident iteration — fixes and features can move from patch to verified release-shaped build much quicker from here on.

What's changed

Coordination daemon & concurrency

This is the largest backend change since the project began: cbm's execution model moved from independent per-session processes to a coordinated per-user backend. Concurrent sessions coordinate through the daemon (daemon start|stop|status, permanent or session-managed) with authenticated IPC, build-fingerprint/version/cache-root conflict detection, physical-job admission control for parallel indexing, and the graph UI served from the daemon. Because a per-user daemon is a security boundary, its IPC was hardened accordingly — on Windows, pipe clients are validated by process identity rather than impersonation (and the daemon reads a client's first frame before ever impersonating it), private-namespace objects are owner-stamped with the token user's SID, and DACLs are strictly validated; on POSIX, socket identity is checked against inode-pinned records. Everything remains strictly local. It is deliberately conservative in this RC — coordination, admission control, and lifecycle — but it is the substrate for centralized multi-agent controls and local-only observability going forward.

Preparation for worktree-native multi-agent workflows. The daemon is also the groundwork for how multi-agent setups actually run today: one agent per git worktree. Right now each worktree has to be indexed as if it were a separate repository — a full reindex of what is largely the same code. With the centralized daemon layer in place, upcoming releases will rework exactly this: worktrees become children of the main repository's graph, sharing everything unchanged and indexing only what differs — making the agent-per-worktree pattern dramatically cheaper in time and disk. This lands once the daemon has proven itself in the field, which is another reason your RC reports from worktree-heavy workflows matter. Release paths and verif...

Read more