Release notes
Changelog
Newest first · update an existing install with recon update
Update an existing install with recon update. Versions are tagged on git; release artefacts are signed and verifiable with cosign.
Passive update notices · reindex purge · serve file gate · OAuth fix
Added.
- Passive update notices — every CLI command (except
serve, update, doctor --json) prints a one-line stderr hint when a newer release is available. The check is cached for 24 h; suppressed under --json.
recon update now prints a restart reminder after the binary swap, and suggests recon reindex when the new version changes indexing behavior.
Fixed.
- Sensitive-path blocking now canonicalizes symlink targets before applying the denylist, closing alias-based bypasses.
recon serve file-count startup checks now honor .recon/config.toml ignore_patterns, so configured ignored paths do not count against tier limits.
- Incremental reindex detects changed
ignore_patterns and cascade-deletes symbols/refs for already-indexed paths that are newly ignored.
- OAuth state handling and stale index cleanup fixed in the web auth flow.
- Parallel test flakes from shared Codex environment variables serialized for CI stability.
Changed.
- CLI and server now use the same ignore-aware repository walker for file-count gating.
- Repo startup and indexing flows thread configured file-size, sensitive-path, and ignore-pattern rules through the same validation paths.
Per-repo calibration · session restore fix · Windows paths
Added.
- Per-repo baseline calibration (closes #29) — after indexing, recon runs an async calibration pass that simulates the Read+Grep alternative against the repo's actual source files and persists per-tool median token counts. Session 1 uses static baselines; session 2+ uses repo-calibrated values (20–80× higher on large repos). Re-calibrates when file count changes by >25% or on force reindex.
Fixed.
restore_session() no longer overrides the active repo — the --repo flag passed to recon serve is now always respected; session restore only pre-loads other repos into the router.
RefreshGate moved from process-global static to per-ReconServer instance so multiple servers in multi-repo mode refresh caches independently.
sk-recon-* keys added to the secret redaction allowlist so recon's own API keys in error messages are not garbled.
- Response paths normalized for Windows (forward-slash consistency).
- Mutex guards added to env-var-mutating tests to prevent race conditions under parallel execution.
Changed.
- Automatic savings push removed — users push explicitly via
recon savings push.
- Indexing config and worker rate limits hardened.
Hosted embeddings fix
embed-client DEFAULT_API_URL now points at the deployed worker host (was localhost placeholder).
- Hosted embeddings correctly wired for router-loaded repos in multi-repo mode.
Telemetry credibility pass
Measured baselines, sampled response BPE, persisted dedup.
- Static
BASELINES (9 non-migrated tools) now derive from a bench-baselines binary that simulates the literal Read+Grep alternative against a fixture repo and BPE-counts the result. Previous values under-claimed by 2–5×.
- Encoder version bumps to
bpe-v2-baselines-measured so old cumulative counters reset cleanly on first hydrate.
- Measured-baseline path bounded at 32 KB with linear extrapolation (
count_tokens_capped); runs off the tokio executor via spawn_blocking.
Telemetry::sample_response runs a fire-and-forget BPE sample on 1-in-64 calls (responses ≥ 1 KB) to track a BPE/heuristic ratio; code_savings applies it to display corrected tokens_saved.
- Per-process dedup persists to SQLite with a 24 h sliding TTL — a
recon serve restart no longer re-credits every file's baseline.
- LRU eviction (true LRU by
last_access_secs) replaces iteration-order eviction in measured_baseline_cache.
- New
Baseline fields: range_low_tokens, range_high_tokens, derivation. code_savings emits a methodology trailer for audit.
Also: watcher test timeouts bumped for self-hosted CI runners; CI release matrix timeout raised 30→45 min for cold Windows builds.
Cold-index performance + hosted semantic search
A performance-focused release targeting cold-index latency and steady-state query throughput.
- FTS triggers dropped during cold bulk index — re-created after commit; eliminates per-row trigger overhead on initial parse.
- Single-flight gate on
cached_call_graph — concurrent graph-tool calls no longer rebuild the adjacency structure in parallel.
- Compound index
(path, byte_start) — schema V5; accelerates code_read_symbol lookups on large files.
- Interim Tantivy commits dropped during cold index — single commit at the end instead of per-batch.
- Flush guard released before SQLite writes — telemetry persistence no longer holds the lock across I/O.
- Watcher channel bounded to 64 batches — backpressure instead of unbounded memory growth on rapid file changes.
- Prepared-statement cache raised to 128 — reduces re-prepare overhead on hot read paths.
- Hosted semantic search wired in default release build.
Startup handshake fix — repo_map pre-warm no longer blocks the MCP initialize
v0.5.1 was unusable on any repository large enough to take more than a few seconds to compute its repo_map: ReconServer::index_repo() ran the PageRank-based pre-warm of the repo_map cache inline, before the rmcp stdio transport opened. On a 511,561-symbol corpus that was a 55-second block — well past every IDE's MCP handshake timeout (Claude Code, Cursor, Windsurf, OpenCode all hung up after ~10–30 s). The server was alive and responsive once it finally got around to reading stdin; by then the IDE had marked the connection failed and stopped trying.
The pre-warm is now spawned via tokio::task::spawn_blocking. index_repo() returns within milliseconds of finishing tree-sitter parsing and the Tantivy commit, regardless of corpus size. The first code_repo_map call computes the answer cold-path if the spawn hasn't finished yet — same result, no startup wedge. New regression test (index_repo_does_not_block_on_repo_map_prewarm) seeds 1,600 synthetic symbols and asserts index_repo() returns in under 5 s, well below any inline-PageRank wall time on that corpus.
Honest savings — kill the per-call double-count
The tokens_saved headline was a per-call upper bound — every tool call credited the full Read+Grep alternative even when the agent had already seen the file or run the query in the same conversation. On hot sessions that drove a ~3.5× over-statement (one user reported 2.83M saved across 160 calls; the honest figure was around 800K).
v0.5.1 adds process-scoped baseline dedupe (closes #25). The first call against a (tool, dedup_key) pair credits the full Read+Grep alternative; subsequent calls credit 0 (call counts and latency still accrue). Per-tool keys: file path for code_outline / code_skeleton / code_read_symbol; symbol identifier for code_find_symbol / find_refs / callers / callees / impact / context; mode|query for code_search; kind|pattern for code_find_strings; sorted patterns for code_multi_find; (src, dst) for code_path; focus-files set for code_repo_map; subsystem id for code_subsystem; singleton for code_subsystems.
Process-scoped is the v0.5.1 simplification. For stdio MCP transport (Claude Code, Cursor, Windsurf, OpenCode all spawn one recon serve per conversation) this is identical to session-scoped. Streamable HTTP multiplexes many sessions through one process and will under-count until v0.5.2 plumbs the rmcp RequestContext session id through.
Schema unchanged. Past rollups stay at the v0.5.0 calculation; only fresh pushes use deduped values. Numbers will visibly shrink after upgrade — that's the honesty pass. recon savings show gains a footer note clarifying the dedupe window and that provider prompt-cache absorption (Anthropic / OpenAI / Gemini / vLLM) shaves more on top at billing time.
Dashboard dollar conversion (closes #21). Pick your model on the Savings tab and the headline gains a clay-coloured $X.XX in <model> input cost tile alongside the tokens-saved figure. The picker ships a 20-row curated short list (Anthropic / OpenAI / Google / DeepSeek / Mistral / Together / Cohere) plus a "Browse all 1,945 models →" button that opens a search modal over the full litellm catalog (snapshot 2026-04-30, lazy-loaded as a 165 KB JSON, served from /js/model-prices.json). A "Self-hosted / not sure" option hides the dollar tile entirely — we don't pretend there's a number when there isn't one. Choice persists in localStorage (catalog picks cache id + label + rate so the rate survives reloads); tooltip discloses the exact rate used. recon stays model-agnostic on the backend — the conversion is pure dashboard JS, no provider-side state.
Forward-compat hardening, two of two from the v0.5.0 audit plan that hadn't shipped yet.
RepoEntry deserializes with missing fields. Every field of the registry record (~/.config/recon/repos.json) is now #[serde(default)]. Future versions adding fields to the registry will hydrate older files cleanly instead of taking the whole multi-repo registry dark on a single missing key. Older binaries opening newer files just ignore unknown keys.
- SQLite "schema is newer than this binary" check.
Store::open now peeks at meta.schema_version before calling to_latest; if the on-disk stamp exceeds CURRENT_SCHEMA_VERSION the open fails with "recon database schema version 99 is newer than this binary supports (max 4). Upgrade recon to read this database, or delete the .recon/ directory to start fresh." instead of letting rusqlite_migration surface a generic "migration defined after database" message — protects users who downgrade across a schema bump.
Multi-repo MCP + canonical Hits envelope + session receipt + latency savings
Multi-repo MCP, the canonical Hits envelope, a session-end savings receipt to stderr, latency savings alongside token savings on the dashboard, plus seven hot-path / hygiene fixes from a 4-axis promise audit. Wire-format hard-cut at this release: bundled CLI version-locks against the server, so there is no in-the-wild consumer mismatch.
Multi-repo MCP service. The RepoRouter infrastructure that has been quietly enforcing tier limits in the CLI is now exposed to agents as two new MCP tools, with session persistence so agents do not re-activate after every restart.
code_activate_repo(path) — switch the active repository for subsequent stateful tools. Canonicalises the path, routes through the router (subject to max_repos for the current tier), atomically swaps the active server pointer, persists the new session. Returns a Skeleton view with the activated repo's path plus its file and symbol counts.
code_list_repos() — enumerate every loaded repo with path, files, symbols, and an active flag. Returned as a Hits(kind="repo") envelope so the existing CLI dispatcher and agents render rows without special-casing.
- Session persistence — loaded set + active repo saved to
<config_dir>/sessions.json on every successful activate. On recon serve startup the session is re-loaded; repos that fail under the current tier are warned and skipped, never blocking startup.
- Hot-path cost — every tool call performs one
ArcSwap::load_full (relaxed atomic load + Arc::clone, ≈3 ns) before delegating to the active ReconServer. Same cost class as the single-repo &self access today; multi-repo is effectively free on the steady-state path.
Canonical Hits output envelope for the 5 row-oriented tools. ARCHITECTURE.md §3 promised every tool emits exactly one of the canonical shapes; five tools were shipping bare Vec<Value> arrays. This release closes that gap with a sixth canonical variant (Hits) used by code_find_symbol, code_search, code_list, code_find_strings, code_multi_find. Wire shape: {shape:"Hits", kind, count, hits, truncated?}. Net wire-overhead per response is ≈40 bytes — well under 1 % of typical row-oriented payloads. The truncated flag is omitted when the result was not capped.
Audit-driven fixes. Three runtime bugs surfaced by a 4-axis promise audit (output discipline, privacy, performance, license/schema):
- Tantivy writer error visible. Six call sites swallowed the underlying
tantivy writer error via .ok() and logged a context-free warning. The most common cause is a stale .tantivy-writer.lock from a previously killed process; the new warning names that explicitly so users can act on it. Affected paths: ReconServer::new, RepoRouter::load_repo, indexer::index_repo / ::index_diff, recon init, recon index.
- Telemetry counters survive upgrades.
CounterSnapshot::static_baseline_tokens and ::measured_baseline_tokens are now #[serde(default)]. Older on-disk snapshots (predating those fields) hydrate as zero instead of failing deserialisation and silently wiping the lifetime "tokens saved" history on every upgrade.
recon reindex renders correctly. The CLI's print_output dispatcher now matches the reindex arm before the bare-files_indexed stats arm, so reindex output renders as ok N files, M symbols, X errors instead of an Index Health block with repo ? / tantivy 0.
Session-end savings receipt to stderr (closes #19). At the end of every recon serve session — IDE close, signal, or license revocation — recon prints a one-block summary to stderr. The IDE's MCP debug log captures stderr, so the headline reaches Claude Code / Cursor / Windsurf / OpenCode users without having to remember recon savings show or open the dashboard:
recon · session ended
18 tool calls · saved 47,200 tokens · ~9.4s faster than Read+Grep loop
top: code_outline (12,400 tok, 1.6s) code_search (9,800, 0.8s) code_read_symbol (8,100, 0.6s)
dashboard: https://mcprecon.pages.dev/dashboard
Suppressed when the session had zero tool calls (no "0 tokens saved" noise on a fresh recon serve nobody connected to). Honour RECON_QUIET=1/true/yes/on for CI / scripted runs. Failures are silent skips, never a blocker on shutdown.
Latency savings alongside token savings (closes #20). Tokens are one number; users feel time more than tokens. Baseline now carries a per-tool baseline_latency_ms alongside baseline_tokens — a conservative estimate of the wall-time the Read+Grep alternative loop would have taken (e.g. code_outline 200 ms, code_list 2 s, code_repo_map 5 s). The session receipt and the dashboard headline both surface this:
312,400 tokens saved · ~6m 12s faster than Read+Grep loop
- D1 migration
0012_usage_rollups_latency_saved.sql adds latency_saved_micros INTEGER NOT NULL DEFAULT 0 to the usage_rollups table. Pre-v0.5 CLIs talking to a v0.5 worker default to 0 (the column DEFAULT catches the absent push); a fresh v0.5 push monotone-MAX-merges the row up to the real number.
- Worker validates and round-trips the new field;
GET /v1/dashboard/savings totals the column.
- Dashboard JS renders a clay-coloured "
~6m 12s faster" line next to the existing token tile, hidden when the value is 0 so pre-v0.5 rollups don't render misleading "0s faster".
recon savings show TSV gains a time_saved_ms column (per-tool + total row).
Hybrid telemetry flush — count OR timer (closes #13). Pure count-based flushing left bursty agentic flows fine but stranded idle sessions: an IDE window with 3 calls/hr never persisted any telemetry, so recon savings show reported "no counters" after a real session. Lower FLUSH_THRESHOLD from 50 → 10 so even moderately active sessions persist quickly; add FLUSH_INTERVAL_SECS = 60 with a periodic flush task that covers the long tail. Override via RECON_TELEMETRY_FLUSH_SECS (clamped to [10, 3600]; 0 disables the timer entirely).
Hot-path performance — three caches and one O(1) lookup along the dispatcher and search paths:
- Telemetry hash lookup (closes #16).
Telemetry::record ran a linear scan over the 18-entry tools vec on every MCP tool call — ~900 string compares for a 50-call burst, for no algorithmic reason. Swap Vec<(&'static str, ToolCounter)> for AHashMap<&'static str, ToolCounter>: O(1) hash lookup, deterministic ordering preserved via BASELINES iteration in per_tool_snapshots.
- Per-file newline index cache (closes #18).
code_multi_find rebuilt the line-number index for every file in scope on every call — a 320K-symbol Rust repo with 2K files in scope re-scanned ~20 MB of bytes per call just to resolve hit lines. New line_index_cache: DashMap<PathBuf, Arc<Vec<usize>>> sits next to the existing mmap cache; both invalidate together in refresh().
- Token-count cache by (path, mtime) (closes #17). Each measured-baseline call re-opened and re-read the same file an agent was actively exploring — three full reads of identical bytes for the typical
code_outline → code_read_symbol → code_context sequence. New DashMap<PathBuf, (mtime_secs, tokens)> on ReconServer, sized at 2,048 entries (matching FffBackend's mmap cache). Self-invalidating: every lookup compares the current file mtime against the stored one; mismatch overwrites the slot.
Hygiene + audit-driven fixes (rolled up):
- Tantivy writer error visible. Six call sites swallowed the underlying
tantivy writer error via .ok() and logged a context-free warning. The most common cause is a stale .tantivy-writer.lock from a previously killed process; the new warning names that explicitly. Affected paths: ReconServer::new, RepoRouter::load_repo, indexer::index_repo / ::index_diff, recon init, recon index.
- Telemetry counters survive upgrades.
CounterSnapshot::static_baseline_tokens and ::measured_baseline_tokens are now #[serde(default)]. Older on-disk snapshots hydrate as zero instead of failing deserialisation and silently wiping the lifetime "tokens saved" history on every upgrade.
recon reindex renders correctly. The CLI's print_output dispatcher now matches the reindex arm before the bare-files_indexed stats arm, so reindex output renders as ok N files, M symbols, X errors instead of an Index Health block with repo ? / tantivy 0.
- Path-component blocklist.
is_blocked_path now scans every component, not just the leaf. Paths like vault/secret.pem/leaf.json are blocked even when the leaf has a benign extension.
- Tantivy schema-bump regression test. First test that exercises the wipe-and-rebuild on
TANTIVY_SCHEMA_VERSION mismatch — locks in recovery so a future bump cannot silently break opening.
code_skeleton fallback allocation. Replaced the collect::<Vec<_>>().join("\n") with a single-pass push_str loop into a pre-sized String.
Out of scope for this release (documented as the natural follow-up): an optional repo: Option<String> parameter on every stateful tool to override the active dispatch on a per-call basis. The current shape covers ≥99 % of agent flows (activate-then-query); the per-call override is niche convenience for cross-repo queries within a single conversation. The dashboard dollar conversion (#21, v0.5.0 milestone) ships in a follow-up — token-savings stays the headline; the picker UX is worth its own polish pass.
Patch — measured baselines for the common search paths
Two correctness bugs in the v0.4.0 measured pipeline plus one CI annoyance.
code_search exact mode credited zero savings. The Tantivy-served path passed None as the measured baseline, so the most common code_search call (default mode: "exact") reported zero tokens saved on the dashboard. v0.4.1 sums the content tokens of the top-2 unique hit files — same rationale as the v0.3.x static estimate ("Grep + read 2 hit files"), measured per call against real bytes.
code_list under-counted by ~50×. The agent's real alternative is Glob + cat top-N files, not just enumerating paths. v0.4.0 only summed the path-listing bytes; v0.4.1 also reads up to 3 top files and sums their content tokens. Capped by the same MAX_READ_FILE_SIZE the rest of the read-shaped tools use.
- Subscription-lifecycle test flake. The Razorpay-race test hit the default 5 s vitest timeout under CI load (it makes a real network call, no mock). Bumped to 15 s for that one case; passes in <500 ms locally.
No schema changes. CLI ↔ worker wire compatibility unchanged. Dashboard numbers will go up for users running code_search in default mode and code_list; the underlying static estimates documented in BASELINES are now closer to what those tools actually save.
Measured token-savings + tighter MCP surface
Two changes that move the savings dashboard from a defensible estimate to an auditable measurement, and trim two operator-only tools off the agent's MCP surface.
Measured per-call baselines. Eight tools now compute their "what Read+grep would have cost" figure from real bytes touched on the call, not a hard-coded constant. The dashboard sums those measurements into the per-day rollup; recon savings show reflects the same numbers locally.
- Migrated to measured —
code_outline, code_skeleton, code_read_symbol, code_search (regex / grep paths only — tantivy and semantic modes pass None), code_find_strings, code_multi_find, code_list, code_context. Each handler reuses already-warm bytes — no extra I/O, no extra grep passes — so latency stays under the 100 ms p99 budget.
- Worst-case mitigation — the running-sum search path caps match-bytes scanned at 1 MiB per call, then extrapolates by the unscanned-file ratio. Bounded wall-time on regexes that match every line of a giant repo.
- Static-only, with rationale — 10 tools keep documented static estimates because their alternative is fuzzy ranking, transitive call-graph traversal, or PageRank — none of which a single-pass grep replicates honestly.
code_find_symbol, code_find_refs, code_path, code_callers, code_callees, code_impact, code_subsystems, code_subsystem, code_repo_map, code_reindex.
- Calibration harness —
cargo xtask measured-baselines-corpus --repo <path> runs every migrated tool against a real repo, prints (static_estimate, measured, response, divergence) as TSV, and gates a PASS/FAIL on a 15 % divergence threshold. Will run in CI on PRs touching the measured handlers.
Honest dashboard numbers. Pre-v0.4 static baselines were conservative-by-design over-estimates. The measured numbers will be smaller for narrow / cheap calls and larger for wide regex queries — closer to what the agent's alternative actually would have cost. Disclaimer copy on the Savings tab updated to reflect which tools are measured vs estimated.
MCP surface trimmed: 20 → 18 tools. code_stats and code_savings dropped their #[tool(...)] registrations — they're operator diagnostics, not exploration tools, and exposing them via MCP encouraged agents to introspect their own savings instead of doing the user's task. Both are still reachable via recon stats and recon savings show in the CLI; the dashboard surfaces the same data for end users.
Schema simplification. The dual-baseline machinery from the v0.3.x telemetry code shrunk to two columns (static_baseline_tokens, measured_baseline_tokens); each call accrues exactly one. The legacy baseline_tokens column was renamed in migration 0011_usage_rollups_measured.sql; CLI/worker/dashboard ship in lockstep, no back-compat shims.
Tests: 8 new per-tool integration assertions (every migrated tool credits the measured counter, static stays at 0); static_only_tools_stay_on_static_baseline proves the unmigrated 10 keep their static credit; bench in crates/recon-search/benches/search_bench.rs demonstrates the byte-budget mitigation bounds the worst-case latency.
Browse the 18-tool surface →
Multi-language parity + token-savings telemetry
The two blockers between v0.3.0 and "I'll buy this" closed in one release: multi-language parser parity and visible token-savings telemetry.
Multi-language parity. All five non-Rust extractors now walk function/method/class/struct bodies and emit identifier refs from a proper identifier arm. The reference graph is now meaningfully populated for every supported language; code_path, code_callers, code_callees, code_context, code_impact, and code_subsystems all work cross-language.
- Python —
function_definition / class_definition walk bodies; decorator identifiers attribute as refs to the decorated symbol; class bases produce refs.
- JavaScript / TypeScript / TSX —
function_declaration, method_definition, class_declaration, interface_declaration, enum_declaration, type_alias_declaration, plus arrow functions assigned to const all walk. extends Base implements Iface produces refs.
- Go — function and method bodies walked; method receivers count as refs from the method.
- Java — methods, constructors, classes, interfaces, enums all walk. Generics like
List<String> produce refs to every type identifier.
- C / C++ — function definitions, struct/class/enum specifiers, template arguments all walk.
Token-savings counter. recon now tracks per-tool calls, response token estimates, and a baseline "what Read+Grep would have cost" figure. The difference is the tokens-saved number you see in code_savings and the telemetry block on code_stats.
- New
code_savings tool — per-tool TSV breakdown of calls, response tokens, baseline tokens avoided, tokens saved, avg latency. Aggregate trailer at the bottom.
code_stats gains a telemetry block (session uptime + lifetime totals). Backward compatible — existing fields unchanged.
- Lock-free hot path. Each tool call records via 4 atomic adds + a single tiktoken pass over the response. The threshold-driven flush is async via
tokio::spawn_blocking so SQLite writes never block tool latency.
- Lifetime persistence. Counters round-trip through the SQLite
meta table under tel:tool:<name> keys; recon serve hydrates on startup and synchronously flushes on shutdown.
- Model-agnostic. recon reports tokens — not dollars. Agents using it may run on Claude, GPT, Gemini, or a self-hosted model with its own price sheet; the conversion is yours to make. Per-tool baseline tokens are static, audit-friendly constants documented in
BASELINES.
Tests: 482 across the workspace. Multi-language regression tests in recon-parser::extract::tests assert non-empty refs per language; telemetry_persists_across_server_restarts proves lifetime counters survive a clean shutdown/restart cycle.
Graph-traversal tools
Seven new tools that turn the symbol reference graph into a first-class navigation surface — replacing chained code_find_refs walks with a single bounded BFS.
code_path — bidirectional BFS shortest path between two symbols (default 8 hops, max 16). Reports the exact chain or an unresolved_hint when the search hit a likely dyn-dispatch / FFI boundary.
code_callers / code_callees — layered transitive traversal up to depth rings (default 1, max 6). Cycle-safe; per-tier fan-out cap 50 nodes; total-visit cap 50 000 nodes.
code_context — one-shot bundle: signature + body + 5 callers + 5 callees + 3 types + 3 reaching tests. Replaces the canonical 4-call understand-X agent loop. Honors a token budget.
code_impact — blast radius. Tiered transitive callers + transitively-reaching test functions. Use before refactors.
code_subsystems / code_subsystem — repo orientation by weakly-connected components, ranked by hub. Architectural slices without directory lore.
Engineered alongside: a forward + reverse CSR call graph cached on the server (built lazily on first graph-tool call after each reindex), invalidated by the watcher alongside cached_symbols / cached_refs. Latency: code_path typically < 5 ms on real repos.
Also fixed: a parser/storage parser-local-id mismatch that caused refs in every file after the first to point at the wrong global symbol — invisible in single-file unit tests, broken in real multi-file workspaces.
Browse the new tool surface →
Patch
- Skip the
watcher_delete integration tests on macOS to keep the CI matrix green; the underlying watcher fix from v0.2.3 is unchanged.
Patch
- MCP tool fixes across
recon-parser, recon-server, and recon-search.
- Fixed a macOS pipeline hang in CI.
Release
- Watcher overhaul — file save → queryable in < 1 s, with a Phase 0 cascade that propagates deletes and renames immediately.
- Tier-1 token diet in tool responses: skips
None and empty fields so the wire payload stays lean.
code_search hybrid mode is now deterministic.
- Audit cleanups across the workspace.
Release
recon init --mcp <ide> now smoke-tests recon serve after writing the IDE config — you find out at install time, not when the agent first calls a tool.
Server-side repo enforcement
- Server-side
max_repos: recon init now registers each repo's canonical-path SHA-256 fingerprint with the worker via atomic POST /v1/account/repos.
recon repos list / recon repos remove for managing slots.
recon doctor [--json] — health check across binary, license, credentials, worker reachability, index, MCP wiring, and agent rules.
recon purge --mcp <ide> now also frees the server-side slot.
Patch
- Aligned the licence HMAC secret between the CLI and the worker — fixes intermittent licence-validation failures from v0.1.0.
Initial release
The first public cut. Twelve MCP tools, nine languages, one small signed Rust binary.
- Local-first index with tantivy + tree-sitter.
- MCP server with the
code_* tool family.
- Cosign-signed release artefacts.