Token-efficient .NET library and CLI for codebase exploration via tree-sitter AST parsing.
Index once. Query cheaply. Let your LLM focus on reasoning, not searching.
Originally inspired by the DotNetCodeMunch project.
Traditional AI agents exploring a codebase open entire files and flood their context window with irrelevant code. CodeExplorer indexes a codebase once using tree-sitter AST parsing, then lets you retrieve exactly the symbols you need — with O(1) byte-offset seeking, BM25 + fuzzy search, and full DI-friendliness.
No LLM required. This is a pure retrieval engine designed to be consumed by an LLM — not to contain one.
| Task | Brute-force | CodeExplorer |
|---|---|---|
| Find a function | ~40,000 tokens | ~200 tokens |
| Understand module API | ~15,000 tokens | ~800 tokens |
| Explore repo structure | ~200,000 tokens | ~2,000 tokens |
| Artefact | Description |
|---|---|
CodeExplorer.Core |
NuGet library — all features, DI-friendly, no CLI dependency |
cxp |
Self-contained CLI executable (Win/Linux/macOS, no .NET install required) |
Windows (PowerShell):
$installDir = "$env:LOCALAPPDATA\Microsoft\WindowsApps"; $zip = Join-Path $env:TEMP "cxp-win-x64.zip"; Invoke-WebRequest -Uri https://github.com/Knaackee/code-explorer/releases/latest/download/cxp-win-x64.zip -OutFile $zip; Expand-Archive -Path $zip -DestinationPath $installDir -ForceLinux:
tmpdir="$(mktemp -d)" && curl -L "https://github.com/Knaackee/code-explorer/releases/latest/download/cxp-linux-x64.tar.gz" -o "$tmpdir/cxp.tar.gz" && tar -xzf "$tmpdir/cxp.tar.gz" -C "$tmpdir" && sudo mkdir -p /opt/cxp && sudo cp "$tmpdir"/* /opt/cxp/ && sudo ln -sf /opt/cxp/cxp /usr/local/bin/cxpmacOS:
tmpdir="$(mktemp -d)" && curl -L "https://github.com/Knaackee/code-explorer/releases/latest/download/cxp-osx-arm64.tar.gz" -o "$tmpdir/cxp.tar.gz" && tar -xzf "$tmpdir/cxp.tar.gz" -C "$tmpdir" && sudo mkdir -p /opt/cxp && sudo cp "$tmpdir"/* /opt/cxp/ && sudo ln -sf /opt/cxp/cxp /usr/local/bin/cxpcxp index folder .
cxp search symbols "Command"
cxp search text "TODO"If --repo is omitted, cxp resolves the index from your current folder name when possible.
dotnet add package CodeExplorer.Coreservices.AddCodeExplorer(options =>
{
options.IndexPath = "~/.code-index";
options.MaxFileSizeBytes = 1_000_000;
});
var indexer = sp.GetRequiredService<ICodeIndexer>();
var retriever = sp.GetRequiredService<ISymbolRetriever>();
await indexer.IndexRepoAsync("fastapi/fastapi");
var results = await retriever.SearchSymbolsAsync("fastapi/fastapi", "authenticate", kind: SymbolKind.Function);
var source = await retriever.GetSymbolSourceAsync("fastapi/fastapi", results[0].Symbol.Id);cxp index repo fastapi/fastapi
cxp index folder ./my-project
cxp search symbols --repo fastapi/fastapi "authenticate" --kind function
cxp search text --repo fastapi/fastapi "TODO"
cxp get symbol --repo fastapi/fastapi "fastapi/security/oauth2.py::OAuth2.authenticate#method"
cxp get context --repo fastapi/fastapi "auth flow" --budget 4000
cxp outline repo fastapi/fastapi
cxp outline file fastapi/fastapi --path fastapi/main.py
cxp analyze importance fastapi/fastapi
cxp analyze dead-code fastapi/fastapi
cxp analyze blast-radius fastapi/fastapi "fastapi/routing.py::APIRouter.add_api_route#method"
cxp list
cxp invalidate fastapi/fastapiCodeExplorer/
├── src/
│ ├── CodeExplorer.Core/
│ │ ├── Models/ # Symbol, CodeIndex, SearchResult, ...
│ │ ├── Parsing/ # tree-sitter AST + SymbolExtractor + LanguageRegistry
│ │ ├── Storage/ # IIndexStore + JsonFileIndexStore
│ │ ├── Search/ # BM25Engine + FuzzySearchEngine + HybridSearchEngine
│ │ ├── Summarizer/ # ISymbolSummarizer + SignatureFallbackSummarizer
│ │ ├── Retrieval/ # IRepositoryClient + OctokitRepositoryClient + LocalFolderClient
│ │ ├── Security/ # ISecurityFilter + DefaultSecurityFilter
│ │ ├── Analysis/ # PageRank + DeadCode + BlastRadius + GitDiff
│ │ ├── DependencyInjection/ # ServiceCollectionExtensions (AddCodeExplorer)
│ │ ├── CodeIndexer.cs # ICodeIndexer orchestrator
│ │ ├── OutlineProvider.cs # IOutlineProvider
│ │ └── Interfaces.cs # All public interfaces
│ └── CodeExplorer.Cli/
│ ├── Commands/ # All Spectre.Console CLI commands
│ └── Program.cs
└── tests/
├── CodeExplorer.Core.Tests/ # xUnit + FluentAssertions + NSubstitute
└── CodeExplorer.Benchmarks/ # BenchmarkDotNet
Every meaningful dependency is behind an interface and registered as a singleton in DI:
| Interface | Default | When to replace |
|---|---|---|
ISymbolSummarizer |
SignatureFallbackSummarizer |
Custom summary extraction logic |
IRepositoryClient |
OctokitRepositoryClient |
Custom GitHub auth, GitLab, Gitea, etc. |
IIndexStore |
JsonFileIndexStore |
Store index in a database |
ISecurityFilter |
DefaultSecurityFilter |
Custom file exclusion rules |
ILanguageDetector |
DefaultLanguageDetector |
Add custom language extensions |
This project was originally developed as DotNetCodeMunch and has been renamed to CodeExplorer (cxp). The core architecture — tree-sitter AST parsing, BM25/fuzzy search, byte-offset retrieval, and DI-based extensibility — originates from the CodeMunch concept.
All grammars ship with TreeSitter.DotNet — no extra native libraries needed.
| Language | Extensions | Symbol types |
|---|---|---|
| Python | .py |
function, class, method, constant |
| JavaScript | .js, .jsx, .mjs, .cjs |
function, class, method, constant |
| TypeScript | .ts, .tsx, .mts, .cts |
function, class, method, interface, type, enum, constant |
| Go | .go |
function, method, type, constant |
| Rust | .rs |
function, type, constant |
| Java | .java |
class, method, field |
| PHP | .php |
function, class, method, constant |
| C# | .cs |
class, interface, enum, method, property, field, constant |
| C | .c, .h |
function, type, constant |
| C++ | .cpp, .hpp, .cc, .cxx, .hh |
function, class, method, type, field |
| Ruby | .rb, .rake, .gemspec |
function, class, method, module, constant |
| Swift | .swift |
function, class, method, type, enum, property |
| Scala | .scala, .sc |
function, class, method, type |
| Haskell | .hs |
function, type, class |
| Julia | .jl |
function, type, module, constant |
| OCaml | .ml, .mli |
function, type, module |
| Bash | .sh, .bash |
function |
| Agda | .agda |
function, type |
| CodeQL | .ql, .qll |
function, class, module |
| SystemVerilog | .sv, .v, .svh |
function, method, module |
| Language | Extensions | Notes |
|---|---|---|
| HTML | .html, .htm |
Language detection & AST parsing (no symbol extraction) |
| CSS | .css |
Language detection & AST parsing (no symbol extraction) |
| JSON | .json |
Language detection & AST parsing (no symbol extraction) |
| TOML | .toml |
Language detection & AST parsing (no symbol extraction) |
| Razor | .razor, .cshtml |
Language detection (symbols extracted from embedded C#) |
# Build
dotnet build
# Run all unit tests
dotnet test tests/CodeExplorer.Core.Tests
# Run benchmarks (Release mode required)
dotnet run --project tests/CodeExplorer.Benchmarks -c Release
# Publish self-contained CLI
dotnet publish src/CodeExplorer.Cli -r linux-x64 -c Release --self-contained -p:PublishSingleFile=true
dotnet publish src/CodeExplorer.Cli -r win-x64 -c Release --self-contained -p:PublishSingleFile=true
dotnet publish src/CodeExplorer.Cli -r osx-arm64 -c Release --self-contained -p:PublishSingleFile=trueThis repository ships two workflows:
.github/workflows/ci.yml: build, test, and publish CLI artifacts on push/PR..github/workflows/release.yml: tag-based release pipeline that:- runs build + tests,
- packs and publishes
CodeExplorer.Coreto NuGet, - builds
cxpbinaries for Linux, Windows, and macOS, - creates a GitHub Release and uploads all CLI binaries.
Add the following repository secret in GitHub:
NUGET_API_KEY: API key with push permission forCodeExplorer.Core.
git tag v0.2.0
git push origin v0.2.0The release workflow will publish to NuGet and attach release binaries automatically.
| Variable | Purpose |
|---|---|
GITHUB_TOKEN |
Raises GitHub API rate limits and enables private repos |
CODE_INDEX_PATH |
Override default index path (~/.code-index) |
MIT