Skip to main content

CodeRadar v0.6.5

CI PyPI Python Rust License Languages

Live semantic graph of your codebase — incremental, queryable, LLM-writable.

CodeRadar maintains an incrementally updatable graph of your code's logical structure, enabling LLMs and developer tools to both query and safely rewrite code through a unified pipeline.

Why CodeRadar

CodeGraph pioneered the semantic code graph for agents — CodeRadar builds on that foundation with capabilities CodeGraph doesn't have:

Capability CodeGraph CodeRadar
Mutate code ❌ Read-only ✅ AST-aware body replacement, indent preservation, WriteGuard safety
Temporal queries ✅ Macrame bitemporal DB — query the graph as it existed at any point in time
Rewrite safety ✅ Dry-run mutation plans, stale-write rejection, automatic rollback on tainted updates
Semantic fallback resolution ✅ L4 embedding-based resolution when structural resolution fails
Python-native embedding ✅ Native Python integration for embeddings, GraphRAG, and ML pipelines
Zero runtime boot 1.4s Node.js startup ✅ <50ms — Python process is already warm
LLM-driven refactoring plan_body_replacement() — LLM proposes, CodeRadar validates, applies, and rolls back on error

The key insight: CodeGraph answers "what is this codebase?" — CodeRadar answers that and "what was it yesterday?" and "what would it look like if I changed X?" and "apply that change safely."

Performance

Head-to-head benchmarks (N=5 median, lower is better):

Codebase Files Lang CodeRadar CodeGraph 1.5.0 Ratio
CodeRadar self 84 Python+Rust 554ms 1,434ms 0.39× (faster)
codegraph-main 558 TypeScript 12,232ms 6,970ms 1.75×

CodeRadar wins on small-to-medium Python/Rust projects due to zero runtime boot overhead. On large TypeScript codebases, CodeGraph's hand-written per-language Rust walkers and flat-buffer emission are still faster than the generic .scm-query engine, but the gap narrowed from 2.77× to 1.75×. See performance-roadmap.md for the optimization backlog.

Architecture

Python Layer (CLI, Visualizers, Framework Resolvers, GraphRAG, MCP Server)
        │
    PyO3 FFI  +  register_synthetic_edge() bridge
        │
Rust Core (ProjectedGraph, Tree-sitter 41-lang, Parallel Extraction,
           Resolution Cascade L1-L3, Query Engine, Mutation Engine, Smell Engine)
        │
    Macrame DB (bitemporal persistence with valid_from/valid_to timestamps)
Metric Value
Languages indexed 41 (12 Tier 1, 29 Tier 2, 330+ Tier 3)
Tests 556 (200 Rust + 356 Python)
MCP Tools 18 (explore, search, node, affected, resolve, query, search_similar, module_children, as_of, traverse, get_smells, replace_body, update_signature, rename, create_entity, compute_embeddings, reindex, update_file)
Query surface Pest structural + Macrame agent traversals + vector search
Frameworks Django, Flask, FastAPI, Go, Actix, Express, Spring Boot, Laravel, ASP.NET, Rails, NestJS, Vue Router, React Router
Agents MCP server with explore, node, search, affected tools

Quick Start

pip install coderadar-rs

# Initial analysis (includes framework detection)
coderadar init src/

# Query
coderadar query "functions where is_async == true"

# Explore call flows
coderadar explore UserService.create --direction downstream

# Watch for changes
coderadar watch src/ --debounce 50

# Visualize
coderadar visualize module_graph --format graphviz src/

Python API

import coderadar

# Initial analysis
graph = coderadar.analyze("src/")

# Query
for cls in graph.query("classes where inherits_from contains 'BaseModel'"):
    print(cls.name, [m.name for m in cls.methods])

# Framework-aware exploration (Django/Flask/FastAPI/Go/Actix routes included)
flow = graph.explore(["UserService.create"], direction="downstream")

# Callers (includes framework edges: route → handler)
callers = graph.callers_of("views.py::user_detail")

# Update after file change
report = graph.update_file("src/core/engine.py")

# Mutation (LLM-driven)
plan = graph.plan_body_replacement(
    entity_id="src/auth.py::validate_user",
    new_body="    return bool(re.match(r'^[^@]+@[^@]+$', email))",
    dry_run=True
)

# Module children resolution
children = graph.module_children("src/auth.py::auth")
for cls in children["classes"]:
    print(cls["name"], cls["grammar_kind"])

# Temporal queries (Macrame bitemporal)
past = graph.as_of("2026-08-01T00:00:00Z")

Language Support

Tier Languages Resolution Mutation
Tier 1 Python, TypeScript, JavaScript, Rust, Go, Java, C, C++, Ruby, PHP, C#, Kotlin Import → Signature → Framework Full tool suite
Tier 2 Swift, Scala, Lua, Elixir, Zig, R, Bash, Dart, Protobuf, Dockerfile, SQL, HCL, CMake, GraphQL, Erlang, Haskell, Nix, Shell, Groovy, Perl, SystemVerilog, OCaml, Clojure, F#, Verilog, Julia, PowerShell, Emacs Lisp, Objective-C Import → Signature replace_body, create_entity
Tier 3 Shell, SQL, HTML, CSS, YAML, TOML, JSON, Markdown + 280 more Signature Match only replace_body, create_entity

Resolution Cascade

Layer Method Confidence Languages
L1 Import + Scope 0.80–0.89 All
L2 Signature Match 0.40–0.79 All
L3 Framework Resolvers 0.80–1.00 Python, Go, Rust
L4 Embedding (Python) 0.20–0.39 Python
L5 LSP Override 1.00 Optional, disabled by default

Stack Graphs (L1 in v3.3 spec) was deferred to post-v1. CodeGraph ships 30+ languages at production scale with zero Stack Graphs dependency — compiler-grade scope disambiguation is not required for MCP agent use cases.

Framework Resolvers

CodeRadar detects and extracts framework-specific patterns that tree-sitter can't see:

Framework Language Detection Extracted Patterns
Django Python manage.py path() routes, DRF router.register(), admin registrations, .as_view() handlers
Flask Python @app.route Route decorators, Flask-RESTful add_resource(), Blueprint registration
FastAPI Python APIRouter @app.get()/@router.post() routes, Depends() injection chains, include_router()
Go Go go.mod gin.GET(), mux.HandleFunc(), Chi/Echo/Fiber route patterns
Actix Rust Cargo.toml App::new().route(), web::resource(), #[get]/#[post] attribute macros
Express JS/TS package.json app.get(), router.post(), chained .route() builder, app.use() middleware
Spring Boot Java pom.xml/build.gradle @GetMapping, @PostMapping, @RequestMapping(method=...), class-level @RequestMapping prefix, [controller] token replacement
Laravel PHP composer.json Route::get(), Route::resource(), Route::group() prefix propagation, [Controller::class, 'method'] array + 'Controller@method' string syntax
ASP.NET C# .csproj/.sln [HttpGet], [HttpPost], [Route("api/[controller]")] token replacement, Minimal API app.MapGet()
Rails Ruby Gemfile has_many/belongs_to/has_one associations, before_action/after_action callbacks
NestJS TS package.json @Controller route prefix, @Get/@Post routes, @Module dependency edges
Vue Router JS/TS package.json createRouter route objects, lazy import() component resolution, addRoute dynamic routes
React Router JSX/TSX package.json JSX <Route> declarations, v6 data router objects, <Link>/<NavLink> navigation tracking

Framework edges are registered in the Rust graph — agents can trace from URL patterns to handler functions via callers_of() / callees_of().

v0.6.5 Feature Highlights

  • Native Rust code-smell engine — 9 structural smells (god-class, long-method, long-parameter-list, deep-nesting, data-class, high-cyclomatic-complexity, brain-method, excessive-returns, too-many-fields) with severity tiers, exposed via the codegraph_get_smells MCP tool (filter by entity_id and/or rule_id)
  • AST metrics pass — cyclomatic complexity, nesting depth, and return count computed during single-pass extraction (Function.metrics), so the engine needs no source re-parse; class-level roll-ups (WMC, max-method cyclomatic, CBO) derived from the resolved graph
  • Class-field extraction — class-level @field captures now populate Class.fields (previously always empty), unblocking the class-scope rules
  • Generalized traverse binding — native-Rust BFS across all 4 edge kinds (calls, imports, extends, overrides) with py.allow_threads, replacing the pure-Python fallback
  • Resolve back-fillsubclasses, importers, and overrides reverse indexes populated (previously silently empty); cross-file MRO; TS/JS extends/implements base capture; Module concepts emitted so IMPORTS edges persist to Macrame
  • 556 tests, 0 failures — 200 Rust + 356 Python

v0.6.4 Feature Highlights

  • Query engine fixed — Pest WHERE clauses now match (atomic path rule yielded Path([]), non-silent operand/value wrappers fell through to a string-literal arm; name == "x" / name contains "x" / caller_count > 0 all returned 0 rows). Fixed path parsing, operand/value recursion, and Int/Float mixed comparison arms.
  • and/or chains fixed — boolean folds panicked (parts.remove(1) assumed the keyword was a pest pair, but string literals are silent); rewritten as left-associative folds.
  • imports query fixedtarget_kind is now derived from ImportResolution (function/class/module/import/external/wildcard/dynamic/unresolved) so imports where target_kind == "external" works.
  • traverse edge filter fixedcodegraph_traverse returned "No neighbors" because the fallback filtered entity kind ("function") against edge types ("calls"); now matches the edge type case-insensitively.
  • Anonymous functions skipped — anon callbacks no longer collapse to one empty-name "file::" entity; named functions stay accurate (calls still attributed to enclosing fn via stack frames).
  • Query UX — single-quoted strings now parse; empty-query prompt shows even without a loaded graph.
  • 531 tests, 0 failures — 180 Rust + 351 Python (extended E2E + TestQueryTool with real-row assertions)

v0.6.3 Feature Highlights

  • Mutation safety hardened — stale-write rejection (every edit carries an xxh3_64 content hash of its span, verified before any write → RejectedStale on mismatch) and automatic rollback on tainted updates (backup → atomic write → tree-sitter post-parse → restore on introduced syntax errors)
  • WriteGuard wired up — mutation writes are suppressed in a shared process-wide guard so the file watcher doesn't re-index the engine's own writes
  • create_entity fixed — language-aware code rendering (Python/Rust/Go/JS/TS/Java/C#/PHP/Ruby), real byte spans for top/end anchors, project-relative path canonicalization
  • Honest error reportingupdate_file surfaces fully_applied=False instead of swallowing failures; search_similar caches the embedding model
  • 524 tests, 0 failures — 176 Rust + 348 Python

v0.6.0 Feature Highlights

  • 17 MCP tools — full query surface: explore, search, node, affected, resolve, query (Pest), search_similar (embeddings), module_children, as_of (temporal), traverse (graph walk), replace_body, update_signature, rename, create_entity, compute_embeddings, reindex, update_file
  • Embeddings pipeline — compute + store + search_similar across ALL entity types (functions, classes, modules, imports, constants, type aliases); fastembed/BGE-small, xxHash dedup, auto-trigger on first search_similar call
  • Mutation pipeline — plan-review-apply via dry_run toggle; rename cascades to all references; create_entity with language-aware placement
  • 13 framework resolvers — Django, Flask, FastAPI, Go, Actix, Express, Spring Boot, Laravel, ASP.NET, Rails, NestJS, Vue Router, React Router
  • 41 languages — 12 Tier 1, 29 Tier 2, 330+ Tier 3 via tree-sitter-language-pack 1.14
  • 509 tests, 0 failures — 168 Rust + 341 Python, full E2E and MCP coverage

v0.5.7 Feature Highlights

  • 13 framework resolvers — Django, Flask, FastAPI, Go, Actix, Express, Spring Boot, Laravel, ASP.NET, Rails, NestJS, Vue Router, React Router — detect route registrations, model associations, controller callbacks, and navigation links across 7 languages
  • 10 new languages — Bash, Dart, Protobuf, Dockerfile, SQL, HCL, CMake, GraphQL, Erlang, Haskell (28 languages total across 3 tiers)
  • QueryPlanner — natural-language intent classifier routing to MacrameQuery primitives
  • 476 tests, 0 failures — 163 Rust + 313 Python, full E2E coverage

v0.5.6 Feature Highlights

  • 9 framework resolvers — Django, Flask, FastAPI, Go, Actix, Express, Spring Boot, Laravel, ASP.NET — detect route registrations and synthesize handler edges across 6 languages
  • 10 new languages — Bash, Dart, Protobuf, Dockerfile, SQL, HCL, CMake, GraphQL, Erlang, Haskell (28 languages total across 3 tiers)
  • QueryPlanner — natural-language intent classifier routing to MacrameQuery primitives
  • 451 tests, 0 failures — 163 Rust + 288 Python, full E2E coverage

v0.5.4 Feature Highlights

  • Single-pass cursor-driven extraction — QueryCursor directly drives entity emission, eliminating the two-pass tag→walk pipeline. Inline fn-ref subtree scanning during function emission. 37% faster on real-world TypeScript codebases.
  • Parallel extraction pipeline — 3-phase design: collect → parallel parse/tag/walk (fragment merge) → sequential projection commit.
  • 18-language query files — per-language .scm queries with automated compile validation. C/C++ and TypeScript/JavaScript query files split to eliminate grammar mismatches.
  • Query compilation cachingCompiledQuery wraps pre-compiled queries + pre-indexed capture tags; compiles once per language, not per file.
  • grammar_kind field — raw tree-sitter node kind on every Class entity (e.g. class_declaration/struct for Swift)
  • Function-as-value capture — detects self.on_click = handler, callback assignments, return values, kwargs
  • Cross-file fn-ref — resolves imported names across module boundaries
  • Noise filtering — builtin type filter (70+ types), literal receiver filter, name stoplist (12 names)
  • Docstring extraction — preceding comment runs for all languages, not just @docstring captures
  • Elixir def/defp — precise extraction via predicate queries
  • __all__ detection=, +=, .extend(), .append() patterns
  • module.children() — resolves child entity IDs to full dicts
  • Parameter annotations — type annotations extracted and filtered for builtins
  • Live file watchernotify-based debounced watcher with incremental re-indexing
  • Graphviz visualizer — call graph rendering with SCC cycle highlighting
  • Scoped call resolution — per-file resolution with caller/callee tracking
  • Benchmark pipeline — balanced (50 modules × 1000 calls) and heavy (100 modules × 4000 calls) correctness tests

Project Structure

core_indexer/              # Rust core
  queries/                 # 18 .scm query files (one per language)
  src/
    extract/               # Tree-sitter: tagger (query cursor) + walker (hierarchy) + docstring + decorators
    update/                # Incremental diff + patch + WAL
    resolve/               # Resolution cascade (import_graph, orchestrator, signature, cache, stack_graph stub)
    query/                 # Pest grammar + execution engine
    mutation/              # AST-aware refactoring (rope, indent, WriteGuard)
    fs/                    # File watcher (notify) + git integration
    graph.rs               # In-memory ProjectedGraph + parallel extraction + reverse indexes
    smells/                # Native code-smell engine (metrics pass, 9 rules, engine, registry)
    storage.rs             # Macrame concept/edge persistence
    lib.rs                 # PyO3 FFI bindings

py_agent/src/coderadar/    # Python layer
    resolvers/             # 13 framework resolvers: Django, Flask, FastAPI, Go, Actix, Express, Spring Boot, Laravel, ASP.NET, Rails, NestJS, Vue Router, React Router
    embedding/             # Content-addressed dedup
    agent/                 # GraphRAG query pipeline
    lsp/                   # Persistent LSP warm pool
    mutation/              # Tool router for LLM
    mcp/                   # MCP server (explore, node, search, affected, get_smells, …)
    query/                 # Query planner + templates + cache
    visualizers/           # Mermaid + Graphviz (SCC cycle highlighting)

docs/                      # Specifications + code review + performance roadmap
tests/                     # 356 Python tests (E2E, MCP, smells, framework resolvers, benchmarks)

Configuration

# .coderadar.toml
[project]
languages = ["python"]
roots = ["src/", "tests/"]

[resolution]
min_confidence = 0.3

[macrame]
db_path = ".coderadar/store/coderadar.db"

[mutation]
enabled = true
default_dry_run = true

[performance]
worker_threads = 4
debounce_ms = 50

License

MIT — incorporates techniques from CodeGraph (MIT License).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

coderadar_rs-0.6.5.tar.gz (268.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

coderadar_rs-0.6.5-cp39-abi3-win_amd64.whl (10.6 MB view details)

Uploaded CPython 3.9+Windows x86-64

coderadar_rs-0.6.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

coderadar_rs-0.6.5-cp39-abi3-macosx_11_0_arm64.whl (10.6 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

Details for the file coderadar_rs-0.6.5.tar.gz.

File metadata

  • Download URL: coderadar_rs-0.6.5.tar.gz
  • Upload date:
  • Size: 268.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for coderadar_rs-0.6.5.tar.gz
Algorithm Hash digest
SHA256 f9584f7d2ce42ecb205ecc6e58a14579c747ffd789e63b8ec72e0ef6199bcce6
MD5 23e21cb92e67218cb95c8cb957a18e14
BLAKE2b-256 4e4fa558268035f257a80f155633190f783e1adb508b12b8eed2ec82c8a0b5fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for coderadar_rs-0.6.5.tar.gz:

Publisher: release.yml on opticsWolf/coderadar

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coderadar_rs-0.6.5-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: coderadar_rs-0.6.5-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 10.6 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for coderadar_rs-0.6.5-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a6174a1caaec6af36129b0f35f8b70a2991939a6e20a480ad2ce673fda42ae01
MD5 d3a27fbd084f0684e20dcdf174a4b560
BLAKE2b-256 c98481d380ee34b19d5da22613d63cf6d8f3295cfebf578397dabf4e2f6e6acb

See more details on using hashes here.

Provenance

The following attestation bundles were made for coderadar_rs-0.6.5-cp39-abi3-win_amd64.whl:

Publisher: release.yml on opticsWolf/coderadar

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coderadar_rs-0.6.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for coderadar_rs-0.6.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f61a8eabcfbfb30e83f95089ed610e0abaa456aac84f105635f3e03e3ceef649
MD5 f490a532ebfa96c8e0e7f21f326c6422
BLAKE2b-256 9c45c4152c14eccdfd9b9e526c76a7d496bc59c7413e4ad5a0ac52bb97d366e0

See more details on using hashes here.

Provenance

The following attestation bundles were made for coderadar_rs-0.6.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on opticsWolf/coderadar

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file coderadar_rs-0.6.5-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for coderadar_rs-0.6.5-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 587cc4d64e2e0bfce8a5137fc4741f52af22f68be3eada15fe9deaa42bf7cca4
MD5 71fe613e4844a951d3a39fcc9886448e
BLAKE2b-256 19e9e93960908f8078f25af24db861312d651203faee4e19cb02b07dada2ac07

See more details on using hashes here.

Provenance

The following attestation bundles were made for coderadar_rs-0.6.5-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on opticsWolf/coderadar

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page