• v0.41.52 7fc7fb206e

    code-index v0.41.52
    All checks were successful
    Pilot plugin compatibility / Pilot scope (push) Successful in 15s
    CI (Windows) / changes (what this run must test) (push) Successful in 27s
    CI (Windows) / fmt + clippy + build + test (windows) (push) Has been skipped
    CI / changes (what this run must test) (push) Successful in 31s
    Package CI / changes (which packages this run must test) (push) Successful in 31s
    CI / cargo fmt (push) Successful in 34s
    Package CI / package suites (clippy) (push) Has been skipped
    CI / cargo clippy (push) Has been skipped
    CI / cargo check (MSRV 1.99.1) (push) Has been skipped
    CI / cargo check (windows-gnu) (push) Has been skipped
    CI / cargo test (abi, 32-bit + wasm32) (push) Has been skipped
    CI / cargo deny (push) Has been skipped
    CI / CI lane wall-clock headroom (push) Has been skipped
    CI / guest crates (fmt, clippy, doc) (push) Has been skipped
    CI / cargo doc (intra-doc links) (push) Has been skipped
    CI / OSS corpus (tier 1) (push) Has been skipped
    CI / OSS corpus tier-3 scale (nightly) (push) Has been skipped
    CI / Grammar rebuild from source (nightly) (push) Has been skipped
    CI / cargo test (push) Has been skipped
    Pilot plugin compatibility / Fetch the pinned runtime once (push) Successful in 19s
    CI / cargo test (daemon transport) (push) Has been skipped
    CI / Plugin path cost + pool throughput (nightly) (push) Has been skipped
    Package CI / package (php) (push) Successful in 3s
    Package CI / package (csharp) (push) Successful in 4s
    Package CI / package (javascript) (push) Successful in 4s
    Package CI / package (python) (push) Successful in 3s
    Package CI / package (svelte) (push) Successful in 3s
    Package CI / package (timeline) (push) Successful in 4s
    Package CI / package (rust) (push) Successful in 4s
    Package CI / package (vue) (push) Successful in 5s
    Package CI / package (ruby) (push) Successful in 4s
    Package CI / package-corpus (csharp) (push) Successful in 6s
    Package CI / package-corpus (javascript) (push) Successful in 6s
    Package CI / package (xaml) (push) Successful in 7s
    Package CI / package-corpus (php) (push) Successful in 5s
    Package CI / package (typescript) (push) Successful in 7s
    Package CI / package-corpus (ruby) (push) Successful in 5s
    Package CI / package-corpus (python) (push) Successful in 6s
    Package CI / package-corpus (rust) (push) Successful in 5s
    Package CI / package-corpus (svelte) (push) Successful in 6s
    Package CI / package-corpus (xaml) (push) Successful in 4s
    Package CI / package-corpus (vue) (push) Successful in 4s
    Package CI / package overhead budgets (nightly, one package at a time) (push) Has been skipped
    Package CI / package-corpus (timeline) (push) Successful in 5s
    Package CI / package-corpus (typescript) (push) Successful in 5s
    Pilot plugin compatibility / Pilot compatibility (csharp) (push) Successful in 18s
    Pilot plugin compatibility / Pilot compatibility (timeline) (push) Successful in 21s
    Pilot plugin compatibility / Pilot compatibility result (push) Successful in 1s
    Release Build / Generate Version (push) Successful in 17s
    Release Build / Required CI green (push) Successful in 51s
    Release Build / Build linux-aarch64 (push) Successful in 19m13s
    Release Build / Build windows-x86_64 (push) Successful in 26m50s
    Release Build / Build linux-x86_64-musl (push) Successful in 27m55s
    Release Build / Build linux-x86_64 (push) Successful in 29m36s
    Release Build / Assemble the release archives (push) Successful in 1m3s
    Release Build / Windows archive smoke (msvc) (push) Successful in 1m8s
    Release Build / Create Forgejo Release (push) Successful in 50s
    Release Build / Seed the package channel (push) Successful in 23s
    Stable

    buildagent released this 2026-11-13 12:24:50 +01:00 | 102 commits to master since this release

    code-index v0.41.52

    Build: v0.41.52+2613

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

    Windows installer: install.ps1 and checksum, from the same release commit. It installs AND updates — the same code does both — verifies the archive against its published .sha256 before unpacking, refuses hostile archive members (absolute paths, .. escapes, symlinks and reparse points, which Expand-Archive does not protect you from), and grants nothing when it installs a package: the bytes go into the machine's store and the approving line is PRINTED for you to run from inside a project. -Help lists the flags; -Tag v0.41.52 pins the binaries.

    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).

    v0.41.51 was tagged but never published: its release run stopped in the Windows archive smoke on the defect fixed here (#581). This release contains everything prepared for v0.41.51 plus that fix. Compared with v0.41.50:

    Startup cost (#581)

    • Since v0.41.49 every start of a process (a one-shot code-index query, index, languages enable, the MCP server without a daemon) read every package in the user's store about 22 times and computed two content hashes for each. With the seven first-party packages a one-shot query took 8.5-9.7 s instead of 1.4-1.6 s; with 45 installed packages it took 17-19 s and the first call was refused with index_incomplete, because the one-shot wait budget is 10 s.
    • The availability check now reads only each package's index and manifest, computes no hash, and is skipped when every enabled language is a first-party one. A package that is used is still read and verified completely (signature, trust, approval, enablement); nothing is cached between calls, so installing or removing a package while a daemon runs is seen at once.
    • Measured on the shipped build shape, fresh project, no daemon:
    store step v0.41.48 v0.41.49 to v0.41.51 this release
    7 packages languages enable (7 languages) 14.2 s 28.2 s 12.5 s
    7 packages index 3.7 s 10.3 s 3.4 s
    7 packages one-shot query 1.7 s 9.1 s 1.5 s
    45 packages, 141 MiB languages enable (7 languages) 13.6 s 132.7 s 12.9 s
    45 packages, 141 MiB index 3.6 s 29.4 s 3.4 s
    45 packages, 141 MiB one-shot query 1.4 s 17-19 s, first call refused 1.5 s
    • A test counts archive reads and content hashes in one startup and one index before and after installing eight unused packages: they add nothing, and the one used package stays within four reads per startup. It does not bound a time.
    • The release smoke for Windows prints the elapsed time of each step, retries a call refused as retryable for a bounded time and says so, and stops the daemon it may have started on every exit path.

    Changed behaviour

    • Every string argument of every MCP tool, and every entry of a string list, is limited to 8,192 characters (Unicode scalar values). A longer value is refused before any work with invalid_argument_value, received: {"characters": n} (plus "entry": i for a list) and accepted: {"maxLength": 8192}. v0.41.50 accepted any length.
    • search_text with whole_word: true and a literal past the regex engine's limit answered whole_word_needle_unsupported; such a literal is now refused by the length rule first.
    • review_diff with path_glob: summary.changed_files is the number of files the filter matched (it was the whole diff). The whole-diff split stays in coverage.filter (matched_files, excluded_files).
    • changed_symbols and review_diff: a deleted symbol's visibility is its effective visibility (see below), not always the one written at the symbol.
    • read_code on a dangling symbolic link answers path_outside_root (v0.41.50 answered file_not_readable when the link was the last path component). A link that cannot be resolved proves nothing about where a read through it would land.

    Fixes

    • #575: one search_text query with a very long literal kept the server busy (SQLite's FTS5 phrase parser reallocates per eight tokens; more than 30 s for 400,000 characters on Windows). The length rule above bounds it. An inventory measured every text argument of every tool up to 1,048,576 characters; no other argument grows superlinearly.
    • Long caller text no longer ends in internal_error or a JSON-RPC error: a search_symbols query with very many name tokens (the token fallback now considers the first 512 and reports token_tier.<project>.tokens_omitted), a very long path_glob or lang, and a read_code path the filesystem cannot represent. A test reads the published tool list and exercises every string argument at the limit.
    • #578: read_code on a missing file whose directory does not exist answered path_outside_root; it answers file_not_readable like any other missing file. Containment is decided on the deepest existing directory, and a component is skipped only when the filesystem proves nothing is there, so a path through a symlink that leaves the root, or through a link that cannot be resolved, stays refused.
    • #573: review_diff graded a deleted pub field or method of a crate-private type as api_break_deleted (high). A deletion is graded by the least visible of the symbol and its enclosing types; a method of an inherent impl takes its type's visibility when that type is declared in the same file. Modules never lower a grade, because a public item of a private module can be re-exported. The finding names the type that limited it.
    • #576: index_coverage (and three other replies) advised "Restart the daemon" while the index was only starting. The remedy follows the reported lifecycle: retry during startup and reconciliation, repair or restart only for a degraded index.

    Documentation

    • New docs/configuration.md: every .code-index.toml key (type, default, bounds, effect) and every environment variable the release binaries read. A test compares the key table with the decoder in both directions. Six accepted keys are marked as having no effect (watcher.mode, watcher.poll_interval_ms, logging.level, logging.format, workspace.name, plugins[].file).
    • README.md, CONTRIBUTING.md and docs/ were checked statement by statement against the tree; 32 false statements are corrected (Rust version requirement, native parser fallbacks that release binaries do not have, the retired native-plugin authoring path, counts that had gone stale).
    • docs/mcp-arguments.md states the length rule once for all string arguments.

    Size

    • tools/list is 59,229 bytes (59,167 in v0.41.50; the test ceiling of 59,311 is unchanged). The added bytes are the maxLength on search_text.query and one sentence in the review_diff description.

    Qualification

    • Two full local gate runs: one on the tree tagged v0.41.51 (42 of 44 steps passed; the two failures were on tests new in that tree, both fixed and re-run), and one on this release's tree (43 of 43 steps passed, no record moved). The runs cover the workspace and MCP suites on both legs with their timing profiles, clippy for the host and for x86_64-pc-windows-gnu, rustdoc, precision_gate 7/7, the corpus suites, eleven package legs, scale and tier-3 corpus, packages-only and shipped-shape acceptance, and the nightly-only cost steps.
    • The startup figures above were measured by the release lead on the shipped build shape, with the seven first-party packages and with a copy of a developer machine's 45 installed packages.
    • The path check for read_code was tightened after an automated security review of the v0.41.51 branch (a component is skipped only when proven absent); its tests were run on both legs with a mutation.
    • CI on the pull request head: the package, pilot-plugin and Windows workflows passed. ci.yml run 8637 passed all 16 jobs; it was dispatched by hand, so it also ran the nightly-only jobs (tier-3 scale, grammar rebuild, plugin path cost with language_package_overhead 3 passed). Ten earlier runs on this head tested nothing: the runners could not resolve index.crates.io, static.rust-lang.org or code.forgejo.org for about eight hours (#582). One run in between (8631) failed in a single test, sfc_first_contact_delegates_script_languages_and_refuses_only_unavailable_regions: the index was still reconciling after 60 s. The same commit passed that test in run 8637 and in every local run (36 s alone, 102 s with the machine oversubscribed two-fold; the previous master takes 144 s). The cause of that one failure is not known; it is recorded on #582.

    Remaining scope

    • #540 (was #577): review_diff grades an edited file-level #[test] function (or one in a #[cfg(test)] module not named tests) as an untested production change. The test role is decided from paths and container names; a fix needs the language packages to emit a per-symbol test marker.
    • #531 (was #579): in Rust, V::Value where V is a generic parameter can bind to a same-named type declared inside a function body elsewhere in the project, and is reported as a resolved reference. Found by this release's own gate; the resolver is unchanged in this release.
    • #570: six test timing hooks are still read by release binaries, and the six no-effect configuration keys are still accepted with a warning.

    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.41.52-linux-x86_64.tar.gz
    Linux x86_64 (static/musl) code-index-v0.41.52-linux-x86_64-musl.tar.gz
    Linux ARM64 code-index-v0.41.52-linux-aarch64.tar.gz
    Windows x64 code-index-v0.41.52-windows-x86_64.zip

    First-party language packages

    Every archive carries code-index-packages/: the first-party language packages at the versions the package channel had published when this release was cut — de.h-dv.csharp-0.1.11 de.h-dv.javascript-0.1.6 de.h-dv.php-0.1.6 de.h-dv.python-0.1.5 de.h-dv.ruby-0.10.2 de.h-dv.rust-0.1.8 de.h-dv.typescript-0.1.7 — each signed by the key below and verified at the install door. code-index languages enable <lang> adopts the bundled package offline. A package is released by its own pkg/<id>/v<version> tag, whose release carries its .cip, .cips and digest, and code-index plugin update <id> reads the package channel, so a package fix reaches you without a new core release.

    These release binaries contain no native language parsers. Under auto, enabled languages use their approved packages. First start adopts bundled packages verified against this build's own publisher keys; existing approvals and enablement remain authoritative. If your project explicitly pins a language to builtin, switch it with code-index languages owner <lang> auto; an unavailable builtin is refused rather than silently ignored. To enable languages explicitly:

    code-index languages enable csharp
    code-index languages enable javascript
    code-index languages enable php
    code-index languages enable python
    code-index languages enable ruby
    code-index languages enable rust
    code-index languages enable typescript
    

    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 first-party package. 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.

    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