CodeGraph

repository·main·Indexed 13 days ago

https://github.com/colbymchenry/codegraph

A local semantic code intelligence platform that provides AI agents with surgical code context. It uses a Rust-powered kernel to build and maintain code graphs for 20+ languages, reducing tool calls and token usage for agents like Claude Code, Cursor, and GitHub Copilot. Features include framework-aware routing, cross-language bridging for iOS and React Native, and automatic file synchronization.

Tokens
205.3K
Snippets
359
Records
782
Agent score
98%

What's inside CodeGraph

  1. What is CodeGraph?

    main

    CodeGraph is a local-first code-intelligence tool designed to provide AI coding agents (such as Claude Code, Cursor, and GitHub Copilot) with semantic structural knowledge of a codebase.

    Instead of agents using grep or glob to scan files to understand code structure, CodeGraph parses the codebase using tree-sitter and stores the resulting knowledge graph in a local SQLite database. This allows agents to answer structural questions (like symbol relationships or call graphs) via a queryable index, significantly reducing tool calls and file reads.

  2. Supported agents for CodeGraph

    main

    CodeGraph supports several AI agents and IDEs. You can use the interactive installer to auto-detect and configure these agents, which includes wiring the CodeGraph MCP server and writing instruction markers (like CLAUDE.md, AGENTS.md, or GEMINI.md) so agents learn the codegraph explore command.

    Supported agents include:

    • Claude Code
    • Cursor
    • Codex CLI
    • opencode
    • Hermes Agent
    • Gemini CLI
    • Antigravity IDE
    • Kiro
  3. Supported languages in CodeGraph

    main

    CodeGraph provides full structural extraction and cross-file resolution into a single graph for all supported languages. No per-language setup is required to begin using semantic code intelligence across your codebase.

    Supported languages include:

    • Web/Frontend: TypeScript, JavaScript, Svelte, Vue, Astro, Liquid
    • Systems/General Purpose: Rust, Go, C, C++, Objective-C, Swift, Java, C#, Kotlin, Scala, Python, ArkTS
    • Specialized/Other: Metal, CUDA, PHP, Ruby, Lua, Luau, Dart, R, CFML, COBOL, Visual Basic .NET, Erlang, Solidity, Terraform / OpenTofu, Nix, Delphi (Pascal)
  4. Understand the CodeGraph A/B benchmark results

    main

    The CodeGraph A/B benchmark compares agent performance (using Claude Opus) with the codegraph MCP server versus without it (using only built-in Read/Grep/Glob/Bash tools).

    Key Performance Metrics

    • File Reads: CodeGraph reduces total file reads by approximately 76% (e.g., 159 $\rightarrow$ 38 reads).
    • Tool Calls: Reduces tool calls by ~41% (e.g., 321 $\rightarrow$ 189 calls).
    • Wall-clock Time: Mean duration decreases from 48s to 38s.
    • Efficiency: CodeGraph prevents 'agent thrashing' in large repositories where agents typically fall back to expensive shell find/grep (Bash) calls or spawn sub-agents.

    When to use CodeGraph

    • Medium/Large Repositories: Significant wins are seen in backends with complex flows (e.g., route $\rightarrow$ handler $\rightarrow$ service). CodeGraph avoids the need for many greps/globs and shell commands.
    • Small Repositories: In very small repos (a few files), the performance may tie with or be slightly slower than the 'without' arm due to MCP and indexing overhead.
  5. Understand the codegraph telemetry ingest worker

    main

    The telemetry-worker is the first-party endpoint for telemetry.getcodegraph.com. It receives anonymous usage telemetry from CodeGraph clients.

    Key behaviors:

    • Validation: Validates incoming batches against a strict allowlist. Unknown events are dropped and unknown properties are stripped.
    • Privacy: Never reads or stores client IP addresses.
    • Rate Limiting: Limits requests per machine_id.
    • Storage: Writes surviving events to a Cloudflare D1 database (env.DB) using ctx.waitUntil to ensure writes happen off the response path.
    • Fail-silent: If a D1 write fails, it is logged to Workers Logs, but the client still receives a 204 response to prioritize availability over data completeness.
    • Data Lifecycle: A nightly cron job rolls up raw events into anonymous daily counts and purges raw rows older than the RETENTION_DAYS (default 90) to stay within D1 storage limits.
  6. How PHP static member and property references are extracted

    main

    CodeGraph extracts references to constants and properties using the following logic:

    • Class Constants: UserModel::class or Foo::CONST extracts the class name at the receiver's position if the name matches the capitalized regex ^[A-Z][A-Za-z0-9_]*$.
    • Relative Constants: self::CONST or static::X does NOT emit a reference.
    • Scoped Properties: UserModel::$conn extracts UserModel.
    • Qualified Constants: \App\Models\User::class does NOT emit a reference.
    • Lowercase Receivers: References using lowercase receivers (e.g., $x->y) are not accepted as valid class/constant access patterns for extraction.

    These extractions are only performed when the access occurs within a function or method body.

    // Extracts 'UserModel'
    UserModel::class;
    
    // Extracts 'UserModel'
    UserModel::$conn;
    
    // Does NOT extract (relative scope)
    self::CONST;
    
    // Does NOT extract (qualified name)
    \App\Models\User::class;
  7. Encoding and Column handling in R

    main

    To maintain parity with the kernel, the following encoding rules must be followed:

    • Columns: All column positions are measured in UTF-16 code units. For example, an emoji like 🎉 counts as 2 units.
    • Slicing: All getNodeText calls and signature .slice(0, 100) operations must be UTF-16 based.
    • CRLF: The only difference in multi-line import signatures between CRLF and LF is the presence of `

    within the text. Comment nodes include the trailing ` at the grammar level, but this is invisible to the R extraction logic.

  8. Verify language migration via the Equivalence Gate

    main

    When a language is migrated from the WASM-based extractor to the codegraph-kernel, it must pass an Equivalence Gate to ensure correctness. A language is only considered shipped when it meets these three criteria:

    1. Structural Parity: Node, edge, and reference counts must be within ±0.5% across three real repositories (small, medium, and large), with all differences manually reviewed.
    2. Retrieval Invariants: The explore-flow must successfully connect the language's canonical flows end-to-end, and agent A/B testing must show no regressions.
    3. Performance Improvement: The fresh-index wall clock time must improve on the target language's repositories, with no regression observed on a control repository of a non-migrated language.
  9. Understand the CodeGraph budget allocation model

    main

    CodeGraph uses a proportional allocation model (allocateExploreBudget) to decide how many bytes (source code) are sent to an AI agent. Instead of a flat cap per file, it reserves a share of the total 'envelope' (the maximum output character limit) for each file based on its relevance and importance.

    The Allocation Logic:

    1. Weight Calculation: Weight = score × worth × (spine ? 2 : 1).
      • score: The relevance score.
      • worth: A secondary penalty applied to the rank to ensure that high-ranking but low-value files (like generated boilerplate) don't consume the entire budget.
      • spine: A multiplier for files on the primary code path.
    2. Relative Cliff: Files with a weight less than 15% of the top weight (capped at SCORE_FLOOR_MAX) receive zero source code. They only receive metadata (path, symbols, and line numbers). This saves space and prevents low-value files from consuming maxFiles slots.
    3. Floor and Split: Every admitted file is guaranteed a minimum of MIN_CHARS (700 characters) to ensure at least one complete method is visible. The remaining budget is then split proportionally based on weight.
    4. Safety Valve: No single file can exceed 70% of the total envelope.

    This model ensures that 'diffuse' queries (asking about many components) get a spread of files, while 'precise' queries concentrate bytes on the most relevant files.

  10. Understand the Explore Session State mechanism

    main

    CodeGraph uses ExploreSessionState to track what has already been sent to an agent during an MCP session. This prevents redundant data transfer by allowing the system to recognize when a file or specific line ranges have already been delivered.

    Key Data Recorded

    For each resolved project root in a session, the following is tracked:

    • callCount / responseBytes: Cumulative totals for the session.
    • calls[]: Detailed history of recent calls, including:
      • The query used.
      • Emitted line ranges (spans).
      • A content fingerprint (hash) for the source bytes.
      • The 1-based session index.

    Constraints and Behavior

    • Per Session, Not Persisted: State is lost when a new agent session starts.
    • Per Resolved Project Root: State is keyed by the actual project path, not the path typed by the agent.
    • Bounded Memory: To prevent unbounded growth, state is limited by EXPLORE_SESSION_LIMITS (e.g., 8 retained calls per project).
    • Daemon-Safe: State is stored on the MCPSession object, not on shared handlers or workers, ensuring different agents do not share history.
  11. How Rust calls and instantiations are indexed

    main

    The extractCall and extractInstantiation logic determines how code interactions are recorded:

    • Method Calls: For x.foo(), the extractor identifies foo as the method. If the receiver is a literal (e.g., 5.len()), it is ignored. If the receiver is an identifier (e.g., my_obj.foo()), it is recorded.
    • Chained Calls: For Foo::new().bar(), the extractor re-encodes the call as Foo::new().bar only if the inner function is a scoped_identifier. Otherwise, it emits bare method names.
    • Turbofish: Generic function calls like helper::<T>() preserve the full helper::<T> text.
    • Struct Instantiation: struct_expression nodes (e.g., m::Widget { }) emit instantiates references. The extractor strips everything before the last . or :: to find the type name.
  12. How Lua and Luau imports are resolved

    main

    The resolveLuaRequire function (part of the TS-side resolution consumers) handles imports references by treating the referenceName as a dotted path.

    Resolution Logic:

    • Dotted Paths: Converts telescope.config to telescope/config.lua.
    • Roblox Leaves: Converts Signal to Signal.luau.
    • Suffix Probing: Tries suffixes in this order: <p>.lua, <p>.luau, <p>/init.lua, or <p>/init.luau.
    • Selection: The file with the longest shared prefix with the requiring file wins.
    • Confidence: Returns a file-node target with a confidence of 0.9.

    Walker Obligation: The walker must provide the referenceName as the module string or leaf VERBATIM (keeping dots intact and performing no normalization).