What sets it apart
Three bets no other code index makes at once: the past is data, evidence comes standard, and one fix reaches every surface.
History as bytes
Every generation stored as content-addressed blobs over a bitemporal ledger:
every fact carries world-time and learned-time, so any recorded moment folds
back into a readable state. read_bytes serves exact source-at-T;
diffs compute on read; cold bytes archive, never vanish.
- Names at T: symbols as they were, renames included
- Bytes at T: exact source, CRLF and CJK intact
- Diffs on read: generations diffed live, nothing pre-rendered
# what did this file look like before the refactor?
snap = g.as_of("2026-09-01T00:00:00Z")
snap.read_bytes("py_agent/src/coderadar/ops.py")
→ exact bytes · old names · old edges
Honest by construction
No capability fakes an answer. Missing graphs, absent blobs, and temporal dead-ends raise named errors: instead of rendering plausibly, misses say which tokens were tried and where to look next.
- Evidence comes standard: findings carry reasons, tiers, and distances.
- Results carry receipts: mutations preview diffs; what can't be resolved is listed, never skipped.
- Nothing is take-my-word: misses name the tokens tried and where to look next.
$ coderadar traverse dead::module --as-of 2024-01-01
TemporalUnsupported: traverse reads live state;
use as_of + read_bytes for moments.
One op, every agent surface
26 operations share one name across MCP, CLI, and Python, all calling one shared function, pinned by parity tests. A fix in the op layer lands everywhere at once, and agent skills ship in the repo, drift-tested against the registry.
- 26
coderadar_*tools: one prefix, allow-list friendly - CLI for every op: JSON out, stderr + exit codes, dry-run by default
- Skills in-repo:
skills/coderadar-mcpis the source of truth
# same op, three spellings, one behavior
$ coderadar callers pkg/mod.py::handler
tools.coderadar_callers({entity_id: …})
g.callers("pkg/mod.py::handler")
- grep / ripgrep
- Finds text. No semantics, no history, no notion of a rename: a moved symbol vanishes.
- Language servers
- Answer precisely about now. They remember nothing, diff nothing, and won't batch-rewrite with receipts.
- CodeRadar
- Semantics plus memory plus guarded writes: resolved edges, every generation readable, mutations planned, verified, and reversible.
Built for agents that read code
AST-only resolution at 100/100 precision-recall, an honesty-first error model, and history stored as bytes: not vibes.
Semantic graph, 41 grammars
Single-pass tree-sitter extraction across 12 Tier-1 languages. Imports, calls,
inheritance, and route → handler edges resolved through the L1–L4 cascade
at 100/100 precision-recall: thirteen framework resolvers trace URLs to functions.
Query + keyword + vectors
A real query language with a generated reference, millisecond FTS5
search_symbols, and Phase-1 embedding search with keyed, gated vectors.
Smells · clones · dead code
Twelve smell rules, deterministic MinHash clone detection, and reachability-based dead code that shrinks as resolution improves: findings fell 269 → 121.
Guarded mutations
Plan-then-apply rewrites with byte-span verification and post-write parse checks.
Dry-run unless applied; call-site cascades flagged as
unverified_sites, never silently skipped.
Cold start, warm everything
Loads the ledger and refreshes only changed files — zero tree walks at steady state. A watcher keeps it live; the last project resumes across restarts.
History that fits on disk
archive_after_days moves cold bytes aside without breaking reads;
hot + cold backup restores are tested, not hoped. 41 grammars, one store.
Three surfaces, one name per op
One fix in the shared op layer reaches MCP, CLI, and Python — pinned by parity tests.
# who calls the embedding gate?
$ coderadar callers core_indexer/graph/embeddings.py::dedup_key
→ search_similar, compute_embeddings, 4 call sites
# what breaks if this file changes?
$ coderadar affected py_agent/src/coderadar/ops.py --max-depth 2
Every example above runs the same coderadar.ops function —
tests/test_surface_parity.py keeps it that way.
The ledger remembers
A bitemporal Macrame ledger under the graph: facts carry world-time and learned-time, so any recorded moment folds back into a readable state.
Ask the past
- Names at T —
as_of(t)reconstructs every symbol as it was. - Bytes at T —
read_bytes(id)returns exact file bytes, CRLF intact. - Diffs on read — generations diffed live from blobs; nothing pre-rendered.
Keep the present fast
- Cold start — load the ledger, refresh only changed files. Zero walks at steady state.
- Retention —
archive_after_daysmoves cold bytes aside; reads never break. - Backup — quiesce, checkpoint, copy hot + cold. Restore tested, not hoped.
Read deeper
The repo docs are the live set — everything retired lives in the knowledge graph, never deleted.
Architecture
Layers, data model, pipeline, storage, honesty model, decision index.
Quick reference
Everyday ops as CLI·MCP·Python triples, config cheat, troubleshooting.
Changelog
Per-version record from v0.5.4 to v0.12 — cold start, smells, blobs, FTS, routes.
Agent skills
Repo-truth MCP + CLI skill packs, drift-tested — drop into any agent harness.