• v0.28.2 76e8967c12

    code-index v0.28.2
    All checks were successful
    CI / cargo fmt (pull_request) Successful in 49s
    CI / OSS corpus tier-3 scale (nightly) (pull_request) Has been skipped
    CI / Grammar rebuild from source (nightly) (pull_request) Has been skipped
    CI / cargo doc (intra-doc links) (pull_request) Successful in 6m22s
    CI / cargo test (abi, 32-bit + wasm32) (pull_request) Successful in 6m25s
    CI / cargo check (MSRV 1.98) (pull_request) Successful in 7m6s
    CI / cargo deny (pull_request) Successful in 7m14s
    CI / cargo clippy (pull_request) Successful in 7m31s
    CI / cargo check (windows-gnu) (pull_request) Successful in 7m40s
    CI / OSS corpus (tier 1) (pull_request) Successful in 33m9s
    CI / cargo test (pull_request) Successful in 31m39s
    CI / cargo test (daemon transport) (pull_request) Successful in 8m6s
    CI / Plugin path cost + pool throughput (nightly) (pull_request) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (pull_request) Successful in 52m44s
    Release Build / Generate Version (push) Successful in 30s
    Release Build / Required CI green (push) Successful in 1m5s
    Release Build / Build linux-aarch64 (push) Successful in 14m20s
    Release Build / Build linux-x86_64 (push) Successful in 17m33s
    Release Build / Build linux-x86_64-musl (push) Successful in 17m46s
    Release Build / Pack the XAML reference package (push) Successful in 52s
    Release Build / Pack the Ruby language package (push) Successful in 59s
    Release Build / Pack the TimeLine package (push) Successful in 1m11s
    Release Build / Build windows-x86_64 (push) Successful in 21m9s
    Release Build / Windows archive smoke (msvc) (push) Successful in 8s
    Release Build / Create Forgejo Release (push) Successful in 4m24s
    Stable

    buildagent released this 2026-09-11 23:24:30 +02:00 | 244 commits to master since this release

    code-index v0.28.2

    Build: v0.28.2+760

    Installer: install.sh and checksum. Both come from this release commit. To pin the installed binaries too, run it with --tag v0.28.2.

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (bounded worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Maintenance fixes

    • Python receivers retain imported-origin rejection evidence even when another function rebinds the imported name. The two reported Django user.email references in #246 no longer point to an unrelated test application's User.email. Filtering happens after member uniqueness and does not turn an ambiguous candidate set into a new unique target.
    • Schema 68 re-decides existing Python bindings and advances committed content identity. Actual Flask and Django schema-67 upgrades match fresh schema-68 indexes without reparsing.
    • #263's historical package-identity acceptance is complete: all 379 historical losses and nine apps.ready sites have occurrence-level source evidence. The corrected loss classification is 301 false bindings removed and 78 correct coverage losses. A four-crate membership fixture now detects the actual M5 mutation.

    Validation and limits

    The nine-repository comparison for #246 preserves every reference population and changes exactly the two reported false bindings. Every other target and resolver rule is unchanged, including the 17 required #199 controls. Two correct ContentType property bindings are also explicitly preserved. The tier-3 measurement records only the resulting four counters at -2; cost and resolver-rule thresholds are unchanged.

    The Python inherited field remains unresolved; this release does not add inheritance traversal or general interprocedural type inference. #250's untyped storage.request.COOKIES chain is still unresolved. The historical #263 report explicitly retains the 78 coverage losses and four remaining locally derived apps.ready false bindings; adjudicating them does not mean they were repaired.

    Independent plugin package versions and package identities are unchanged. The pinned installer and its checksum ship with the release, and archive checks require every shipped executable to report the same version and build.

    The implementation and source evidence are in PR #266. Publication is gated on native Windows CI, Linux workspace and daemon-transport tests, and the OSS corpus checks for the tagged commit. Post-publication verification checks the actual installer and archives, both MCP transports, all nine corpus projections, and Flask/Django upgrades from the published v0.28.1 databases.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.28.2-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.28.2-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.28.2-linux-aarch64.tar.gz
    Windows x64 code-index-v0.28.2-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.2.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.2.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.2.0.cip --sha256 sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin check   sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin enable  sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79 \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.2.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed by this package. The TimeLine package below claims .dataset, .xsql, .shd and .lgd; all other markup remains text-only (searchable, no symbols).

    TimeLine plugin package

    de.h-dv.timeline-0.1.0.cip makes the four TimeLine definition formats carry symbols and references instead of being text-only: .dataset and .xsql through one language, .shd and .lgd through another, both out of a single sandboxed extractor. References resolve INSIDE a definition file; nothing in v1 crosses into the C# that loads it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.timeline-0.1.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the XAML package above, and the same key signs both.

    code-index plugin install de.h-dv.timeline-0.1.0.cip --sha256 sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin check   sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin enable  sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f \
        --capabilities same_file_candidate,exported_candidate
    

    No --bridges, and that is the package saying so: it declares none, so there is nothing to grant. The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.timeline-0.1.0.cip.digest.txt carries it and the extraction identity.

    The 5 fixtures shipped inside it are synthetic and modelled on the worked examples in the two format specifications. They carry no customer definition.

    Ruby plugin package

    de.h-dv.ruby-0.6.0.cip is the compiled-in Ruby extractor as an EXTERNAL, sandboxed package: tree-sitter-ruby loaded at runtime, the extractor compiled to wasm32-unknown-unknown and byte-reproducible from crates/guest/ruby/, and the same symbols, references, visibility and Rails association names the built-in produces.

    It claims .rbx, not .rb. The compiled-in Ruby plugin owns .rb, .rake, .gemspec, Rakefile and Gemfile, and a package may not claim a file a built-in claims. So installing this changes NOTHING about how your .rb files are indexed — it is the migration proof for running a full language out of a package, published so it can be read and run rather than described. Do not install it expecting to replace built-in Ruby support.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.ruby-0.6.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the packages above, and the same key signs all three.

    code-index plugin install de.h-dv.ruby-0.6.0.cip --sha256 sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048
    code-index plugin check   sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 --derived-names
    code-index plugin enable  sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 --derived-names \
        --capabilities same_file_candidate,exported_candidate,reachability_anchor,qualified_candidate,type_position_candidate,member_candidate
    

    --derived-names is required on check as well as on enable, and without it check REPORTS FAILED. Rails' has_many :posts emits a type reference named Post at the span of the literal :posts, so the name was not copied out of the source it points at; validation is all-or-nothing per file, so the authority is what admits the whole file rather than the one row. Withhold it and you keep the package with every Rails file refused — that is a supported answer, not a broken install.

    No --bridges: Ruby resolves inside its own language, so the package declares none. The six capabilities above are exactly what its manifest requests and enable refuses a grant wider than the request; grant fewer and the index stays searchable but resolves less, because every candidate pool a reference could be admitted to is one of them.

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.ruby-0.6.0.cip.digest.txt carries it and the extraction identity.

    The 5 fixtures shipped inside it were generated from the COMPILED-IN Ruby extractor, by a different author from the port they grade, and plugin check compares the package's facts against them exhaustively.

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. It signs every package above. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.28.1 340a75af85

    code-index v0.28.1
    All checks were successful
    CI / cargo fmt (pull_request) Successful in 47s
    CI / OSS corpus tier-3 scale (nightly) (pull_request) Has been skipped
    CI / Grammar rebuild from source (nightly) (pull_request) Has been skipped
    CI / cargo doc (intra-doc links) (pull_request) Successful in 3m57s
    CI / cargo test (abi, 32-bit + wasm32) (pull_request) Successful in 5m3s
    CI / cargo deny (pull_request) Successful in 5m49s
    CI / cargo check (MSRV 1.98) (pull_request) Successful in 5m54s
    CI / cargo check (windows-gnu) (pull_request) Successful in 6m2s
    CI / cargo clippy (pull_request) Successful in 5m59s
    CI / OSS corpus (tier 1) (pull_request) Successful in 25m46s
    CI / cargo test (pull_request) Successful in 26m39s
    CI / cargo test (daemon transport) (pull_request) Successful in 9m31s
    CI / Plugin path cost + pool throughput (nightly) (pull_request) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (pull_request) Successful in 53m15s
    Release Build / Generate Version (push) Successful in 37s
    Release Build / Required CI green (push) Successful in 1m23s
    Release Build / Build linux-aarch64 (push) Successful in 31m5s
    Release Build / Build linux-x86_64 (push) Successful in 34m50s
    Release Build / Build linux-x86_64-musl (push) Successful in 34m58s
    Release Build / Pack the Ruby language package (push) Successful in 51s
    Release Build / Pack the TimeLine package (push) Successful in 57s
    Release Build / Pack the XAML reference package (push) Successful in 1m7s
    Release Build / Build windows-x86_64 (push) Successful in 26m13s
    Release Build / Windows archive smoke (msvc) (push) Successful in 9s
    Release Build / Create Forgejo Release (push) Successful in 4m40s
    Stable

    buildagent released this 2026-09-11 18:57:54 +02:00 | 252 commits to master since this release

    code-index v0.28.1

    Build: v0.28.1+752

    Installer: install.sh and checksum. Both come from this release commit. To pin the installed binaries too, run it with --tag v0.28.1.

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (bounded worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Maintenance fixes

    This EBF ships the fixes merged in PR #264, plus the release version update in PR #265.

    • Query provenance identifies the SQLite content actually read, including its database incarnation and committed revision. Cursors are bound to that content, and compound queries disclose inconsistent snapshots. An older daemon that cannot report this evidence leaves it unavailable (#245).
    • Bounded working-tree observations distinguish detected changes and incomplete scans from a measured current index. The checks cover new, deleted, ignored and text-only files; they do not promise a complete filesystem snapshot (#260).
    • Python module, import, alias and conservative re-export resolution follows the proven module origin. Project modules shadowing standard-library names no longer receive the reported false bindings (#251). The imported views.serve case in #250 is repaired. Import-aware receiver narrowing is included, but the two real Django User.email sites in #246 remain wrong because an unrelated local rebinding suppresses their import evidence; the smaller regression fixture did not cover that shape.
    • Routing regression checks measure deterministic work instead of using a wall-clock floor that fails under contention (#253).
    • install.sh and its SHA-256 sidecar are release assets, audited against the tagged source before publication. Pin both the installer URL and its --tag argument (#261).
    • All four shipped executables, including code-index-plugin-host, report their version and common build identity. Archive checks derive the executable population from the archive and reject mixed versions (#262).

    Upgrade and coverage

    The database advances to schema 67. Existing Python bindings are cleared and resolved again; actual Flask and Django schema-65 database upgrades matched fresh indexes in validation. Allow reconciliation to finish after upgrading.

    The source-adjudicated comparison against v0.28.0 kept all nine reference populations unchanged, and all seven non-Python corpora were bind-for-bind unchanged. Django gained 1715 correct bindings, removed 1126 false bindings, lost 74 correct and 76 conditionally correct bindings, and corrected two targets. Flask gained 13 correct bindings, removed 10 false bindings, and lost two correct bindings.

    The accepted coverage losses involve composed exports, additional import roots, object/ancestry flows, runtime proxies, GIS configuration and task decorators. Query response costs and corpus measurements were recorded with explicit attribution; tolerance multipliers and the response drift allowance were not widened. Plugin package versions and package identities are unchanged.

    Remaining work

    The two User.email sites in #246 remain falsely bound, and the untyped storage.request.COOKIES chain in #250 is still unresolved. The historical before/after acceptance evidence and membership-isolation regression in #263 are separate follow-ups. This release does not claim these issues are complete.

    macOS remains unsupported (#59). Linux ARM64 is cross-built; the release workflow does not execute that archive on an ARM64 host. The release's download table reports which archives were actually published.

    Validation

    Publication requires green native Windows CI, Linux workspace and daemon-transport tests, and the OSS corpus gates on the release commit. The release pipeline runs plugin loading, timeout and trap-recovery checks against the supported executable artifacts, including the Windows archive after its artifact-store round trip. Post-publication checks verify the installer and downloaded archive checksums, executable versions and installation into an isolated prefix.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.28.1-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.28.1-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.28.1-linux-aarch64.tar.gz
    Windows x64 code-index-v0.28.1-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.2.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.2.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.2.0.cip --sha256 sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin check   sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin enable  sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79 \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.2.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed by this package. The TimeLine package below claims .dataset, .xsql, .shd and .lgd; all other markup remains text-only (searchable, no symbols).

    TimeLine plugin package

    de.h-dv.timeline-0.1.0.cip makes the four TimeLine definition formats carry symbols and references instead of being text-only: .dataset and .xsql through one language, .shd and .lgd through another, both out of a single sandboxed extractor. References resolve INSIDE a definition file; nothing in v1 crosses into the C# that loads it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.timeline-0.1.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the XAML package above, and the same key signs both.

    code-index plugin install de.h-dv.timeline-0.1.0.cip --sha256 sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin check   sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin enable  sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f \
        --capabilities same_file_candidate,exported_candidate
    

    No --bridges, and that is the package saying so: it declares none, so there is nothing to grant. The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.timeline-0.1.0.cip.digest.txt carries it and the extraction identity.

    The 5 fixtures shipped inside it are synthetic and modelled on the worked examples in the two format specifications. They carry no customer definition.

    Ruby plugin package

    de.h-dv.ruby-0.6.0.cip is the compiled-in Ruby extractor as an EXTERNAL, sandboxed package: tree-sitter-ruby loaded at runtime, the extractor compiled to wasm32-unknown-unknown and byte-reproducible from crates/guest/ruby/, and the same symbols, references, visibility and Rails association names the built-in produces.

    It claims .rbx, not .rb. The compiled-in Ruby plugin owns .rb, .rake, .gemspec, Rakefile and Gemfile, and a package may not claim a file a built-in claims. So installing this changes NOTHING about how your .rb files are indexed — it is the migration proof for running a full language out of a package, published so it can be read and run rather than described. Do not install it expecting to replace built-in Ruby support.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.ruby-0.6.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the packages above, and the same key signs all three.

    code-index plugin install de.h-dv.ruby-0.6.0.cip --sha256 sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048
    code-index plugin check   sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 --derived-names
    code-index plugin enable  sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 --derived-names \
        --capabilities same_file_candidate,exported_candidate,reachability_anchor,qualified_candidate,type_position_candidate,member_candidate
    

    --derived-names is required on check as well as on enable, and without it check REPORTS FAILED. Rails' has_many :posts emits a type reference named Post at the span of the literal :posts, so the name was not copied out of the source it points at; validation is all-or-nothing per file, so the authority is what admits the whole file rather than the one row. Withhold it and you keep the package with every Rails file refused — that is a supported answer, not a broken install.

    No --bridges: Ruby resolves inside its own language, so the package declares none. The six capabilities above are exactly what its manifest requests and enable refuses a grant wider than the request; grant fewer and the index stays searchable but resolves less, because every candidate pool a reference could be admitted to is one of them.

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.ruby-0.6.0.cip.digest.txt carries it and the extraction identity.

    The 5 fixtures shipped inside it were generated from the COMPILED-IN Ruby extractor, by a different author from the port they grade, and plugin check compares the package's facts against them exhaustively.

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. It signs every package above. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.28.0 017c6d875d

    code-index v0.28.0
    All checks were successful
    CI / cargo fmt (push) Successful in 52s
    CI / OSS corpus tier-3 scale (nightly) (push) Has been skipped
    CI / Grammar rebuild from source (nightly) (push) Has been skipped
    CI / cargo doc (intra-doc links) (push) Successful in 6m41s
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 6m46s
    CI / cargo deny (push) Successful in 7m52s
    CI / cargo check (MSRV 1.98) (push) Successful in 8m16s
    CI / cargo clippy (push) Successful in 8m24s
    CI / cargo check (windows-gnu) (push) Successful in 8m40s
    CI / OSS corpus (tier 1) (push) Successful in 31m58s
    CI / cargo test (push) Successful in 38m9s
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 50m57s
    CI / cargo test (daemon transport) (push) Successful in 15m6s
    CI / Plugin path cost + pool throughput (nightly) (push) Has been skipped
    Release Build / Generate Version (push) Successful in 31s
    Release Build / Required CI green (push) Successful in 1m3s
    Release Build / Build linux-aarch64 (push) Successful in 12m34s
    Release Build / Build linux-x86_64 (push) Successful in 15m1s
    Release Build / Build linux-x86_64-musl (push) Successful in 15m34s
    Release Build / Pack the XAML reference package (push) Successful in 51s
    Release Build / Pack the Ruby language package (push) Successful in 58s
    Release Build / Pack the TimeLine package (push) Successful in 1m10s
    Release Build / Build windows-x86_64 (push) Successful in 20m21s
    Release Build / Windows archive smoke (msvc) (push) Successful in 8s
    Release Build / Create Forgejo Release (push) Successful in 4m7s
    Stable

    buildagent released this 2026-09-10 23:39:06 +02:00 | 257 commits to master since this release

    code-index v0.28.0

    Build: v0.28.0+738

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (bounded worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Install, and update, with one command — NEW

    curl -sSfL https://git.h-dv.de/h-dv/code-index/raw/branch/master/install.sh | sh
    

    The same command does both. It asks this repository's release API for
    the latest tag; if that version is already installed it says so and
    downloads nothing.

    sh install.sh --check                  # installed vs published; writes nothing
    sh install.sh --tag v0.27.1            # a specific release, including an older one
    sh install.sh --prefix "$HOME/.local"  # default: /usr/local if writable, else ~/.local
    

    There is no self-update subcommand, deliberately: a self-update cannot
    install the first copy, so it can only ever be half a mechanism — and
    the half that rots while installs keep working.

    It refuses rather than guesses, and a refusal installs NOTHING.

    • It never installs bytes it has not verified against the published
      .sha256. If neither sha256sum nor shasum is available it
      REFUSES instead of skipping — a check that silently does not run is
      worse than none, because it reads as having run.
    • The four binaries are staged inside the target directory, verified
      there, and only then renamed into place, so a failure part way
      through cannot leave two new binaries beside two old ones.
    • The staged code-index is asked its own version BEFORE anything is
      replaced, so a wrong-libc or mis-rolled archive leaves your existing
      install untouched rather than bricking it with no way back.
    • An archive member that is a symlink is refused: a symlink resolves
      against YOUR machine, and the default prefix is /usr/local.
    • A destination that is already a directory is refused before the first
      rename, instead of writing inside it and reporting success.
    • macOS is refused by name (#59), Windows is named and pointed at its
      .zip, an unrecognised uname prints what it saw, and the libc
      decision is disclosed in both directions — including when it is a
      guess.

    Every one of those is graded against a real archive, and each arm
    asserts that nothing was installed — not merely that the exit code was
    non-zero. Most of them exist because an independent adversarial pass
    broke the first version of this script and the tests could not see it:
    four of those tests were satisfied by something other than what they
    named, each demonstrated with a mutation that survived.

    Which platforms it must handle is nobody's list: the published set is
    derived from the release workflow's own build matrices, and an archive
    that is neither installable nor waived by name fails the build.

    All three language packages are published — for the first time

    de.h-dv.ruby 0.6.0 ships as a release asset here. v0.27.1 published
    de.h-dv.xaml and de.h-dv.timeline and nothing for Ruby, while
    this repository's own docs called it product — because the audit's
    required-package list was a literal and could not grow when the tree
    did. That list is now enumerated from tests/packages/*/plugin.toml,
    so a fourth package is required the moment its directory exists.

    Installing it, in one command — a URL REQUIRES --sha256, and the
    digest is published beside the package in its .digest.txt:

    code-index plugin add \
      https://git.h-dv.de/h-dv/code-index/releases/download/v0.28.0/de.h-dv.ruby-0.6.0.cip \
      --sha256 sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 \
      --grant requested
    

    That digest is the recorded one, and the release REFUSES to publish a
    package whose packed digest differs from it — so it is the value the
    asset will have, not a guess. de.h-dv.ruby-0.6.0.cip.digest.txt ships
    beside the package if you would rather read it from there.

    --grant requested is what Ruby needs and the other two packages do
    not: requested means the manifest's whole request, and Ruby's includes
    [capabilities] derived_names, which is what admits the Rails
    association DSL. plugin check is RED without that grant and GREEN with
    it, and BOTH directions are graded — a smoke that only ever passes the
    flag proves nothing about the flag.

    BEHAVIOUR CHANGE: plugin update now compares versions

    Before this release plugin update compared no version at all: an
    OLDER package auto-applied as an update. Measured — 0.0.1 replaced
    9.9.9. It now refuses anything that is not strictly newer, and says
    which side it could not parse when a version is not comparable
    (#255).

    Also on the update path:

    • plugin add <url> now offers the [update] stanza in its payload,
      at the one moment the operator has both the id and the source URL in
      front of them (#257).
    • plugin update has operator documentation. It shipped with none, and
      nothing graded that a subcommand is documented; now something does
      (#256).

    A cold index of a Rust repository costs 36% less SQLite work

    One statement was 36.8% of an entire cold index of rust-ripgrep: the
    container rule's UPDATE refs … EXISTS(…), a correlated subquery
    re-walking every symbol declared above every ref in the file. It is a
    join off the module rows now.

    rust-ripgrep   vm_step 74,456,733 -> 47,462,831    -36.2% of the whole pass
      that statement 27,411,064 ->   404,127           -98.5%, x38 executions both sides
    rust-analyzer         880,065,547 -> 846,528,318    -3.81%
    

    The rust-ripgrep figure is checkable against this repository's own
    records: the 74,456,733 is what cost-baseline.json carried before this
    change, and an independent run after it measured 47,466,737 — 0.008%
    from the re-recorded value, which is inside the run-to-run jitter this
    gate documents. rust-analyzer is NOT priced by that gate, so only its
    post-change total was re-measured independently (846,638,064, 0.013%
    away); its before-figure is a single measurement and is reported as
    one.

    Every other statement in the top eight is identical to the digit, and
    the six priced repos that declare no Rust test module sit inside
    run-to-run jitter. The same statement runs on every single-file
    re-index, so saving a file with a mod tests in it went from about
    721,000 SQLite steps to about 10,600 on ripgrep-sized files.

    Bit 32 is the TEST role, which decides exclude_tests, so a shape that
    tagged a different set would be a correctness regression wearing a perf
    change's clothes. Counts cannot see WHICH refs carry the bit, so the ref
    projection — path, name, kind, line, col, roles — was compared
    binary-to-binary: rust-ripgrep 41,428 refs and rust-analyzer 410,278
    refs md5-IDENTICAL, with 14,804 and 27,609 test-bit-carrying refs as the
    non-vacuous population (#259).

    Honesty and gate fixes

    • Two ratcheted records that describe the same index must now agree:
      sum(stage-baseline.json rule.*) == baseline.json resolved, per repo.
      One resolver change moves several records, and re-recording only the
      one that fired left master's corpus job red for six commits (#248).
    • The agent-task bench pins correct_via_fallback exactly. It was
      recorded and compared by nothing, so answers reachable ONLY through
      the name-fallback channel could move silently (#249).
    • A per-link payload ceiling was measuring the temp directory's own
      path length rather than the payload (#252).
    • A conformance verdict dropped the bound a refusal named, so
      host.deadline_exceeded could not be told from a different limit
      hitting the same wall (#254).
    • read_code no longer says an empty body "PROVES the range does not
      exist". It proves it about the tree THIS SERVER indexes, which
      answer_provenance.indexed_trees names — if you are reading a sibling
      worktree, it is not a statement about your copy (#258).
    • cost_attribution covers all nine pinned corpus repos, not three, and
      selects one with COSI_ATTRIBUTION_REPO. A positional cargo filter
      that matches nothing exits 0 and reads as a clean run, which is how a
      cost was blessed that could name a change but not a statement (#259).

    Known gaps, stated

    • answer_provenance reports a commit read from git, so an index that
      has not caught up to the working tree still reports a clean tree at
      the new HEAD — a watcher-lag miss and a measured absence are
      indistinguishable (#260, with #245).
    • Two py-django phantoms and two lost correct binds remain diagnosed
      and unfixed (#250, #251).
    • macOS is still not built and not published (#59).
    • install.sh cannot yet be pinned to a release; it is fetched from the
      default branch (#261).
    • code-index-plugin-host does not answer --version, so it is the one
      shipped binary that cannot say which build it is (#262).

    Verify what you downloaded

    Every archive ships a .sha256 beside it, and every .cip ships
    .sha256, .digest.txt and a signature by the recorded first-party
    publisher key. install.sh checks the archive automatically.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.28.0-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.28.0-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.28.0-linux-aarch64.tar.gz
    Windows x64 code-index-v0.28.0-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.2.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.2.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.2.0.cip --sha256 sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin check   sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin enable  sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79 \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.2.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed by this package. The TimeLine package below claims .dataset, .xsql, .shd and .lgd; all other markup remains text-only (searchable, no symbols).

    TimeLine plugin package

    de.h-dv.timeline-0.1.0.cip makes the four TimeLine definition formats carry symbols and references instead of being text-only: .dataset and .xsql through one language, .shd and .lgd through another, both out of a single sandboxed extractor. References resolve INSIDE a definition file; nothing in v1 crosses into the C# that loads it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.timeline-0.1.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the XAML package above, and the same key signs both.

    code-index plugin install de.h-dv.timeline-0.1.0.cip --sha256 sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin check   sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin enable  sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f \
        --capabilities same_file_candidate,exported_candidate
    

    No --bridges, and that is the package saying so: it declares none, so there is nothing to grant. The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.timeline-0.1.0.cip.digest.txt carries it and the extraction identity.

    The 5 fixtures shipped inside it are synthetic and modelled on the worked examples in the two format specifications. They carry no customer definition.

    Ruby plugin package

    de.h-dv.ruby-0.6.0.cip is the compiled-in Ruby extractor as an EXTERNAL, sandboxed package: tree-sitter-ruby loaded at runtime, the extractor compiled to wasm32-unknown-unknown and byte-reproducible from crates/guest/ruby/, and the same symbols, references, visibility and Rails association names the built-in produces.

    It claims .rbx, not .rb. The compiled-in Ruby plugin owns .rb, .rake, .gemspec, Rakefile and Gemfile, and a package may not claim a file a built-in claims. So installing this changes NOTHING about how your .rb files are indexed — it is the migration proof for running a full language out of a package, published so it can be read and run rather than described. Do not install it expecting to replace built-in Ruby support.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.ruby-0.6.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the packages above, and the same key signs all three.

    code-index plugin install de.h-dv.ruby-0.6.0.cip --sha256 sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048
    code-index plugin check   sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 --derived-names
    code-index plugin enable  sha256:a6b8d7787cecb49c225ff3dda9016c96babc00c4cf59242a2d774c8b06672048 --derived-names \
        --capabilities same_file_candidate,exported_candidate,reachability_anchor,qualified_candidate,type_position_candidate,member_candidate
    

    --derived-names is required on check as well as on enable, and without it check REPORTS FAILED. Rails' has_many :posts emits a type reference named Post at the span of the literal :posts, so the name was not copied out of the source it points at; validation is all-or-nothing per file, so the authority is what admits the whole file rather than the one row. Withhold it and you keep the package with every Rails file refused — that is a supported answer, not a broken install.

    No --bridges: Ruby resolves inside its own language, so the package declares none. The six capabilities above are exactly what its manifest requests and enable refuses a grant wider than the request; grant fewer and the index stays searchable but resolves less, because every candidate pool a reference could be admitted to is one of them.

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.ruby-0.6.0.cip.digest.txt carries it and the extraction identity.

    The 5 fixtures shipped inside it were generated from the COMPILED-IN Ruby extractor, by a different author from the port they grade, and plugin check compares the package's facts against them exhaustively.

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. It signs every package above. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.27.1 f9ddfaf776

    code-index v0.27.1
    Some checks failed
    CI / cargo fmt (push) Successful in 53s
    CI / OSS corpus tier-3 scale (nightly) (push) Has been skipped
    CI / Grammar rebuild from source (nightly) (push) Has been skipped
    CI / cargo doc (intra-doc links) (push) Successful in 4m49s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m10s
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 5m22s
    CI / cargo clippy (push) Successful in 5m32s
    CI / cargo check (windows-gnu) (push) Successful in 5m56s
    CI / cargo deny (push) Successful in 6m15s
    CI / OSS corpus (tier 1) (push) Successful in 24m9s
    CI (Windows) / fmt + clippy + build + test (windows) (push) Failing after 34m10s
    CI / cargo test (push) Successful in 29m17s
    CI / cargo test (daemon transport) (push) Successful in 12m45s
    CI / Plugin path cost + pool throughput (nightly) (push) Has been skipped
    Release Build / Generate Version (push) Successful in 28s
    Release Build / Required CI green (push) Successful in 1m2s
    Release Build / Build linux-aarch64 (push) Successful in 12m20s
    Release Build / Build linux-x86_64 (push) Successful in 15m15s
    Release Build / Build linux-x86_64-musl (push) Successful in 15m50s
    Release Build / Pack the XAML reference package (push) Successful in 52s
    Release Build / Pack the TimeLine package (push) Successful in 1m3s
    Release Build / Build windows-x86_64 (push) Successful in 20m13s
    Release Build / Windows archive smoke (msvc) (push) Successful in 11s
    Release Build / Create Forgejo Release (push) Successful in 3m53s
    Stable

    buildagent released this 2026-09-09 09:26:47 +02:00 | 325 commits to master since this release

    code-index v0.27.1

    Build: v0.27.1+691

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (bounded worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    A patch release. Its headline is an asset that should have been in v0.27.0 and
    was not, and the gate that now makes that omission impossible to repeat.

    de.h-dv.timeline ships as a signed package

    de.h-dv.timeline is published as a signed .cip asset, pinned to

    sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    

    It teaches the index four TimeLine definition formats — .dataset, .xsql,
    .shd and .lgd — which stop being text-only and start carrying symbols and
    intra-file references: tables, columns, computed fields, arguments and their
    :name bindings for .dataset; display fields, XSQL tables and join structure
    for .shd and .lgd.

    Install it the way you install any package:

    code-index plugin install de.h-dv.timeline-0.1.0.cip \
      --sha256 sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    

    Enabling it re-extracts its claim domain. extraction_identity is new, so
    every .dataset, .xsql, .shd and .lgd in a project is extracted on
    activation. Measured on the corpus it was built against: 1,323 files, 87,528
    symbols, 142,614 refs. That is a real indexing pass, not instant, and it is
    worth choosing when it happens.

    It is signed with the same first-party key as the XAML package, which means
    an operator who has anchored that fingerprint installs it with no new trust
    decision, and plugin trust list marks it [BUILTIN]. That is a deliberate
    choice rather than an inherited one: the package lives in this repository, goes
    through these gates, is conformance-checked here, and runs sandboxed behind an
    explicit capability grant.

    Reproducibility, stated precisely. Its extractor.wasm is rebuilt from
    source and byte-compared wherever the suite runs, CI included — an absent wasm32
    target is a failure there, not a skip. What is NOT measured is the
    across-directory leg: cargo derives -C metadata from an absolute path, so
    proving it needs a comparison between two checkouts that no single cargo test
    can perform. That state is "not measured", which is not the same as "measured
    and bad".

    Why it was not in v0.27.0, and what stops that happening again

    The pack job did not exist. Nothing failed, because an asset that was never
    declared cannot be reported absent
    — the release audit refuses a missing
    required
    asset, and the required list named only the XAML package.

    That is now a gate. Dropping a package from the audit's required list fails with
    the sentence the omission deserves:

    a package the audit does not name cannot be reported absent — the release
    publishes without it and every gate reads green.

    Proven the only way that means anything: deleting the pack job makes the new
    audit refuse and name it, while the audit shipped in v0.27.0 exits clean on the
    same artifacts.

    Three surfaces stop reporting states they did not measure

    • plugin check --repo reported a file whose extraction DIED as a successful
      extraction.
      The repo leg read symbols, refs and imports off the guest's
      reply and discarded its diagnostics — the failure arm of the guest's own
      report, dropped at the boundary. It now carries a diagnostic census in which
      the count and the basis it was measured against are a single value, so no
      surface can render one without the other. An empty census is emitted as a
      measurement rather than omitted, because "none reported" and "not looked at"
      are different answers.

    • A measured absence now names the tree it measured. A tool answering
      symbol_not_found with empty_population: {basis: "measured"} was making a
      claim about a specific indexed tree and not saying which — worst for anyone
      working in a git worktree, whose own edits are not indexed and who therefore
      received a confident measured absence about somebody else's checkout. Errors
      that carry a measurement now carry answer_provenance with it; errors that
      carry no measurement stay short, which is the distinction that keeps this from
      becoming noise on every reply.

    • The host's grammarless states now name what they are. Two enum variants
      and an ABI guarantee described a package state no manifest can produce.
      They describe the runtime state that every package actually traverses, and a
      new gate drives all five states from real packages and compares them for set
      equality — so a state nothing reaches fails, and a state that no longer exists
      fails too.

    Honest limits

    The plugin ABI and the .cip package format remain EXPERIMENTAL and may
    change incompatibly in any release. A package is pinned to one thing — the host
    fact-ABI major it brackets — and to nothing else.

    Two findings from this round are filed and NOT fixed here. plugin enable
    fails on a project holding only files a package claims; and the plugin-wpf
    payload ratchet has absorbed 549 tokens across 36 commits, leaving eight tokens
    of headroom, undiagnosed. Each is recorded with its measurement rather than left
    to be rediscovered.

    A third was filed and fixed inside this release. Three guest-rebuild tests read
    their artifact from a hard-coded path while an inherited CARGO_TARGET_DIR
    redirected the child build. That splits into two failures and only the first was
    reported: on a clean tree the artifact is absent and the read panics, but on a
    tree that has ever built that guest, the leftover is read instead
    — measured at
    a 19,765-byte artifact from an earlier run, compared and passed green. A
    reproducibility test that reads whatever is on disk is not binding the artifact
    to its source, which is the whole property it exists to establish. The fix
    clears the variable rather than teaching the paths to follow it, for that
    reason.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.27.1-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.27.1-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.27.1-linux-aarch64.tar.gz
    Windows x64 code-index-v0.27.1-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.2.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.2.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.2.0.cip --sha256 sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin check   sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin enable  sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79 \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.2.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed by this package. The TimeLine package below claims .dataset, .xsql, .shd and .lgd; all other markup remains text-only (searchable, no symbols).

    TimeLine plugin package

    de.h-dv.timeline-0.1.0.cip makes the four TimeLine definition formats carry symbols and references instead of being text-only: .dataset and .xsql through one language, .shd and .lgd through another, both out of a single sandboxed extractor. References resolve INSIDE a definition file; nothing in v1 crosses into the C# that loads it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.timeline-0.1.0.cips too and keep the .cips beside the .cip. The same signature rules apply as for the XAML package above, and the same key signs both.

    code-index plugin install de.h-dv.timeline-0.1.0.cip --sha256 sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin check   sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f
    code-index plugin enable  sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f \
        --capabilities same_file_candidate,exported_candidate
    

    No --bridges, and that is the package saying so: it declares none, so there is nothing to grant. The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.timeline-0.1.0.cip.digest.txt carries it and the extraction identity.

    The five fixtures shipped inside it are synthetic and modelled on the worked examples in the two format specifications. They carry no customer definition.

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. It signs every package above. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.27.0 5cc15a61af

    code-index v0.27.0
    All checks were successful
    CI / cargo fmt (push) Successful in 47s
    CI / OSS corpus tier-3 scale (nightly) (push) Has been skipped
    CI / Grammar rebuild from source (nightly) (push) Has been skipped
    CI / cargo doc (intra-doc links) (push) Successful in 4m53s
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 5m18s
    CI / cargo deny (push) Successful in 5m15s
    CI / cargo clippy (push) Successful in 5m47s
    CI / cargo check (windows-gnu) (push) Successful in 6m12s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m51s
    CI / OSS corpus (tier 1) (push) Successful in 25m24s
    CI / cargo test (push) Successful in 30m14s
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 40m59s
    CI / cargo test (daemon transport) (push) Successful in 12m54s
    CI / Plugin path cost + pool throughput (nightly) (push) Has been skipped
    Release Build / Generate Version (push) Successful in 27s
    Release Build / Required CI green (push) Successful in 1m1s
    Release Build / Build linux-aarch64 (push) Successful in 12m25s
    Release Build / Build linux-x86_64 (push) Successful in 15m33s
    Release Build / Build linux-x86_64-musl (push) Successful in 15m42s
    Release Build / Pack the XAML reference package (push) Successful in 50s
    Release Build / Build windows-x86_64 (push) Successful in 20m23s
    Release Build / Windows archive smoke (msvc) (push) Successful in 8s
    Release Build / Create Forgejo Release (push) Successful in 2m54s
    Stable

    buildagent released this 2026-09-08 20:57:30 +02:00 | 330 commits to master since this release

    code-index v0.27.0

    Build: v0.27.0+679

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (bounded worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    The runtime plugin architecture becomes usable end to end; the Windows archive is
    rebuilt on a linkage where a guest trap is actually intercepted rather than
    fatal; and a round of dogfooding against this release candidate fixed eleven
    findings — ten places where a tool reported a state it had not measured, and one
    operator-facing measurement that had gone stale.

    A second package, de.h-dv.timeline, exists in this tree and is graded by CI —
    its extractor.wasm is rebuilt from source and byte-compared on every run — but
    it is NOT published as a release asset here. The only .cip this release
    ships is the XAML reference package. An operator who wants the TimeLine package
    must pack it themselves from the source tree; a signed asset for it is planned
    for the next release.

    Two further findings from that round are filed and NOT fixed here — an index that
    cannot see a git worktree's own edits, and a corpus bless writer with no arm for a
    record whose measurement reproduced while its conditions moved.

    149 commits since v0.26.1.

    Upgrading: existing conformance verdicts must be re-run

    This release records the WASM engine identity with the execution knobs it pins
    (epoch, fuel, stack, rsimd, rsimd_det, multimem, backtrace), not the
    wasmtime version alone. Those knobs decide how a package actually runs, so a C1
    verdict recorded without them is not provably transferable to this host — and every
    verdict recorded by v0.26.1 or earlier was recorded without them.

    On any machine that already holds conformance verdicts, code-index plugin doctor
    reports them as not current and WARNs, and plugin status shows not run here.
    Nothing is broken and no package changed; the record is simply less precise than
    the check now requires. A fresh install is unaffected — it has no prior verdict.

    Remedy, once per installed package:

    code-index plugin check <digest>
    

    plugin doctor names this case explicitly ("recorded before this host began
    pinning engine knobs — same wasmtime <version>") rather than reporting it as
    another engine, so the wording does not send you looking for a wasmtime change
    that did not happen.

    Upgrading: the first run after this release re-parses your code files

    A schema migration widens the recorded annotation region so a position inside a
    symbol's documentation resolves to the symbol it documents. That lower bound comes
    out of the parser and cannot be derived from stored rows, so the migration
    invalidates every code row and the next index pass re-parses them.

    Nothing is lost and no action is needed. The daemon answers throughout, and
    project_overview discloses the window while it runs — state: "reconciling" with
    a SCHEMA-UPGRADE REBUILD detail naming how many files still carry the
    invalidation sentinel. Counters read during that window describe rows being
    replaced, and the payload says so rather than letting you read them as settled.

    Text and metadata rows (Markdown, TOML, SQL, and the rest) are deliberately NOT
    invalidated — they carry no extraction, so re-hashing them would cost time and
    change nothing.

    Cost is proportional to code files, not to repository size on disk. A full
    re-parse of a large index has been measured at about ninety minutes; a few hundred
    files is seconds.

    The Windows archive is built natively now, and a guest trap is actually caught

    Until this release the Windows archive was CROSS-BUILT on Linux for
    x86_64-pc-windows-gnu and linked against the legacy msvcrt C runtime. On
    that linkage a WASM guest trap was not intercepted: instead of
    host.worker_trapped in milliseconds, the worker took 33 seconds and then
    died with abi.frame_truncated, leaving the host with a dead worker and no
    usable diagnosis. Every other platform we ship intercepts the same trap
    immediately and keeps the worker alive.

    The archive is now built natively on Windows with the MSVC toolchain, on the
    same runner that already smoke-tests it. Measured on the shipping
    configuration, one variable at a time:

    linkage trap verdict worker
    MSVC, static CRT (shipped now) 67.6 ms host.worker_trapped survives
    gnu + msvcrt (shipped through v0.26.1) 33,293 ms abi.frame_truncated dead

    Those timings are first-request figures and include worker spawn; steady-state
    repeat traps on the surviving configurations measured around 10 ms. The claim
    worth taking from the table is not the millisecond count — it is that the trap
    is intercepted at all and the worker is still alive to answer the next request.

    The archive name does not change, and neither does anything else you may
    have pinned: release archives are named <os>-<arch>, never by target triple,
    so the Windows asset is code-index-<tag>-windows-x86_64 before and after.

    It depends on no redistributable. The C runtime is linked statically, so the
    binaries import only DLLs present on a stock Windows 10 or later install. That
    is checked rather than assumed: a plain MSVC build imports vcruntime140.dll,
    which ships with the Visual C++ Redistributable and is not on a clean machine,
    and the release now REFUSES to publish an archive importing anything outside the
    stock set. Trading a trap bug for "the program can't start because
    VCRUNTIME140.dll is missing" would have been the worse regression, on the one
    path where the user has no toolchain.

    What this does not claim. The root cause is the C runtime, not the
    toolchain. A gnu build against UCRT also intercepts the trap and keeps the
    worker, and the one wasmtime build flag that looked like a suspect
    (__USE_MINGW_SETJMP_NON_SEH, which wasmtime defines for every
    target_env = "gnu" Windows build) is present in the working configuration too,
    so it cannot be the cause on its own. With that held constant the CRT is the
    only variable that moved. We ship MSVC because it is a supported configuration
    on a runner we already have — not because the gnu toolchain is at fault. UCRT on
    the gnu target does work, but it needs a UCRT-CONFIGURED mingw toolchain,
    headers and libmingwex included; swapping only the CRT import library is not
    enough and fails at wasmtime's own setjmp. Measured, with every attempt and
    its exact failure, in #231.

    Upgrading: the XAML package is 0.2.0 and its digest has MOVED

    de.h-dv.xaml is now 0.2.0, published as de.h-dv.xaml-0.2.0.cip, and its
    digest has moved to
    sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79.

    Re-pin it:

    code-index plugin install de.h-dv.xaml-0.2.0.cip \
      --sha256 sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    

    An operator who does not re-pin gets a bare digest_mismatch and no other
    explanation. The extraction_identity moved too, so every project with this
    package enabled re-extracts its .xaml files once — which is the point: files
    that were reported extract.truncated_tree are now indexed whole.

    Why it moved. The extractor's walk budget cut real markup at roughly 64-80 KB
    of source, depending on density — measured on a 14,056-file production repository
    where about fifty files were affected, including every theme dictionary. Symbols
    past the cut were missing from file_outline, search_symbols, find_references
    and change_impact, disclosed per file but easy to miss.

    All three budgets are now derived from the largest file the indexer will hand any
    extractor (2 MiB) rather than from the corpus of the day: the walk budget is 16 MiB
    of serialized tree, the output budgets 48,000 facts and 2 MiB of fact bytes. At
    2 MiB of dense markup the extractor emits 29,845 facts and reports nothing. Both
    truncation codes still fire, still mean different things, and are still
    distinguishable through index_coverage.

    The instrument, not just the fix

    The bug itself is one line of linkage. What let it ship in every release
    carrying a Windows archive is that the tested binary and the shipped binary
    were different builds, and nothing compared them.
    CI built its own gnu
    binaries natively and ran the plugin smoke against those; the archive users
    downloaded was cross-built and, until this cycle, had never executed a wasm
    guest at all.

    So the durable part of this change is not the CRT:

    • the archive is smoked with its own shipped bytes before publication, and
      the release job waits on that;
    • the smoke refuses to grade an artifact whose linkage does not match what
      the build leg declared — the refusal that turned this investigation into a
      finding instead of a confident wrong number, and it has correctly blocked
      publication twice;
    • linkage is now reported on two axes, toolchain and C runtime, because
      after this change both toolchains can import the same api-ms-win-crt-* set
      and a two-valued verdict would start lying in the opposite direction;
    • CI's own Windows smoke builds the same linkage as the shipped archive, so
      the two cannot drift apart again.

    Plugins

    A package can now be located, verified, installed, conformance-checked, enabled
    with an explicit capability grant, rolled back, disabled, removed and garbage
    collected, with every mutating command disclosing what it is about to do first.

    • A package may displace a builtin's claim, with consent recorded in
      [[displaces]] and the operator told what it costs. An undeclared intersection
      is still refused.
    • The package lifecycle is a committed number, ratcheted one rung at a time
      rather than asserted.
    • A refused package reaches an agent as a reason code, not as silence.
    • Reproducible guest wasm, byte-comparable from any directory.
    • A migrating daemon is distinguishable from a wedged one, and a wedged
      project has an exit.

    The architecture is proven on a real language rather than on markup alone: the
    full-language migration parity gate (#84) is closed.

    Honesty fixes found by dogfooding this candidate

    Eleven findings, filed and fixed against the release candidate itself.

    • doctor no longer renders "could not measure" as a verdict. PRAGMA integrity_check returning "unable to validate … : database is locked" said the
      check did not run and was reported as corruption — hardest exactly when an
      operator was most likely to run it, mid-reconcile. The opposite direction was
      also wrong: an error mid-iteration reported an all-clear.
    • doctor's freshness check counted never-indexable files as staleness — 35 of 35
      on this repository — producing a permanent WARN that hid real drift. It now
      splits the disk side by the same classifier index_coverage uses, and asks the
      project's own extractor set, so the two surfaces give the same verdict.
    • context_pack shipped over-budget responses with budget_exceeded: false. Six
      of eleven budgets were over; the block attached above the router was outside the
      arithmetic. The flag and the number are now one measurement of the bytes shipped.
    • changed_symbols reported a bare ref_count: 0 for symbol kinds this index
      measures as having no use channel, where four other surfaces disclosed it. The
      counter and its basis are now a single value, so no surface can render one
      without the other. direct_callers gained a basis of its own.
    • review_diff's same-package counterevidence was unreachable in every workspace
      and monorepo layout, because the root segment was stripped only when leading.
    • A declaration's leading DOCUMENTATION block is now part of it, in the six
      languages that mark one. get_symbol on a /// line answered symbol_not_found
      while the same query on a #[test] line one file over resolved, and a commit
      whose entire deliverable in a file was a correction to a recorded measurement
      reported symbols: []. Python and Ruby are excluded with reasons and tests:
      Python's docstring is already inside the span, and Ruby marks no comment as
      documentation — RDoc reads the same # syntax as # frozen_string_literal: true.
    • partial_sources now answers the sentence that cites it. The list of partial
      files was suppressed whenever a reply named none of them, so every reply carried
      a disclosure pointing at a field that was not there. An empty list is now the
      measurement that this reply names none.
    • One helper decides AND words the engine-drift distinction, across the three
      surfaces that render it. A verdict recorded before this host began pinning
      engine knobs is no longer reported as another engine.
    • search_text(whole_word=true) graded a different query from the one the daemon
      ran. Boolean and prefix expressions were matched as literal source characters and
      the resulting total: 0 was described as exact; ASCII-only matching lost Unicode
      case folding, so café missed a standalone CAFÉ while fix matched inside
      préfixé; and the census restated the matching rules a second time, so total,
      matches_in_file and the returned line numbers could describe different
      predicates. One compiled matcher now serves admission, census and line numbers,
      and an expression the post-filter cannot honour is refused with a reason instead
      of answered with a confident zero. Whole-word pagination also minted unstamped
      cursors, bypassing the stale-generation rejection.
    • The promotion-lock ceiling plugin enable discloses to operators was wrong at
      the 100k shape. Re-measured, with the cause established by removal rather than by
      reading, and the rollup census it pays for is now graded.

    One reported defect was refuted rather than fixed, and the counterexample is
    pinned so it cannot be quietly re-implemented: a builtin's auto-generated
    exclusion is NOT package-independent, because a consented [[displaces]] covers
    exactly the files the builtin excluded.

    Honest limits

    The plugin ABI and the .cip package format are EXPERIMENTAL and may change
    incompatibly in any release. A package is pinned to one thing — the host fact-ABI
    major it brackets in [abi].host_min/host_max — and to nothing else. No
    compatibility is promised or implied by this project's semantic version, in either
    direction.

    Epic #75 is not closed by this release. #80's final end-to-end gate has steps
    1–11 implemented and green and step 13 done, and step 12 has moved: the Windows
    archive is now BUILT natively and executed by a job whose verdict gates
    publication, so the platform is no longer cross-built and graded elsewhere.
    aarch64 remains UNMET by decision — there is no runner — and that is
    declared rather than silently skipped. #41 and #45 remain open.

    The TimeLine package's ACROSS-DIRECTORY reproducibility is unmeasured.
    de.h-dv.timeline's extractor.wasm is rebuilt from source and byte-compared
    wherever the suite runs, CI included — an absent wasm32 target is a failure
    there, not a skip. What is NOT measured is the across-directory leg: cargo
    derives -C metadata from an absolute path, so proving it needs a comparison
    between two checkouts, which no single cargo test can perform. That state is
    "not measured", which is not the same as "measured and bad".

    Packing determinism is verified separately and independently: the same
    checked-in bytes produce
    sha256:150ceb22ed9757a660d5a2bf58b80c81b60043cc419e5da5dde559d5d6fc9c9f on two
    different machines, directories and host binary builds.

    Package conformance is bounded evidence, not proof of semantic correctness.
    C1 stages a package alone with no capability grant; passing it says the package
    runs and responds within budget on its own fixtures.

    The promotion-lock constant is a flat rate over a cost that climbs with scale.
    It is sized to over-predict, which is the direction it is allowed to be wrong in,
    and at small generations it over-predicts by more than twice. lock_estimate is
    labelled PREDICTED at every call site.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.27.0-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.27.0-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.27.0-linux-aarch64.tar.gz
    Windows x64 code-index-v0.27.0-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.2.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.2.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.2.0.cip --sha256 sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin check   sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79
    code-index plugin enable  sha256:7b572f5cc32ffcd5af550900a451bbef37e255804776d7e3e3e71d2dd7d0aa79 \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.2.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed. .dataset and other markup remain text-only (searchable, no symbols).

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.26.1 45558875f7

    code-index v0.26.1
    All checks were successful
    CI / cargo fmt (push) Successful in 46s
    CI / Grammar rebuild from source (weekly) (push) Has been skipped
    CI / OSS corpus tier-3 scale (weekly) (push) Has been skipped
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 3m58s
    CI / cargo doc (intra-doc links) (push) Successful in 4m22s
    CI / cargo clippy (push) Successful in 5m1s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m27s
    CI / cargo check (windows-gnu) (push) Successful in 5m39s
    CI / cargo deny (push) Successful in 5m55s
    CI / OSS corpus (tier 1) (push) Successful in 15m20s
    CI / cargo test (push) Successful in 17m51s
    CI / cargo test (daemon transport) (push) Successful in 6m32s
    CI / Plugin path cost + pool throughput (weekly) (push) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 35m57s
    Release Build / Generate Version (push) Successful in 27s
    Release Build / Required CI green (push) Successful in 48s
    Release Build / Build linux-aarch64 (push) Successful in 12m36s
    Release Build / Build windows-x86_64 (push) Successful in 13m27s
    Release Build / Build linux-x86_64 (push) Successful in 15m22s
    Release Build / Build linux-x86_64-musl (push) Successful in 15m56s
    Release Build / Pack the XAML reference package (push) Successful in 52s
    Release Build / Create Forgejo Release (push) Successful in 2m52s
    Stable

    buildagent released this 2026-09-04 10:05:07 +02:00 | 479 commits to master since this release

    code-index v0.26.1

    Build: v0.26.1+574

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (sandboxed worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Every fix here is the same shape: a state the product could observe but
    had no way to report, so it reported the neighbouring state instead. All
    three were found by dogfooding v0.26.0 against this repository.

    Mistyped arguments now answer like every other argument error

    An MCP tool called with a wrong argument NAME has always answered with a
    structured error naming every accepted argument. A wrong argument TYPE
    did not: it fell through to the framework's own text —

    failed to deserialize parameters: invalid type: string "...", expected a sequence
    

    no error code, no hint, and not JSON at all, so a client that parses one
    could not parse the other. That is exactly the mistake a caller makes:
    passing a single value where a LIST is wanted, for arguments like
    task_terms, symbol_ids, handles and paths whose names read like
    they take one.

    A MISSING required argument had the same problem, one shape further
    along: find_callers with no arguments answered
    failed to deserialize parameters: missing field \symbol_id``.

    All three now answer in one envelope, read off the SAME published schema
    at the SAME boundary — so every registered tool and every declared
    argument is covered by construction, including the element types inside
    a list, and a tool added tomorrow is covered the day it is registered.

    The three are ordered by how much of your call is knowable, and the
    order is deliberate rather than incidental:

    1. an UNDECLARED argument, which has no declared type to be wrong
      against and no bearing on what is required — and a misspelled
      required argument is both defects at once, where naming both sides
      beats naming one;
    2. a MISSING required argument, because no amount of fixing types
      makes an incomplete call run;
    3. a WRONG TYPE, once the call is complete.

    Presence is not value: a required argument supplied as null is
    present, and is graded as a type. The two gates do not overlap.

    The leash actually holds on Windows

    code-index's test harness ties every daemon it spawns to the process
    that spawned it, so none outlives its fixture. On Windows that tie did
    NOTHING — attach returned an inert handle and kill_group had an
    empty body — and the suite that would have caught it was Unix-only, so
    the Windows leg reported running 0 tests. No implementation and no
    coverage, neither able to fail.

    Windows now gets a real Job Object: the job is created BEFORE the child,
    the child is started suspended and assigned while it is still frozen —
    so a grandchild it has not spawned yet cannot escape — and
    KILL_ON_JOB_CLOSE makes the operating system the killer, which is
    stricter than the Unix side, where a nanny process exists only because a
    Drop does not run when the holder is killed outright.

    A leash that CANNOT be established now says so, carrying what the OS
    reported, instead of being indistinguishable from one that was never
    asked for. The same conflation was fixed on Unix, where a child that
    leads no process group was also silently reported as "inert".

    This matters to you only if you run the test suite; it is why a Windows
    CI run could leave daemons behind.

    An admission that no rule proved says which it was

    The file watcher admits a path when nothing proves it should be skipped.
    There are two ways to reach that: the ignore rules were consulted and
    allowed it, or the path's relation to the project root could not be
    parsed at all, so no rule was ever applied. Those were the same number.

    They are now distinguishable. The verdict is UNCHANGED — an unparseable
    path is still admitted, deliberately, because reporting it as
    "deliberately excluded" would be its own lie — and a test now pins that
    so a future "repair" cannot quietly invert it.

    Also

    The release pipeline could not publish its own notes. Two defects, both
    of which produce a release whose changelog is not what its author wrote:

    • actions/checkout resolves a tag to the COMMIT it points at, so the
      annotation is absent in the runner even when the remote holds a real
      tag object. The tag ref is now re-fetched before the notes are read.
    • git tag -F runs git's default cleanup, which strips every line
      beginning with # — deleting every markdown heading from a notes
      file, silently. The pipeline now refuses notes with no heading and
      names --cleanup=verbatim as the repair.

    v0.25.0 shipped an internal narrative about zombie processes as its
    changelog because of the first of these. v0.26.0 caught it and refused
    to publish rather than publish the wrong text.

    Upgrading

    No action required, and no index schema change.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.26.1-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.26.1-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.26.1-linux-aarch64.tar.gz
    Windows x64 code-index-v0.26.1-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.1.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.1.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.1.0.cip --sha256 sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin check   sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin enable  sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.1.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed. .dataset and other markup remain text-only (searchable, no symbols).

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.26.0 e962b34b81

    code-index v0.26.0
    All checks were successful
    CI / cargo fmt (push) Successful in 46s
    CI / OSS corpus tier-3 scale (weekly) (push) Has been skipped
    CI / Grammar rebuild from source (weekly) (push) Has been skipped
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 4m21s
    CI / cargo doc (intra-doc links) (push) Successful in 4m26s
    CI / cargo deny (push) Successful in 5m26s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m35s
    CI / cargo clippy (push) Successful in 5m51s
    CI / cargo check (windows-gnu) (push) Successful in 5m54s
    CI / OSS corpus (tier 1) (push) Successful in 15m50s
    CI / cargo test (push) Successful in 18m22s
    CI / cargo test (daemon transport) (push) Successful in 6m44s
    CI / Plugin path cost + pool throughput (weekly) (push) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 38m3s
    Release Build / Generate Version (push) Successful in 19s
    Release Build / Required CI green (push) Successful in 58s
    Release Build / Build linux-aarch64 (push) Successful in 13m2s
    Release Build / Build windows-x86_64 (push) Successful in 13m48s
    Release Build / Build linux-x86_64 (push) Successful in 15m59s
    Release Build / Build linux-x86_64-musl (push) Successful in 16m26s
    Release Build / Pack the XAML reference package (push) Successful in 50s
    Release Build / Create Forgejo Release (push) Successful in 2m56s
    Stable

    buildagent released this 2026-09-04 08:43:11 +02:00 | 481 commits to master since this release

    code-index v0.26.0

    Build: v0.26.0+571

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (sandboxed worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Activation on demand

    A project holds .xaml files. You installed and enabled that package
    for a DIFFERENT project last week. Until now this one handed you
    text-only rows and said nothing about it.

    code-index now detects that case and tells you: a package in your store
    whose manifest claims an extension this project actually holds files
    for, and whose digest this project has not approved. The census is the
    same population symbol_blind_extensions reports, so the two cannot
    disagree with each other.

    Where you have ALREADY approved that exact digest in another project,
    the row is enabled without asking, and the grant written is the
    INTERSECTION of what you granted there with what the package requests
    here — never wider. Where there is no such basis it is OFFERED, not
    enabled: the first grant of a package stays a human decision, on every
    machine. A .cip found inside the repository never auto-enables, because
    cloning a repository must not activate code.

    A disable outranks the offer. plugin disable now writes a
    tombstone, and nothing in the machinery above can clear it — so a
    package you turned off here stays off, and the undo_command the
    disclosure names actually holds. (Nothing re-granted a disabled row in
    v0.25.0 either: there was no automatic enable at all. The tombstone is
    what makes the new behaviour safe, not a repair to the old one.)

    The daemon leaves an account of itself

    A daemon spawned by the MCP server runs with stdout and stderr on the
    floor, so for the whole life of any startup defect there was nothing to
    read. It now writes daemon.log beside its lockfile — bounded, with one
    rotated backup — and the client's "did not become ready" error names the
    path. The capability token is never written to it.

    Windows: your approval records move, by themselves

    Read this if you run code-index on Windows. The key that names an
    approval record was derived from canonicalize()'s output when the
    project directory resolved, and from the raw path when it did not —
    two different spellings of one project, because a record stores the
    plain root while canonicalize returns the \\?\ form.

    That was not theoretical. The key IS the record's filename, so any
    moment a project directory was not resolvable — a disconnected network
    share, an unmounted volume, a detached disk — the lookup computed a
    different key, found nothing, and every grant that project held appeared
    to have vanished. They came back when the share reconnected.

    The key is corrected, and records already on your disk are MIGRATED to
    it on the first read or write. Nothing is asked of you and no grant is
    lost: if the store cannot be written to, the record is still read at its
    old name. Other platforms are unaffected — their two spellings were
    always identical, so no file moves there.

    For package authors

    A guest can now map a kind NAME to a kind id without a new host call.
    Guests run with an EMPTY IMPORT LIST — that emptiness is what makes
    fork, open and connect inexpressible — so a guest cannot ask "what
    number is function_item?". It now asserts and the host checks: the
    guest exports one immutable kind_table_digest, and the worker
    enumerates the grammar it just loaded, in the same process that writes
    those ids, refusing on mismatch with exit 24 and printing the number the
    guest should have carried. The zero-import property is measured by
    counting the module's imports, not asserted in prose.

    attr_start_line now has a wire representation, and is_extension is
    deliberately still dropped: admitting it means authorising a package
    into the C# extension-method binding pool, which is a capability
    decision rather than a mapping one, and it is left as one.

    When a store holds more than one approved, resolvable digest of the same
    package id, only one of them can be live. Which one that is, and which
    digests it displaced, are now reported — previously the others simply
    did not run and nothing said so.

    Also

    • read_code with a mistyped range — path:60,200, a comma for the
      hyphen — answered internal_error and advised you to check whether
      the daemon or index DB was down. It now answers invalid_target and
      gives the syntax.

    Upgrading

    No action required, on any platform.

    No index schema change — nothing is re-indexed and no migration runs
    over your database; git diff v0.25.0..v0.26.0 touches no migration.
    The only thing that moves is the Windows approval record, on first use,
    and that is idempotent.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.26.0-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.26.0-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.26.0-linux-aarch64.tar.gz
    Windows x64 code-index-v0.26.0-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.1.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.1.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.1.0.cip --sha256 sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin check   sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin enable  sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.1.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed. .dataset and other markup remain text-only (searchable, no symbols).

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.25.0 5d5eba67cf

    code-index v0.25.0
    All checks were successful
    CI / cargo fmt (push) Successful in 45s
    CI / Grammar rebuild from source (weekly) (push) Has been skipped
    CI / OSS corpus tier-3 scale (weekly) (push) Has been skipped
    CI / cargo doc (intra-doc links) (push) Successful in 4m22s
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 4m28s
    CI / cargo clippy (push) Successful in 5m24s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m28s
    CI / cargo check (windows-gnu) (push) Successful in 5m35s
    CI / cargo deny (push) Successful in 6m15s
    CI / OSS corpus (tier 1) (push) Successful in 15m10s
    CI / cargo test (push) Successful in 16m52s
    CI / cargo test (daemon transport) (push) Successful in 6m11s
    CI / Plugin path cost + pool throughput (weekly) (push) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 32m42s
    Release Build / Generate Version (push) Successful in 18s
    Release Build / Required CI green (push) Successful in 56s
    Release Build / Build linux-aarch64 (push) Successful in 12m55s
    Release Build / Build windows-x86_64 (push) Successful in 13m5s
    Release Build / Build linux-x86_64 (push) Successful in 15m41s
    Release Build / Build linux-x86_64-musl (push) Successful in 15m44s
    Release Build / Pack the XAML reference package (push) Successful in 52s
    Release Build / Create Forgejo Release (push) Successful in 2m49s
    Stable

    buildagent released this 2026-09-03 08:43:46 +02:00 | 487 commits to master since this release

    code-index v0.25.0

    Build: v0.25.0+556

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (sandboxed worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Our key ships in the binary, and an agent can ask to install a plugin.

    Installing a package we publish takes one command

    v0.24.1 made packages verifiable and, in doing so, made anchoring a
    publisher the FIRST thing a new operator had to do — a trust add
    with a fingerprint fetched through a second channel, before an install
    that would otherwise refuse. Correct, and the wrong first impression:
    the ceremony that protects you from a stranger was charged to you for
    a package that arrived inside the same archive as the program.

    The first-party key is now compiled into the binaries.
    plugin trust list shows it as [BUILTIN]. plugin add de.h-dv.xaml-0.1.0.cip works on a machine with an empty trust store.

    It extends no trust you had not already extended — forging that anchor
    means forging the binary you are running — and anchoring a THIRD-PARTY
    publisher is still the deliberate act it was.

    It is revocable, offline, like any other key. plugin trust remove <fingerprint> on a built-in WRITES a denial into your trust directory
    rather than deleting a file that is not there, and the key stops
    verifying at the next load. Which mechanic runs is decided from the
    compiled-in bytes and never from a file's own builtin flag, so a
    hand-edited anchor can neither turn the withdrawal into a no-op nor
    let a delete quietly restore trust.

    The fingerprint stays
    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c.
    It is compiled in, committed in tests/packages/first-party.fingerprint,
    printed in these notes, and a gate compares all three — plus one that
    asserts the SHIPPED BINARY lists it, so drift is caught in the artifact
    and not only in the tree.

    plugin_add over MCP

    The CLI half shipped in v0.24.1; this is the other half, and its
    security property is different. On a terminal the human is the caller.
    Over MCP the caller is an agent that reads the repository — the
    untrusted party.

    So there is no approving argument. Inventing one is refused by the
    unknown-argument gate rather than dropped silently. A grant is a
    REQUEST; only the elicitation is an answer. A client declaring no
    elicitation capability gets confirmation_unavailable — no fallback
    and no auto-approve, because a tool that proceeds when there is nobody
    to ask is worse than one that does not exist. Decline, cancel and
    timeout all leave the user root and the project byte-identical.

    The daemon says when it has not looked yet

    project_overview could answer from the database while the live
    package set was still being discovered, and the reply was
    indistinguishable from a healthy project's: an active generation, a
    covered file, and the two package fields simply MISSING because both
    are omitted when absent. Measured at 9 failures in 10 runs under load.

    The daemon binding its listener before discovery finishes is the
    design. Not saying so was the defect. package_set_consulted is now
    on the block: false means nobody has looked yet — ask again — and
    carries the prose explaining it; true means an absent package field
    is a MEASUREMENT; absent still means a daemon that does not report it.

    index_host had the same shape one level down: a worker binary that
    disappeared between two stats produced a silent builtins-only pass
    wearing a line that read as a measurement, in the one state the pass
    policy exists to refuse. It re-measures and re-applies that policy now
    rather than deciding a second time.

    Three binaries stopped shipping a wasm compiler

    nm -C on the release's own build found 441 cranelift symbols in
    code-index, code-index-daemon and code-index-mcp. Cargo unifies
    features across the packages selected in ONE invocation, and
    code-index-plugin-host needs tree-sitter's wasm feature. The
    release builds in two invocations now; shared dependencies compile
    twice, which is the price of three binaries not carrying a JIT.

    Getting the package

    code-index plugin add de.h-dv.xaml-0.1.0.cip
    

    No trust add first. Keep the .cips beside the .cip.

    A signature says these bytes are the ones we signed. It does not say
    they are safe.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.25.0-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.25.0-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.25.0-linux-aarch64.tar.gz
    Windows x64 code-index-v0.25.0-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.1.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.1.0.cips too and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it. You do NOT need to anchor us first: this release's publisher key is compiled into the binary, so the install below works on a machine that has anchored nobody. code-index plugin trust list shows it, marked [BUILTIN], and code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c withdraws it — see About that key.

    code-index plugin install de.h-dv.xaml-0.1.0.cip --sha256 sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin check   sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin enable  sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd \
        --capabilities bridge_source \
        --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.1.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed. .dataset and other markup remain text-only (searchable, no symbols).

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically, and it is compiled into the binaries in this release. That trusts this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. It adds nothing you had not already granted — the bytes are inside the program you are running, so forging that anchor means forging the binary — but you are entitled to know it is there before a package installs rather than after.

    There is no expiry — deliberately, because offline installations must not break on a timer — and withdrawal is on your side and works: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. A compiled-in key has no file to delete, so that writes one instead, carrying denied = true; the key stops verifying at the next load, plugin trust list shows it marked [DENIED], and deleting that file (the command prints its path) is the only undo. If the key is ever rotated, the new fingerprint is published here and in tests/packages/first-party.fingerprint, and a build that predates the rotation will not trust it.

    You may anchor it yourself instead — code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'a label you choose', with code-index-publisher.pub from this release's assets. Your file replaces the compiled-in entry, and the --name is a label YOU choose: nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.24.1 b6f49f86dc

    code-index v0.24.1
    All checks were successful
    CI / cargo fmt (push) Successful in 46s
    CI / OSS corpus tier-3 scale (weekly) (push) Has been skipped
    CI / Grammar rebuild from source (weekly) (push) Has been skipped
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 4m13s
    CI / cargo doc (intra-doc links) (push) Successful in 5m7s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m15s
    CI / cargo clippy (push) Successful in 5m16s
    CI / cargo check (windows-gnu) (push) Successful in 5m51s
    CI / cargo deny (push) Successful in 6m45s
    CI / OSS corpus (tier 1) (push) Successful in 15m35s
    CI / cargo test (push) Successful in 16m48s
    CI / cargo test (daemon transport) (push) Successful in 5m18s
    CI / Plugin path cost + pool throughput (weekly) (push) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 32m36s
    Release Build / Generate Version (push) Successful in 17s
    Release Build / Required CI green (push) Successful in 1m0s
    Release Build / Build linux-aarch64 (push) Successful in 12m59s
    Release Build / Build windows-x86_64 (push) Successful in 13m6s
    Release Build / Build linux-x86_64 (push) Successful in 15m56s
    Release Build / Build linux-x86_64-musl (push) Successful in 16m21s
    Release Build / Pack the XAML reference package (push) Successful in 46s
    Release Build / Create Forgejo Release (push) Successful in 3m1s
    Stable

    buildagent released this 2026-09-02 18:04:41 +02:00 | 492 commits to master since this release

    code-index v0.24.1

    Build: v0.24.1+546

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (sandboxed worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Signed packages, and the one command that installs one.

    v0.24.0 published a .cip for the first time. This release makes it
    verifiable — and, unavoidably, makes v0.24.0's copy permanently
    uninstallable: it was published unsigned, and no later release can
    retroactively sign bytes that are already out. Take the package from
    this release instead.

    Signing

    Ed25519 over the package digest, in a detached .cips. Signing the
    digest rather than the container means the signature check and the
    digest check are the same check, so no path exists where a signature
    verifies over bytes the digest did not cover.

    The store verifies at BOTH doors. Store::get matters as much as
    install, because trust is not a constant: plugin trust remove means
    stop running what that key signed, and that can only take effect where
    the signature is re-examined against the current trust set.

    Unsigned is refused, with no --allow-unsigned — a named downgrade is
    the state everyone ends up in. The escape hatch is three local
    commands and the refusal names them.

    ed25519-compact's verify does not cover the small-order key family;
    measured, an order-8 key with a zero scalar verifies roughly three
    messages in four. The parser screens keys itself, and the test asserts
    both that we refuse and that the library alone would not — so the
    workaround can be retired on evidence rather than on faith.

    One command

    plugin add replaces four commands and a hand-assembled bridge
    string. Nothing is written before the answer: it verifies, measures
    the reindex domain, and shows one block naming the publisher from your
    own trust label and all three effects — installs bytes, RUNS the
    package sandboxed against its own fixtures, grants for this project
    only. Bare Enter is no.

    --yes requires an explicit --grant, and that clause is the whole
    difference between a pre-filled answer and a delegation.

    Honesty

    A zero now says which of three things it is: measured, structurally
    unmeasurable, or filtered away by an argument the reply now names. And
    an agent asking why a plugin stopped working can tell "lost its
    signature" from "never installed" — two states with different repairs,
    which is why they do not share a code.

    Getting the package

    code-index plugin trust add code-index-publisher.pub \
      --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c \
      --name '<your label for us>'
    code-index plugin add de.h-dv.xaml-0.1.0.cip
    

    Anchoring is a decision about a PUBLISHER, not a package, and it is
    the one step that should happen at a keyboard. The fingerprint above
    is published here and committed in the repository precisely so it
    reaches you by a channel other than the key file: a fingerprint you
    compute from the file in front of you agrees with itself and proves
    nothing.

    A signature says these bytes are the ones we signed. It does not say
    they are safe.

    Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
    Claude-Session: https://claude.ai/code/session_01K1zj5VcFJvJt3pQxe9259K

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.24.1-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.24.1-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.24.1-linux-aarch64.tar.gz
    Windows x64 code-index-v0.24.1-windows-x86_64.zip

    XAML plugin package

    de.h-dv.xaml-0.1.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant.

    Download de.h-dv.xaml-0.1.0.cips and code-index-publisher.pub too, and keep the .cips beside the .cip. Packages are signed and an unsigned one is refused (signature_missing) with no flag that accepts it, so anchoring the publisher is the FIRST command and not an optional one — an install run before it refuses with signature_untrusted:

    code-index plugin trust add code-index-publisher.pub --fingerprint sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c --name 'h-dv (first party)'
    code-index plugin install de.h-dv.xaml-0.1.0.cip --sha256 sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin check   sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin enable  sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd \n    --capabilities bridge_source \n    --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.1.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed. .dataset and other markup remain text-only (searchable, no symbols).

    About that key

    sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c is a long-lived Ed25519 key held as a secret in this project's CI, used to sign released packages automatically. Anchoring it means trusting this project's release pipeline, not only its maintainers: anyone who can run a release workflow here can produce a package that verifies under it. There is no expiry — deliberately, because offline installations must not break on a timer — so withdrawal is manual and on your side: code-index plugin trust remove sha256:1cb03259a8c870b6db02360abd9351e17e67724d1f8c3509d85c4bf6b06fa72c. If this key is ever rotated or withdrawn, the new fingerprint is published in the release notes and in tests/packages/first-party.fingerprint, and every machine has to run plugin trust add again.

    An anchor is machine-wide and it is yours: the --name above is a label YOU choose, and nothing in the package, the key file or the signature can name its own publisher.

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads
  • v0.24.0 4a72738211

    code-index v0.24.0
    Some checks failed
    CI / cargo fmt (push) Successful in 47s
    CI / OSS corpus tier-3 scale (weekly) (push) Has been skipped
    CI / Grammar rebuild from source (weekly) (push) Has been skipped
    CI / cargo test (abi, 32-bit + wasm32) (push) Successful in 4m3s
    CI / cargo doc (intra-doc links) (push) Successful in 4m24s
    CI / cargo clippy (push) Successful in 5m11s
    CI / cargo check (MSRV 1.98) (push) Successful in 5m20s
    CI / cargo check (windows-gnu) (push) Successful in 5m46s
    CI / cargo deny (push) Successful in 5m57s
    CI / OSS corpus (tier 1) (push) Successful in 15m47s
    CI / cargo test (push) Successful in 16m55s
    CI / cargo test (daemon transport) (push) Successful in 5m20s
    CI / Plugin path cost + pool throughput (weekly) (push) Has been skipped
    CI (Windows) / fmt + clippy + build + test (windows) (push) Successful in 35m5s
    Release Build / Generate Version (push) Successful in 26s
    Release Build / Required CI green (push) Successful in 47s
    Release Build / Build linux-x86_64-musl (push) Failing after 19s
    Release Build / Build linux-aarch64 (push) Successful in 11m18s
    Release Build / Build windows-x86_64 (push) Successful in 12m2s
    Release Build / Build linux-x86_64 (push) Successful in 14m7s
    Release Build / Pack the XAML reference package (push) Successful in 51s
    Release Build / Create Forgejo Release (push) Successful in 2m17s
    Stable

    buildagent released this 2026-09-02 09:33:19 +02:00 | 502 commits to master since this release

    code-index v0.24.0

    Build: v0.24.0+538

    Four-binary release: code-index-mcp (MCP stdio bridge — the usual entry), code-index-daemon (long-lived watcher + RPC server, auto-spawned), code-index-plugin-host (sandboxed worker for plugin packages, spawned by the daemon), and code-index (CLI: init, index, watch, doctor, link, plugin).

    Epic #75's runtime plugin architecture, phase 4 (#80), plus the review
    round that followed it and the fixes that round demanded.

    The customer-facing change is that the XAML plugin can now be
    obtained: the reference package is packed in CI by the shipped binary
    and published beside the archives with its digest. No release has ever
    carried one.

    Security, all of it found by asking what the shipped binary actually
    contains: eighteen debug_assert!s guarded invariants that do not
    exist under --release, and two of them mattered — the binary
    installed a seccomp filter that ALLOWED socket, and it minted
    builtin language ids that reach grant_all. derived_name is now an
    authority a project grants rather than one every package holds, with a
    detection bit so a fabricated edge can be enumerated after the fact.
    Three package-path guards became refusals.

    Honesty: plugin rollback refuses instead of exiting zero on a
    rollback it did not perform; context_pack's with_source is
    measured rather than derived behind an assertion release deletes;
    refs_resolved reports the rows the resolver actually changed.

    Gates the round added because it needed them: a rustdoc gate (backlog
    131 -> 0, five genuinely broken citations inside it), a README gate
    that caught this very version bump, a fork lock covering whole test
    targets, and three cost bounds on the plugin path — which nothing
    could see before, because the corpus ratchet counts SQLite opcodes and
    the corpus installs no packages.

    Measured, since the direction rests on it: a language plugin's wire
    cost is additive at ~3.5-4% of a real file, and a plugin fleet runs at
    0.97-1.09x of builtins at machine width.

    Verified: fmt, clippy (host + windows-gnu), rustdoc at zero warnings,
    cargo check --locked, MSRV 1.98, 2448 tests, daemon transport leg,
    precision_gate 7/7 phantom_count 0, release_gate, corpus ratchet with
    baseline.json unmoved at 534084b856c22566c48e386bc41ed67e and never
    blessed.

    Downloads

    Four platforms are built for every release. The table below says which ones THIS release published.

    Platform Archive
    Linux x86_64 (glibc) code-index-v0.24.0-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) not published for this release
    Linux ARM64 code-index-v0.24.0-linux-aarch64.tar.gz
    Windows x64 code-index-v0.24.0-windows-x86_64.zip

    No static (musl) archive was published for v0.24.0. That leg is best-effort: it either failed to build or its code-index-plugin-host failed the release plugin smoke/timeout/trap test, and an archive whose plugin host has not been proved on its own target is not one this project ships. Use the glibc archive.

    XAML plugin package

    de.h-dv.xaml-0.1.0.cip makes .xaml files carry symbols and references instead of being text-only: x:Class and Click= handlers bind into the paired C# code-behind, x:Name becomes a searchable declaration, and {Binding …} stays unresolved because no bridge can reach it.

    It is NOT installed by installing code-index. Packages are installed into a user-controlled store and approved per project, and installing grants nothing — enable is the grant:

    code-index plugin install de.h-dv.xaml-0.1.0.cip --sha256 sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin check   sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd
    code-index plugin enable  sha256:584fe7183b234e7133fa7d257cc8a8d687f38bfb43d235cfda657ba13b1186dd \n    --capabilities bridge_source \n    --bridges 'de.h-dv.xaml/xaml:type->csharp:class,de.h-dv.xaml/xaml:call->csharp:method'
    

    The digest above is the one this release packed and it is what --sha256 pins; de.h-dv.xaml-0.1.0.cip.digest.txt carries it and the extraction identity. A digest that changes between releases means the package changed — re-pin, and read the notes.

    Only .xaml is claimed. .dataset and other markup remain text-only (searchable, no symbols).

    macOS is not currently built. No x86_64-apple-darwin or aarch64-apple-darwin archive is published — macOS users should build from source (cargo build --release). This is a deliberate deferral, tracked in #59; no date is promised.

    Wire into Claude Code

    { "mcpServers": { "code-index": { "command": "/usr/local/bin/code-index-mcp", "args": ["--root", "/path/to/your/project"] } } }
    

    SHA256 checksums (.sha256 files) available for every archive.

    Downloads