Skip to content

LocusThe exact code chunk for the job.

Local BM25 search for agents. Ranked chunks, on the machine, with no API key and no vector database.

Locus
The difference

A file list is not a location.
A ranked chunk is.

Locus indexes the repository on the machine and returns the path, the line range, the symbol, and the chunk text. The ranker is BM25. The tool route id rust-tfidf is the historical name of that path, not a TF-IDF score.

What a filename search says

A path that contains the word, with no line range, no symbol, and no reason it ranked above the next file.

What Locus returns

path, startLine, endLine, symbol, BM25 score, and the chunk text. Filters run before limit.

One search. The words the code uses. ​

json
{
  "query": "authenticate request",
  "limit": 5,
  "file_extensions": ["ts"],
  "path_filter": "src/auth",
  "exclude_paths": ["src/auth/legacy"]
}

login does not match authenticate. Pass an absolute --root. Locus will not search the process working directory. The response field route is the string rust-tfidf.

How it works

Three steps from a question to a line

Step 1

Point it at the repository

One npx line with an absolute --root. A stdio MCP server starts for Claude, Cursor, VS Code, Codex, or any other MCP client. No API key.

Step 2

Search with tokens you can see

codebase_search refreshes the local index, scores every chunk that passes the filters, then cuts to limit. The default limit is 10.

Step 3

Expand from a hit you trust

find_related takes the repo-relative path and a line from that hit. It ranks other chunks by token overlap. It does not run BM25.

What you call

Two tools. Nothing else runs for you.

There is no search profile named auto, and there is no embedding path hiding behind the lexical one.

codebase_search

BM25 over symbol and file chunks. k1 is 1.2 and b is 0.75. Document frequency comes from the whole index, even when a path filter is set.

find_related

Starts from a chunk whose line range contains the line you pass. Other chunks are scored by shared tokens. The route id is rust-related.

Filters, then limit

file_extensions, path_filter, and exclude_paths choose the candidates. limit is applied after the score sort.

Limits

The defaults are the contract, not a benchmark.

BM25
the only ranker. No embeddings, no hybrid score, no synonym expansion.
1 MiB
files larger than 1,048,576 bytes are omitted. .json is not an indexed extension.
Regex
chunks come from line patterns, not tree-sitter. An indented method stays inside its class chunk.
.locus
new indexes are .locus/rust-index.json. .coderag/ is read only when that file is absent.

Skipped directory segments are node_modules, dist, target, and .git. This is not gitignore. A missing token is an empty result list, not a guessed synonym.

Install ​

bash
npx -y @sylphx/locus --root=/absolute/path/to/project
json
{
  "mcpServers": {
    "locus": {
      "command": "npx",
      "args": ["-y", "@sylphx/locus", "--root=/absolute/path/to/project"]
    }
  }
}
bash
claude mcp add locus -- npx -y @sylphx/locus --root=/absolute/path/to/project
bash
codex mcp add locus -- npx -y @sylphx/locus --root=/absolute/path/to/project

Search the tokens. Cite the lines.

No API key. codebase_search and find_related are the whole tool surface.

Read the quickstart Star the repo

Released under the MIT License.