contextmaxxer
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Fully local MCP retrieval tool for coding agents. 161M encoder, ~1s per tool call, no API, no LLM in the query path. No file reads: line numbers, callers, callees and exact call sites, packed to a token budget. 2-4x the file coverage of BM25 and TF-IDF on SWE-Explore, and tops the paper's own sub-1B code model on CORE-Bench.
Contextmaxxer
Local code-graph search for coding agents.
Contextmaxxer gives Claude Code, Cursor and Codex an MCP tool for finding the
small set of symbols that answers a question — with source lines, callers,
callees and exact call sites already attached.
On CockroachDB's 90K symbols an agent driving it answered 6/6 architecture
questions with zero source-file reads — every answer cited from what the
tool returned, nothing opened by hand. That is the part that reproduces in
every run we have.
The speed ratios this section used to lead with are gone on purpose. They came
from single paired runs whose repeats vary by up to 57%, and latency turned out
to be roughly 2% of an agent's wall time anyway — a coefficient on the wrong
axis. What an agent actually spends is searches and answer weight.
BENCHMARK.md keeps the runs, the spread and the negative
results, including the one that matters most: whether this makes an agent write
better patches is not measured, and an early read on 25 SWE-bench instances
did not move it.
Everything needed for indexing and search runs locally. Your repository is not
uploaded to a search service.
When to reach for it, and when not to
Use it on a large codebase you do not already know, especially when
following a call chain ("what actually runs when X happens") or when you cannot
name the thing you are looking for and have to describe it.
Use grep instead on a small or familiar repository, or when you already know
the symbol's name. A text search is hard to beat when the name is the query;
this tool earns its keep when the haystack is large and the question is about
behaviour rather than spelling.
See the difference
Ask the agent a normal question:
fit retrieved symbols into the token budget
Contextmaxxer returns the relevant implementation and its structural context in
one response:
1. retrieve.Pack
internal/retrieve/packer.go:19-47
19 | func Pack(symbols []ScoredResult, budgetTokens int, fullBodyCount int) ([]ScoredResult, int) {
| ...
27 | var selected []ScoredResult
28 | total := 0
29 | for i, s := range symbols {
30 | if fullBodyCount >= 0 && i >= fullBodyCount {
31 | s.Body = compactBody(s)
32 | s.Detail = "compact"
Called by:
- retrieve.runPipeline
Calls:
- retrieve.compactBody packer.go:31
- retrieve.estimateTokens packer.go:36
Two things matter in that block. The body arrives line-numbered, so the
agent can cite packer.go:31 without reopening the file. And every neighbour
comes with the line where the call happens — following the chain intocompactBody costs no second search, whatever the size of the repository.
This example is a checked-in public self-eval case, not a prompt written after
seeing the ranking.
Why use it
- Fewer round-trips. One semantic query replaces repeated glob, grep and
file-read calls during code discovery. - Structure, not only similarity. Retrieval uses symbols, lexical and vector
search, the call graph, PageRank, a cross-encoder and an intent ranker. - Agent-ready evidence. Results are packed to a token budget and include the
relationships needed to follow a code path. - Local-first. Indexes, embeddings and feedback logs stay on your machine.
- Polyglot. Thirteen languages, all with symbols and call edges; Go, Python
and TypeScript resolve calls by declared type.
Contextmaxxer is designed for large codebases, where discovery fan-out becomes
the bottleneck. On small projects a strong model with grep is already cheap.
Quick start
Download the archive for your platform from the
latest release
— Windows amd64 and Linux amd64, each withchecksums.txt. Verify it, unpack
it, and putcontextmaxxeron PATH. INSTALL.md has the
per-platform commands; Build from source has the
toolchain list if you would rather build it yourself.Pre-download the models and ONNX Runtime:
contextmaxxer warmupFrom the repository you want to search, wire it into your agent:
contextmaxxer init --host claude-code . # or: cursor, codexRestart the agent and approve the contextmaxxer MCP server.
For a large repository, start with the structural index:
contextmaxxer --fast init --host claude-code .
This makes symbol, lexical and graph retrieval available first. Run warmup when
you are ready for semantic search and reranking.
The init command merges the host configuration instead of replacing it. Use
--no-write to print the proposed configuration without changing host files.
See INSTALL.md for the full agent-oriented installation flow.
How it works
flowchart LR
A["Source repository"] --> B["Tree-sitter symbols"]
B --> C["BM25 + local embeddings"]
B --> D["Call graph"]
C --> E["RRF seed fusion"]
D --> F["Personalized PageRank"]
E --> F
F --> G["Cross-encoder + intent ranker"]
G --> H["Token-budget evidence"]
H --> I["Coding agent"]
The index is a local SQLite database. Embeddings and reranking run through ONNX
Runtime; an in-memory vector cache keeps the non-model portion of a warm query
under tens of milliseconds.
The MCP server exposes:
- find_context — ranked, line-numbered symbols with graph context;
- expand_context — the full indexed body of one result, when its excerpt
cut the branch you needed; no second semantic search; - continue_context — the next page when a response reports
status:more; - record_feedback — optional usefulness labels tied to a retrieval request.
What it costs to keep running
The first index is the only slow part, and it is paid once.
| First index, 99 files / 995 symbols | 40.4 s |
| Re-index after editing one file | 230 ms — 1 file re-parsed, 98 skipped as unchanged |
| Server ready on CockroachDB's 90K symbols | 1.2 s, both ONNX models and a 278 MB vector cache loaded |
| Warm query, 90K symbols | median 996 ms, fastest 652 ms |
| Warm query, this repository | median 462 ms, fastest 246 ms |
Files are hashed, so a re-index touches only what actually changed; with--watch the server does this in the background while you edit and the models
stay loaded, so the 230 ms above is the whole cost of absorbing a change. The
vector cache is what keeps startup at a second: a cold SQL load of 90K
embeddings measured 39.5 s before it existed.
Measured on one consumer GPU (RTX 3060, DirectML) at the served default of five
results, driven through the real MCP server rather than a library harness. A
CPU-only machine will be slower; the shape — one slow index, cheap everything
after — does not change.
Latency is not the lever it looks like. Our own measurement puts it at roughly
2% of an agent's wall time; what actually costs the agent is how many searches
it runs and how heavy each answer is. The second is the reason there is no model
call in the query path at all.
Measured results
SWE-Explore: an external benchmark with published baselines
Everything else in this section is our own measurement. This one is not:
SWE-Explore hands an explorer an issue
and a repository snapshot and grades the ranked (file, start, end) regions it
returns against line-level ground truth distilled from the trajectories of
agents that actually solved the task — what a solver had to READ, not what the
patch changed. Every baseline below is the paper's own number.
All 848 instances, line budget B = 500. Two of our columns: the benchmark
ranks a list, so the list of 20 is the like-for-like comparison against
baselines that also return ranked lists — and the served default of 5 is
what the product actually hands an agent, measured the same way.
| Ctxmaxxer list of 20 |
Ctxmaxxer served (5) |
BM25 | TF-IDF | Potion (RAG) | CoSIL | Claude Code | Oracle | |
|---|---|---|---|---|---|---|---|---|
| HitFile | 0.529 | 0.342 | 0.079 | 0.140 | 0.088 | 0.544 | 0.667 | 0.923 |
| Prec | 0.339 | 0.396 | 0.055 | 0.117 | 0.055 | 0.581 | 0.598 | 1.000 |
| Rec_l | 0.047 | 0.036 | 0.021 | 0.049 | 0.025 | 0.788 | 0.154 | 0.953 |
| HitRegion | 0.375 | 0.267 | 0.065 | 0.121 | 0.069 | 0.544 | 0.531 | 0.915 |
Several times every non-agentic retriever on both columns — the served default
still reaches 2.4× the best of them. At the list of 20 the file coverage comes
within reach of CoSIL, the closest
comparison in kind because it localises from a call graph too; at the served
five it does not, and that gap is real. CoSIL puts a model inside the search
loop, up to ten calls an issue; here the graph is built once at indexing time
and a query needs no model at all.
Read the rest honestly:
- The five-result default trades a third of the file coverage for a sixth
more precision (0.529 → 0.342 HitFile, 0.338 → 0.396 Prec) and sends 58
visible lines instead of 89. That is the shipped tradeoff: the paper's own
analysis puts context efficiency at r = +0.950 with downstream resolve rate,
above every recall measure, and an agent that misses can rephrase and retry.
Both rows come from the same binary in one sitting; the list-of-20 arm
reproduced the published figures to three decimals, so the only difference
between the columns is how many results were asked for. - The agents are ahead on precision (0.598 and 0.581 against 0.396), and
CoSIL is ahead on every column. This is not a claim to beat them. - Line recall is our weakest number by an order of magnitude, and it is a
design position rather than a defect: bodies are trimmed to query-relevant
windows, so a 500-line budget carries 58-89 lines. Filling it is possible and
costs precision. - The comparison is like-for-like. Both sides are the same 848 instances;
all three sub-datasets are complete. One snapshot was found truncated by an
index-size check and re-fetched before scoring.
Protocol, per-repository breakdown, the sweeps, and the seven things that were
tried against the ceiling and failed are in
docs/research/swe-explore.md. The dataset is
CC-BY-NC-ND: numbers may be published, the data is not redistributed and no part
of it is in this repository.
Agent-level discovery
Paired agents answered the same questions on pinned public repositories.
| Repository | Correctness | Discovery calls | File reads | Wall time |
|---|---|---|---|---|
| Prometheus, grep | 5/5 | 51 | 4 | 142 s |
| Prometheus, Contextmaxxer | 5/5 | 8 | 0 | 47 s |
| CockroachDB, grep | 6/6 | 34 | 9 | 96 s |
| CockroachDB, Contextmaxxer | 6/6 | 7 | 0 | 45 s |
Both rows are the runs written up in BENCHMARK.md — Prometheus
from the paired-sonnet comparison, CockroachDB from the v0.1.0-beta.5
replication on six paraphrastic questions. Each is a single run; the same
measurement repeated on one arm has come back 57% apart, so the ratios are
indicative and the zero source reads are the durable part.
Raw token savings are situational because the agent's own base context can
dominate total usage.
BENCHMARK.md has the questions, the protocol, the limitations
and the negative results.
Retrieval quality
Start with the part you can run yourself. A public self-eval — 18 development
and 12 reserved queries over this repository — ships in internal/eval/testdata:
go build -o .task/build/eval ./cmd/eval
.task/build/eval --manifest internal/eval/testdata/manifest.public.json
Behind that, an internal 144-case corpus across five real projects was used
while developing the served configuration. Its 58-case reserved split measured
Hit@1 0.72, Hit@3 0.91, Recall@5 0.93, Recall@10 0.98. Those cases come from
private projects and are not published, so treat those numbers as our
development record rather than as something you can check.
CORE-Bench: the retrieval stage, isolated
SWE-Explore above scores the whole product. CORE-Bench scores one stage of it,
and that is exactly what makes it worth running: the dataset ships its own
corpus — {_id, text} chunks with no paths, symbol names or kinds — so the
extractors, the call graph, PageRank and the intent ranker are not in this path
at all. What remains is the embedder and the seed fusion, measured against
numbers we did not produce. A whole-pipeline table like the one above cannot
exist here, and a benchmark that isolates one stage is the right instrument for
comparing models rather than systems.
Level-2 issue-to-edit localization (arXiv:2606.11864,
HF zhangfw123/CORE-Bench): real GitHub issues as queries, per-query temporal
filters, 253 repositories, ~2,080 scoreable queries, ~2.2M corpus chunks. Every
row marked paper is the paper's own published number, read from v3 (EMNLP 2026,
revised 2026-08-24).
| Retriever | Params | NDCG@10 | Recall@100 |
|---|---|---|---|
| paper: gte-Qwen2-1.5B, general-purpose | 1.5B | 0.035 | 0.159 |
| paper: bge-m3, general-purpose | 568M | 0.046 | 0.183 |
| paper: CodeRankEmbed, code-specific | <1B | 0.121 | 0.329 |
| jina-v2-base-code + BM25, RRF — shipped default | 161M | 0.150 | 0.438 |
| paper: Qwen3-Embedding-8B, zero-shot | 8B | 0.203 | 0.480 |
| paper: SweRankEmbed-Large (CC-BY-NC) | 7B | 0.224 | 0.521 |
| research: ft2 fine-tune + BM25, RRF | 161M | 0.233 | 0.498 |
| paper: Qwen3-8B-SFT, their fine-tune | 8B | 0.328 | 0.664 |
Read that table as system against model, not model against model. Every
paper row is a retriever scoring alone; our row is that retriever fused with
BM25, which is what the product ships and therefore what a user gets — but it
is not a like-for-like encoder comparison. Stripped to the encoder, against
CodeRankEmbed — the paper's own code-specific model in the same sub-1B class —
the shipped default ties on NDCG@10 (0.122 against 0.121) and leads on
Recall@100 (0.383 against 0.329). The 0.150 is the fusion's, not the encoder's.
Against the general-purpose embedders of 3.5× and 9× its size the margin is
3-4× and survives either reading. A fine-tune of that same 161M encoder then
passes the 7B specialized retriever on NDCG@10 — trained only on
SWE-Bench-plus-plus, which shares no repository with the evaluation set, so the
gain is not contamination.
Fusion is where a small encoder earns that place. On the same full set:
| Seed stage | NDCG@10 | Recall@100 |
|---|---|---|
| vector only | 0.122 | 0.383 |
| vector + BM25, RRF-fused (k = 60) | 0.150 | 0.438 |
And the fine-tune's mechanism is the same effect again, which is the part worth
understanding: vector-only NDCG@10 barely moves under fine-tuning (0.142 →
0.141 on a repo-level holdout), while the fused score jumps 0.168 → 0.262. The
tuned model does not rank better on its own — it surfaces different relevant
chunks than BM25 does, and reciprocal rank fusion compounds two disagreeing
rankings. Two independent fine-tunes on disjoint training sets reproduced the
same relative gain (+56% and +55%) and the same flat-vector signature.
Read the limits with it:
- Recall@100 stays below SweRankEmbed-Large (0.498 against 0.521) even where
NDCG@10 passes it — though it clears the 8B zero-shot's 0.480. The fine-tune
fixes ordering more than it extends reach. - The paper's fine-tuned 8B remains clearly ahead at 0.328. Nothing
local-sized is close. - The sets are not identical. Our evaluation excludes Multi-SWE-bench and
the plus-plus split used for training; the paper's covers the full original. - This is a research result, not the install path. The product default is
jina-embeddings-v2-base-code, which is Apache-2.0 and commercially clean.
The fine-tuned weights are published separately as
jina-v2-code-ft2
under CC BY-NC-SA 4.0, inherited from the CORE-Bench training data — research
and reproduction only, not for commercial use. They are not installed by
default, and on short developer queries they trail the base model.
Throughput on a consumer GPU: 49 docs/s indexing, 51-76 ms per query embed.
Both the 0.6B upgrade candidate and a graph-blended fusion mode were measured
and rejected on this benchmark. BENCHMARK.md has the evaluation
boundary, the per-repository reproduction and every negative result.
Supported languages
Full, type-aware call resolution:
- Go
- Python
- TypeScript and JavaScript
Symbols and conservative call edges:
- Java
- Rust
- C
- C++
- C#
- PHP
- Ruby
- Kotlin
- Scala
Enrichment
Most symbols do not have useful docstrings. Contextmaxxer can add one-sentence
purpose summaries to the embedding text:
- generated by the installed coding agent;
- generated by a local Ollama or LM Studio endpoint;
- generated by an explicitly configured OpenAI-compatible API.
The first two paths stay local. The optional cloud path sends the selected
symbol metadata and code excerpt to the endpoint you configure. It is never
used implicitly.
See BETA.md for the current enrichment workflow.
Privacy
- Source code and indexes remain local during indexing and retrieval.
- A retrieval reaches the log only once something labels it — the agent calling
record_feedback, or the discovery hook observing that it reached for grep
straight afterwards. Unlabelled queries are discarded. - Between a query and its label, the most recent request waits in a single
feedback.jsonl.pendingfile, overwritten on every call and removed as soon
as it is labelled or discarded. That file is what lets the hook, which runs
as its own process, attribute what it sees. - What a labelled entry contains: the query, file paths, symbol names and
ranking features — never complete source bodies. - The log is capped at 64 MB and keeps one previous generation
(CONTEXTMAXXER_FEEDBACK_MAX_MB). CONTEXTMAXXER_FEEDBACK_ALL=1 logs
every response instead, for debugging ranking. - Disable feedback entirely with --feedback-log none.
- A redacted export hashes queries, paths and names before sharing.
- Optional cloud enrichment sends code excerpts only when you explicitly
configure an external endpoint.
Build from source
Source builds require Go, Rust and a C/C++ toolchain because the Hugging Face
tokenizer binding is a Rust static library linked through CGo.
task bootstrap
task test
task build
Build output goes to .task/build; it does not overwrite a binary in the
repository root.
The bootstrap scripts fetch one pinned upstream tokenizer commit and build it
with a pinned Rust toolchain. Windows requires a MinGW-compatible gcc.
Current limitations
- The first warmup downloads several hundred megabytes of models and runtimes.
- Windows amd64 and Linux amd64 are the initial release targets. macOS is not
packaged yet, and Intel macOS is unsupported outright — upstream ONNX Runtime
publishes no x86_64 darwin build for the pinned version. - CPU cross-encoder reranking is the dominant part of query latency.
- Benefits are modest on small repositories.
- Public reproduction currently covers the product's self-eval and the pinned
Prometheus experiment, not the private multi-project corpus.
Project status
Contextmaxxer is at v0.1.0, its first public release. Linux and Windows
amd64 archives are built by CI on a tag and published with checksums; the
release is gated on the packaged binary answering a real MCP handshake, not
merely compiling. The retrieval engine is actively dogfooded.
The 0.x is meant literally. What the tool returns is measured against an
external benchmark on all 848 instances, but whether it makes an agent write
better patches has not been measured, and there is no external usage to learn
from yet. Both are the next things worth doing rather than caveats to skip.
Detailed references:
- INSTALL.md — installation and host setup
- BETA.md — beta workflow and feedback
- BENCHMARK.md — product benchmark and research log
- docs/evaluation.md — reproducible public self-eval
- docs/research — research scope and artifact status
- ARCHITECTURE-NOTES.md — design positioning and limits
- CONTRIBUTING.md — development and pull requests
- SECURITY.md — private vulnerability reporting
- CHANGELOG.md — notable public changes
- ROADMAP.md — release direction and research gates
License
MIT © 2026 codeus-morbid
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found