contextmaxxer

mcp
Security Audit
Warn
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.

SUMMARY

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.

README.md

Contextmaxxer

CI
License: MIT
Go
Release

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 into
compactBody 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.

Contextmaxxer terminal search result

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

  1. Download the archive for your platform from the
    latest release
    — Windows amd64 and Linux amd64, each with checksums.txt. Verify it, unpack
    it, and put contextmaxxer on PATH. INSTALL.md has the
    per-platform commands; Build from source has the
    toolchain list if you would rather build it yourself.

  2. Pre-download the models and ONNX Runtime:

    contextmaxxer warmup
    
  3. From the repository you want to search, wire it into your agent:

    contextmaxxer init --host claude-code .    # or: cursor, codex
    
  4. Restart 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:

  1. generated by the installed coding agent;
  2. generated by a local Ollama or LM Studio endpoint;
  3. 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.pending file, 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:

License

MIT © 2026 codeus-morbid

Reviews (0)

No results found