codesearch
Semantic search over local source repositories and forum archives, exposing tools to list sources, search code, read code, and search forum discussions.
README
codesearch
Semantic search over local source repositories and forum/mailing-list archives, exposed both as a shell CLI and as an MCP server so any LLM (Claude Code, a local model, whatever speaks MCP) can look things up while helping you debug.
This is the retrieval half of warpembot, extracted and made project-agnostic. No email, no GitHub, no auto-replying — just indexing and querying.
The csbot command
One entry point for everything:
./csbot init warp https://github.com/warpem/warp.git --kb archives/warp-group.mbox
Registers a codebase (cloning it if you give a git URL, or just pointing at a
local checkout), ingests any accumulated discussion archive you have for it, and
builds the embeddings. --kb is optional — with no archive you get a
code-only knowledge base. Missing archives are reported and skipped, not fatal.
./csbot update --pull
git pulls each registered repo and re-embeds only the files whose checksums
changed. Drop --pull to index local edits; name repos to do a subset.
./csbot ask "why does frame series alignment deselect items" --repo warp
Retrieves the relevant source and prior discussions, sends them to a local
Ollama chat model, and prints the answer followed by the file:line citations it
drew on. Useful flags: --no-forum (code only), -k N (more context),
--model (override the chat model), and --context-only, which prints the
assembled context instead of generating — paste it into Claude or any other
model when you want a stronger answer than the local one.
./csbot status
./csbot kb warp-group archives/more-threads.mbox
status shows chunk/document counts per source and flags repos whose path has
gone missing. kb adds discussion knowledge to an existing project later.
Two models are involved and they are configured separately in config.json:
embedding_model (used for indexing and search — changing it invalidates every
index) and chat_model (used only by csbot ask to write the answer).
Components
The csbot wrapper is thin; the pieces underneath stay usable on their own.
| File | Purpose |
|---|---|
csbot |
Single CLI entry point: init, update, ask, kb, status |
cs_common.py |
Config, Ollama embeddings, on-disk vector index, chunk metadata |
cs_index.py |
Build/update indexes: repos (incremental), mbox archives, text/JSON dumps |
cs_server.py |
MCP stdio server: list_sources, search_code, read_code, search_forum |
cs_query.py |
Shell CLI: code, forum, context |
config.json |
Which repos and corpora exist, embedding model, chunking params |
Everything is local: embeddings come from Ollama, indexes are .npz files of
L2-normalized vectors, search is a dot product. No external services.
Setup
pip install -r requirements.txt
ollama pull embeddinggemma:300m
embeddinggemma:300m is the default embedding model: ~600 MB and 768-dim,
which keeps indexing and query latency sane on Apple silicon.
Vectors from different embedding models are not comparable, so changing
embedding_model invalidates every index. index/manifest.json records which
model built the indexes: csbot update refuses to write into a mismatched index,
and the query paths warn instead of returning nonsense. To switch models,
delete index/ and rebuild.
Each family also wants its own query/document prefixes (Qwen's Instruct:
block, Gemma's task: search result | query:, Nomic's search_query:). These
live in EMBED_PROFILES in cs_common.py and are selected automatically from
the model name — add an entry there if you use something else.
Because embeddinggemma's context window is 2048 tokens, chunk_size defaults
to 100 lines with 25 lines of overlap. If you move to a long-context embedder
such as nomic-embed-text (8192), raising chunk_size back to 200 is safe.
Then use csbot init to register codebases, or edit config.json by hand:
repos— name → path of each checkout you want searchable (relative paths resolve against this directory;~works).corpora— name → directory holding forum/mailing-list documents as JSON.
Direct access to the layers
csbot covers the normal workflow; these are the same operations unwrapped, for
scripting or partial re-indexing.
Indexing
python3 cs_index.py repos
Walks every configured repo, chunks source files into overlapping line
windows (chunk_size/chunk_overlap), and embeds them. It checksums each file, so re-running only re-embeds
what changed — run it after a git pull.
python3 cs_index.py mbox warp-group archive.mbox
Imports a mailing-list archive (Google Groups exports an mbox) into a corpus.
cs_index.py text <corpus> <dir> does the same for a directory of .txt,
.md, or .json posts — use it for scraped forum threads; JSON items may
carry id, title, author, date, body, url.
python3 cs_index.py status
Shows chunk/document counts per source and flags repos whose path is missing.
Querying from the shell
python3 cs_query.py code "how are CTF parameters fitted" --repo warp --show
python3 cs_query.py forum "tilt series stuck at 0%"
python3 cs_query.py context "why does frame series alignment deselect items" --repo warp --forum
context prints a paste-ready block — question, matching source with line
numbers, optionally prior discussions — for feeding to a model that has no
tools of its own.
Querying from an LLM (MCP)
.mcp.json registers the server — edit the placeholder path to point at your
clone, then copy the block into any project's .mcp.json (or your MCP client's
config) and the model gets four tools:
list_sources()— what's indexedsearch_code(query, repo="", top_k=5)— file + line range + scoreread_code(repo, file, start_line, end_line)— the actual linessearch_forum(query, corpus="", top_k=5)— prior discussions
The server loads indexes into memory at startup, so restart it after re-indexing.
Guidance worth putting in your CLAUDE.md (or system prompt): search code with
a targeted query derived from the question, read the real source before
answering, and treat forum hits as leads rather than truth — archived answers
go stale when the software changes.
Reusing the warpembot data
The 2188-message Google Group corpus is already in corpora/warp-group/, copied
from ../warpembot-public/threads/. load_doc maps the old
message_id/subject/sender keys onto id/title/author, so it needs no
conversion — only re-embedding:
python3 cs_index.py rebuild warp-group
The prebuilt .npz indexes that shipped with warpembot were built with
qwen3-embedding:8b and are therefore unusable under the current model. They
are parked in index_qwen8b_legacy/ — delete that directory once the rebuild
is done, or restore it if you ever switch back.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。