claude-db177
Menu

Code graph

One command parses every supported source file and stores what it finds: each symbol, and each relationship between symbols. Parsing is local and deterministic, and costs no tokens.

Build it

claude-db scan          # build or refresh
claude-db scan --force  # re-parse everything
bash

About a second on a mid-size repository. A rescan only re-parses files whose contents changed, so running it again is close to free.

The four modes

The same question can be answered four ways, over MCP as find_usages and on the command line as claude-db usages:

ModeAnswers
textLive git grep. Needs no scan at all and is never stale. The default.
usagesWhat references this symbol, with the relation on each line.
explainThat, plus what the symbol itself reaches.
pathHow two symbols connect.
claude-db usages --mode explain closeObservations
claude-db usages --mode path cmdScan observationId
bash
Shortest path · 4 hops
cmdScanscanRepositoryextractFilesymbolIdobservationId

Confidence on every edge

EXTRACTED means the relationship was read literally out of the syntax tree. An import names its own target, so nothing is guessed. INFERRED means the target was matched by name across files, which is wrong when two files export the same identifier, and it carries a score saying how sure the match was.

One guess, labelled as one

Name matching is the only guess this makes, so it is labelled rather than presented as fact. You can see which half of an answer is certain.

Never stale

Every graph query hashes the working tree first and re-parses whatever changed before answering, so it cannot report a line the source has already moved past. The SessionStart hook does the same refresh in the background for repositories that have been scanned, but correctness does not depend on it having run.

Traversal is keyed on symbol id rather than name. Keying by name would merge every same-named symbol into one node, and a repository with a run in each test file would grow shortcuts between unrelated code, making the shortest path a route nothing can actually take.

Languages

Two tiers, and the graph always says which one an answer came from.

Parsed — TypeScript, TSX, JavaScript, Python, Go, Rust and Ruby. The parser is ast-grep, which ships with the package as a prebuilt binary per platform, so nothing compiles at install and nothing else has to be installed. These languages get real syntax: definitions read literally from the tree, and calls, imports, extends and implements told apart.

Read by pattern — Java, C, C++, C#, Objective-C, Swift, Kotlin, Scala, PHP, Perl, Lua, R, Julia, Dart, Elixir, Erlang, Clojure, Haskell, OCaml, F#, Groovy, shell, PowerShell, SQL, Zig, Nim, Crystal, Solidity and Vala. A shared table of declaration patterns finds classes, modules, functions and methods, and references are matched by name, so every edge from this tier is tagged INFERRED with a score. A reference that matches no declaration anywhere in the repository produces no edge at all, rather than a guess. It is less precise than a real parse and is meant to be: the alternative for these languages is nothing.

Edit this page on GitHub