devscout-rs 0.3.0

Fast code index for C# and TypeScript codebases -- map, find, refs, impact from the CLI.
Documentation

devscout

A fast code index for C# and TypeScript codebases — map, find, refs, impact from the CLI.

devscout walks a repository once, parses it with tree-sitter (C#, TypeScript, TSX, JavaScript), and writes a small set of JSON artifacts next to the repo. Every later query is answered from those artifacts, so asking "who calls this?" or "what breaks if I touch this file?" costs a few milliseconds instead of a full-text sweep.

It is built for the case where a person or an agent needs a name-level answer — a definition site, an inbound edge, a blast radius — and grep would return either nothing useful or far too much.

What it does

Command What you get
devscout init [scope ...] Register the repo, create the artifact directory, install the agent hooks, run a first map
devscout map [scope ...] Build or refresh the index; incremental — unchanged files are reused
devscout find <query> Search the manifest by symbol name or by file purpose
devscout refs <symbol> Inbound references to a symbol, grouped by edge kind (inherits, uses-type, uses-member)
devscout read <symbol> The symbol's declaration span and verbatim source plus the same inbound answer as refs
devscout impact <file|symbol> Blast radius: the files reachable from a seed within N hops
devscout tests <symbol> The test files that reach a symbol
devscout stats Index and cache summary for the current repo
devscout clear Drop freshness rows by age or by session

Plumbing verbs (parse, spans, extract-dump, hook, noop) exist for debugging and for the agent-hook integration. devscout --help lists everything.

Languages. C# (.cs) is the complete story: declarations, inheritance, type and member usage, and preprocessor-aware extraction. TypeScript / TSX / JavaScript (.ts, .tsx, .js, .jsx) are indexed for find and file purposes, and are resolved into the graph with a narrower set of edge kinds — see Limitations.

Install

From crates.io:

cargo install devscout-rs

The crate is named devscout-rs; the binary it installs is devscout.

From source, clone this repository and build it:

cargo build --release
# binary at ./target/release/devscout

Pre-built binaries for Linux, macOS, and Windows are attached to each tagged release.

Quickstart

Any repository with C# or TypeScript in it will do. Using this repo's own fixtures as a throwaway example:

mkdir -p /tmp/demo/src && cd /tmp/demo
cp <path-to-this-repo>/fixtures/ts-grammar/* src/
cp <path-to-this-repo>/fixtures/csharp-demo/src/* src/

devscout init

init registers the root, reports what it found, offers the agent hooks, and runs a first map:

devscout initialized at /private/tmp/demo/.scout (non-git root: /private/tmp/demo)
languages: 3 .cs (fully supported); 1 .js, 9 .ts, 1 .tsx (indexed and graphed, narrower edge coverage)
hooks: installed (Read, Bash); backup /tmp/devscout-home/.claude/settings.json.bak.20260824-074758-728335000
map: mapped 14 files under . (preserved 0 agent purposes, downgraded 0 changed, 14 new, 0 removed, 14 ast signatures); graph rebuilt in 0.01s (24 defs, 4 edges)

(macOS resolves /tmp to /private/tmp; the backup path reflects whatever $HOME the hooks install ran against.)

Then query it:

$ devscout find Article
src/ArticleCard.tsx:1: function ArticleCard | interface ArticleCardProps
src/articleTypes.ts:1: interface ArticleItem | interface ArticleAuthor | type ArticleItemStatus | type ArticlePage

$ devscout refs IOrderRepository
Shop.Data.IOrderRepository  (interface)
def: src/IOrderRepository.cs:3
inbound:
  inherits (1):
    src/OrderRepository.cs:3  inherits  public class OrderRepository : IOrderRepository
  uses-type (0):
  uses-member (0):

$ devscout impact src/OrderRepository.cs --hops 2
impact: src/OrderRepository.cs  (file, seed files: src/OrderRepository.cs)  hops<=2
affected files: 1  shown: 1  dropped: 0
file  hops  via  top-symbols
src/OrderController.cs  1  3  OrderRepository

refs, impact, and tests also take --json (machine-readable) or --compact (one line per hit, for piping). A zero-hit query is reported as a zero hit, not as an error — the tool never guesses a different symbol on your behalf, and an ambiguous name prints every candidate instead of picking one.

Re-run devscout map . after edits; it re-parses only what changed and leaves the graph alone when nothing moved (... 0 new, 0 removed ...; graph unchanged). If the index falls behind HEAD, queries print a staleness warning on stderr rather than silently answering from stale data.

Find ranking

find ranks matching files by tokens matched, then by their precise inbound-reference count. References originating in the same file are excluded from a file's inbound count.

Where it stores things

Inside a git repository, artifacts live under the git common directory, so they never show up as untracked files and are shared correctly by worktrees:

<git-common-dir>/scout/manifest.json              file -> purpose + symbol index
<git-common-dir>/scout/index-state.json           HEAD + timestamp the index was built at
<git-common-dir>/scout/graph/graph.json           definitions and edges
<git-common-dir>/scout/graph/fragments-v15.json   per-file extraction cache (incremental map)

Outside a git repository the same tree is written to <root>/.scout/ instead. devscout init also adds .scout to the repository's local exclude file so the legacy location cannot be committed by accident.

Two stores live outside the repo:

  • Registry — $HOME/.claude/scout/repos.json, the list of roots devscout knows about.
  • Read-freshness cache — <root>/.scout/cache.db plus a content-addressed content.db, both SQLite. These are only written by the agent hooks (devscout hook read|bash); plain CLI use does not touch them.

Environment variables

Variable Effect
SCOUT_REGISTRY Path to the registry JSON. Default $HOME/.claude/scout/repos.json.
SCOUT_CONTENT_DB Path to the shared content-dedup SQLite database. Default $HOME/.claude/scout/content.db.
SCOUT_MTIME_REUSE 1 switches map from content-hash fragment reuse back to mtime-based reuse.
SCOUT_DEBUG 1 turns on hook debug output. Equivalent to creating a .scout/debug file.
HOME Used to locate the registry, content database, and agent settings file.

Reading a symbol

devscout read <symbol> returns the indexed declaration's start and end lines, the verbatim source in that span, and its inbound references. Use --compact for a line-oriented summary or --json for structured output. References that originate inside the target declaration itself are excluded from inbound rows and counts, so recursive and other self-references do not look like external callers.

On the first agent-hook read of an indexed code file, devscout offers the nearest mapped symbol. A ranged read chooses the declaration nearest to the requested range; a full-file read chooses the first mapped declaration. The offer does not replace or truncate the file content, and non-code, unmapped, stale, or already-offered reads do not produce another offer.

Agent hooks

devscout init merges two PostToolUse entries into the agent settings file at $HOME/.claude/settings.json, backing up the existing file first: devscout hook read and devscout hook bash. They read a tool result on stdin and, when the same content has already been read in the session, replace the payload with a one-line marker instead of repeating it. Skip this with devscout init --no-hooks; the hook install is independent of the index, and a failure there never fails init.

Limitations

Known, rather than hidden:

  • TypeScript reference queries fold fewer edge kinds than extraction records. The TS/TSX extractor records more relationships than the graph currently turns into queryable edges, so refs/impact over TypeScript are narrower than over C#.
  • Generic-delegate typeParams divergence is under review. Type-parameter handling for generic delegate declarations does not yet agree with the rest of the generic ladder; the affected shapes are under review rather than pinned.
  • The content store follows HOME by default. Set SCOUT_CONTENT_DB to keep it at a fixed path when HOME varies between invocations.
  • No watch mode. map is fast and incremental, but you run it; nothing watches the filesystem for you.
  • Ordering is load-bearing but not a stability promise. Artifact ordering is fixed and deterministic by design; do not rely on it staying byte-identical across minor versions.

devscout began as the Rust half of a two-implementation tool, and a number of source comments still describe behaviour by reference to that original implementation. Those notes are history: this crate generates and reads its own artifacts, and interoperating with anything else is optional.

Benchmarks

Every claim this project makes about speed, cost, or accuracy lives in docs/benchmarks/, with the command that produced it and the corpus SHA it ran against. The methodology, the peer tools an agent could install instead, the agentic-lane protocol, and the dated result documents are separate files there, and the harness is in bench/.

Scorecard (devscout 0.2.0 vs the rg baseline, MassTransit corpus; full numbers, per-cell commands, and the preliminary-run caveats are in docs/benchmarks/results/2026-08.md):

Kind devscout rg Verdict
Locate 2/2 correct 2/2 correct, ~2x faster Tie — use rg
References 2/2 correct (needs --all) 2/2 correct Tie, cost mixed
Impact 2/2 partial, better precision, 1 call 2/2 partial, 4-call chain devscout wins
End-to-end retrieval 1/2 correct 2/2 correct rg wins
Agentic, Opus (preliminary) 4/4 correct, median 180k tokens 3/4 correct + 1 partial, median 199k tokens No correctness edge; ~25k-token saving only

These numbers were measured on 0.2.0. Release 0.3.0 changes find output ordering and reference resolution (exact generic arity), and has not been re-benchmarked; treat the scorecard as 0.2.0-specific until the next round.

A separate scripted-lane run measured tool calls issued per task: the index arm used fewer calls in all four query kinds, largest on references (5.0 vs 11.8 per lane, ~2.4x) — single-run proxy, details under "Tool-call proxy" in the dated results.

Gaps are published in both directions. devscout answers name-level and reachability questions from a prebuilt graph; questions that reduce to finding one distinctive string are answered well and cheaply by a skilled agent holding rg, with no index at all. Where a peer or the plain rg baseline leads, the results say so. The dated results in docs/benchmarks/results/2026-08.md now include the first agentic (model-in-the-loop) round — preliminary, one run per cell, its integrity caveats leading.

Versioning and releases

Semantic versioning. Releases are cut by pushing a v* tag (v0.1.0, v0.2.0, …), which builds and attaches binaries for Linux, macOS, and Windows. While the version is 0.x, minor bumps may change artifact layout — delete the artifact directory and re-run devscout map after upgrading.

Provenance. devscout is developed alongside a private reference implementation of the same graph contract; every release is gated on behavioral parity, and the committed test fixtures pin that contract byte-for-byte in this repository. You never need the reference implementation — everything required to build, test, and verify devscout is here.

License

Licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.