Your codebase,
on the radar.

CodeRadar indexes your code into a live semantic graph — entities, calls, routes, smells, and keeps every generation as history, so agents and humans can explore, query, and rewrite with the past one lookup away.

$ pip install coderadar-rs

v0.12 — history becomes real · changelog

0 languages · 0 operations, one name each · 0 tests passing · 100/100 resolution precision-recall measured on the self-hosted corpus, guarded by CI — not claimed, proven

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-mcp is 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.

resolution

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.

search

Query + keyword + vectors

A real query language with a generated reference, millisecond FTS5 search_symbols, and Phase-1 embedding search with keyed, gated vectors.

analysis

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.

mutations

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.

serve

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.

retain

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_days moves 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.