lgrep
Dual-engine code intelligence for OpenCode
Project Page · GitHub · Changelog
______________________________________________________________________
lgrep 为AI代理提供了更好的第一步。
而不是从 glob, grep,以及随机文件读取,代理可以:
- 当他们还不知道符号时,按意义搜索
- 当他们知道名称时,按符号搜索
- 打开代码前检查文件和仓库结构
- 跨多个会话和代理重用一个温暖的本地服务器
这就是整个过程:更少的糟糕搜索,更少的浪费上下文,更快地理解人类和代理。
什么是lgrep
lgrep 将两个互补的引擎组合在一个MCP服务器中:
- 语义引擎 -使用带有本地LanceDB存储的Voyage code 3嵌入进行自然语言代码搜索
- 符号引擎 -使用树形图解析和本地JSON索引的精确符号、轮廓和文本工具
使用语义引擎回答以下问题:
- “路由和服务之间在哪里强制执行身份验证?”
- “重试逻辑如何处理失败的请求?”
- “权限在哪里检查?”
使用符号引擎回答以下问题:
- “找到
authenticate功能” - “给我看看大纲
src/auth.py" - “获取符号源
UserService.login"
您的代码保持在本地。只有简短的语义查询和索引有效载荷才能进入Voyage。符号查找保持完全本地并且在没有API密钥的情况下工作。
为什么它存在
AI编码代理通常很早就会失败,而不是很晚。
它们之所以失败,是因为它们从错误的检索原语开始:
grep无法回答概念问题- 完整文件读取不相关代码上的浪费令牌
- 跨并行代理的重复本地探索重复了工作
lgrep 通过为代理提供一个与他们实际推理方式相匹配的搜索堆栈来修复这个问题:
- 按意图查找实现
- 缩小到正确的文件或符号
- 只检索重要的代码
对于重度OpenCode用户来说,这不是一个方便的插件。这是搜索基础设施。
为什么lgrep感觉不同
- 意向优先搜索 -特工在知道名字之前,可以先通过意思提问
- 精确结构工具 -文件大纲、存储库大纲、符号查找和文本搜索位于同一服务器中
- 本地第一存储 -向量和索引存在于磁盘上,而不是其他人的SaaS中
- 共享温暖过程 -一个HTTP MCP服务器可以为多个并发的OpenCode会话提供服务
- 商业上可用 -
lgrep麻省理工学院是否获得许可,因此允许商业使用
比较
lgrep与grep和ripgrep的比较
grep 和 rg 仍然是精确文本和正则表达式查找的正确工具。他们不擅长意图发现。
如果代码说 jwt.verify() 当您的代理询问“在哪里强制执行身份验证?”时,文本搜索往往会错过正确的入口点。语义搜索缩小了这一差距。
lgrep与mgrep
mgrep 是最接近的语义搜索比较点。
mgrep仅限于语义lgrep将语义搜索与符号和结构工具相结合mgrep面向云lgrep将向量保持在本地,并在代理之间共享一个温暖的服务器
lgrep vs jCodeMunch MCP
jcodemunch-mcp 是一个强符号优先的MCP服务器。它是围绕树型索引和精确的字节偏移检索构建的,当代理已经大致知道它想要什么符号并希望最小化上下文开销时,这就很好了。
lgrep 针对另一个问题进行了优化:代理还不知道符号,需要首先通过意图找到正确的实现,然后深入结构。
| grep/rg | mgrep | jCodeMunch MCP | lgrep | |
|---|---|---|---|---|
| 初始强度 | 精确文本/正则表达式 | 语义搜索 | 符号检索 | 语义发现+符号检索 |
| 语义搜索 | 否 | 是 | 否 | 是 |
| 符号工具 | 否 | 否 | 是 | 是 |
| 文件/仓库大纲 | 否 | 否 | 是 | 是 |
| 本地矢量存储 | 不适用 | 否 | 不适用 | 是 |
| 无API密钥模式 | 是 | 否 | 是 | 是(符号引擎) |
| 商业用途 | 是 | 订阅服务 | 根据README需要付费商业许可证 | 是(麻省理工学院) |
| 最佳第一个问题 | “查找此确切字符串” | “查找与此概念匹配的代码” | “找到此确切符号” | “查找实现此想法的代码” |
如果你想在没有语义层的情况下进行最精确的符号检索, jcodemunch-mcp 这是一个可信的选择。
如果你希望OpenCode代理从意图级发现开始,并且在同一服务器中仍然有符号工具, lgrep 更适合。
运作原理
建筑
flowchart LR
A[OpenCode Session 1] --> M[lgrep MCP Server]
B[OpenCode Session 2] --> M
C[OpenCode Session N] --> M
M --> S[Semantic Engine\nVoyage Code 3 + LanceDB]
M --> Y[Symbol Engine\ntree-sitter + JSON index]
S --> V[(Local vector store)]
Y --> J[(Local symbol store)]
S -. query embeddings .-> Q[Voyage API]Agent -> lgrep MCP server -> semantic engine + symbol engine语义引擎
- 在尊重的同时发现文件
.gitignore - 具有AST感知边界的块代码
- 用Voyage Code 3嵌入块
- 将矢量本地存储在LanceDB中
- 通过混合检索和重新排序进行搜索
符号引擎
- 使用树保姆解析源代码
- 提取函数、类、方法和相关结构
- 存储本地符号索引
- 在没有API调用的情况下提供符号搜索、轮廓和源检索
安装
需求
- Python 3.11+
- Voyage API键,如果需要语义搜索
从GitHub安装
pip install git+https://github.com/Sharper-Flow/lgrep.git从源代码安装
git clone https://github.com/Sharper-Flow/lgrep.git
cd lgrep
pip install .OpenCode的快速设置
stdio是本地默认值 对于单会话/单用户设置,不需要服务器进程。有关共享或多会话部署,请参阅 扩展:共享HTTP服务器 在......下面
1.获取Voyage API密钥
在以下位置创建密钥 网站 dash.voyageai.com.
您只需要将其用于语义引擎。符号引擎在没有它的情况下工作。
2.将其连接到OpenCode
对于单用户、单会话设置,stdio是本地默认设置。将此添加到 ~/.config/opencode/opencode.json:
{
"instructions": [
"~/.config/opencode/instructions/lgrep-tools.md"
],
"mcp": {
"lgrep": { "type": "local" }
}
}如果您更喜欢运行共享HTTP服务器(请参阅 第3节),交换 mcp.lgrep 块用于:
{
"mcp": {
"lgrep": {
"type": "remote",
"url": "http://localhost:6285/mcp",
"enabled": true
}
}
}或者让安装程序自动连接共享HTTP路径:
lgrep install-opencode该安装程序将:
- 创建
~/.cache/lgrep/用于索引和日志 - 添加一个
type: "remote"MCP入口指向http://localhost:6285/mcp - 复制包装好的
lgrep-tools.md指导和skills/lgrep/SKILL.md在您的OpenCode配置中 - 将指令文件附加到
instructions阵列,因此代理更喜欢lgrep第一
使用stdio lgrep install-opencode,先运行安装程序,然后更改 mcp.lgrep 在 opencode.json 到 { "type": "local" }.
重要提示:活性剂还必须暴露 lgrep_* 工具定义 工具清单。如果代理配置文件只允许 read/glob/grep,模型 即使配置了MCP服务器和指令,也无法选择lgrep 政策是存在的。
已安装的文件位于:
~/.config/opencode/instructions/lgrep-tools.md~/.config/opencode/skills/lgrep/SKILL.md
3.扩展:共享HTTP服务器
对于共享或多会话部署,请将lgrep作为持久HTTP服务器运行,而不是stdio:
VOYAGE_API_KEY=your-key \
LGREP_WARM_PATHS=/path/to/project-a:/path/to/project-b \
lgrep --transport streamable-http --host 127.0.0.1 --port 6285为什么选择HTTP而不是stdio?
使用stdio,每个OpenCode会话都会生成自己的服务器进程。随着 streamable-http,一个热服务器处理所有会话。启动HTTP服务器后,使用 type: "remote" MCP配置见上文第2节。
4.可选:生成 .lgrepignore
lgrep init-ignore /path/to/project5.可选:检查或修剪孤立语义缓存
lgrep prune-orphans --dry-run
lgrep prune-orphans --execute --cache-dir /path/to/cacheprune-orphans 默认情况下为模拟运行。使用 --execute 实际删除孤立的语义缓存目录。 --cache-dir 覆盖 LGREP_CACHE_DIR 单次跑步。 --execute 和 --dry-run 相互排斥;传递两个出口时出错。代理可以通过以下方式调用相同的工作流 lgrep_prune_orphans MCP工具列于 符号工具;该路径还会跳过当前正在运行的服务器中加载的项目。
格雷斯窗。 最近修改的缓存目录默认保留1小时,因此修剪器无法与实时索引器竞争。覆盖 LGREP_PRUNE_MIN_AGE_S= (0 完全禁用恩典)。这 missing_meta 和 project_path_enoent 原因绕过了宽限期检查,因为它们是明确的。
具有运输意识的MCP安全。 当通过共享传输到达lgrep时(例如 streamable-http),MCP工具强制 dry_run=True 而不管呼叫者的请求。共享部署上的破坏性修剪必须通过CLI(lgrep prune-orphans --execute)因此运算符是显式的。
故障排除 prune-orphans --execute
每个孤儿都被独立删除。如果 shutil.rmtree 一个条目失败(例如,文件锁或权限问题挥之不去),批处理继续进行,失败记录在响应中 failures[] 作为 {path, error}其余的开垦地仍在土地上。重新运行 lgrep prune-orphans --execute 在解决错误后,或用 --dry-run 首先确认孤儿仍然存在。
对于解析缓存目录之外的任何路径(路径限制保护)和任何符号链接缓存条目(TOCTU保护),都会被拒绝删除,这两种情况都会出现在 failures[] 而不是成功删除。
首次使用工作流程
典型的OpenCode流程:
- 问一个有意图的问题
lgrep_search_semantic - 检查结构
lgrep_get_file_outline或lgrep_get_repo_outline - 使用以下命令检索精确符号
lgrep_search_symbols和lgrep_get_symbol
示例:
lgrep_search_semantic(query="authentication flow", path="/path/to/project")
lgrep_get_file_outline(path="/path/to/project/src/auth.py")
lgrep_index_symbols_folder(path="/path/to/project")
lgrep_search_symbols(query="authenticate", path="/path/to/project")
lgrep_get_symbol(symbol_id="src/auth.py:function:authenticate", path="/path/to/project")高值提示:
- “我们在哪里强制路由和服务之间的身份验证?”
- “找到
authenticate功能” - “主要符号是什么
src/auth.py?" - “向我展示有关计费的回购结构”
- “查找参考文献
verifyToken"
刀具选择指南
| 任务 | 最佳工具 | 为什么 |
|---|---|---|
| 意图或概念发现 | lgrep_search_semantic | 按含义搜索 |
| 按名称查找函数或类 | lgrep_search_symbols | 精确符号查找 |
| 检查单个文件的结构 | lgrep_get_file_outline | 快速AST轮廓 |
| 检查回购结构 | lgrep_get_repo_outline | 符号级概述 |
| 查找精确的文本或标识符 | lgrep_search_text 或 grep | 文字匹配 |
| 检索符号的确切来源 | lgrep_get_symbol | 有针对性的代码检索 |
| 直接读取已知文件 | Read | 无需搜索 |
MCP响应格式
截至 3.0.0,每个lgrep MCP工具都返回一个与中声明的TypedDict匹配的结构化dict src/lgrep/server/responses.py。客户端应将响应作为本机字典使用——否 json.loads 需要。
示例-- lgrep_search_semantic:
{
"query": "authentication flow",
"path": "/path/to/project",
"engine": "hybrid",
"total": 3,
"results": [
{"file_path": "src/auth.py", "line_number": 42,
"content": "...", "score": 0.91,
"start_line": 42, "end_line": 87, "match_type": "hybrid"},
# ...
],
}engine 是 "hybrid" 当 hybrid=true (默认)或 "vector" 当 hybrid=false.
错误响应使用共享 ToolError 形状:
{"error": "VOYAGE_API_KEY not set. Cannot perform semantic search."}之前 3.0.0,工具将这些对象返回为 json.dumps(...) 串。如果从升级 2.x,删除任何 json.loads(response) 工具输出的包装器。看 从2.x升级 更改日志中关于完整迁移路径的注释。
MCP工具
语义工具
| 工具 | 目的 |
|---|---|
lgrep_search_semantic(query, path, limit=10, hybrid=true) | 按含义搜索代码 |
lgrep_index_semantic(path) | 构建或刷新语义索引 |
lgrep_status_semantic(path?) | 显示语义索引和观察者状态 |
lgrep_watch_start_semantic(path) | 启动背景语义重新索引 |
lgrep_watch_stop_semantic(path?) | 停止观察者 |
符号工具
| 工具 | 目的 |
|---|---|
lgrep_index_symbols_folder(path, max_files=500, incremental=True) | 本地文件夹中的索引符号 |
lgrep_index_symbols_repo(repo, ref="HEAD") | GitHub仓库中的索引符号 |
lgrep_list_repos() | 列出索引符号库 |
lgrep_get_file_tree(path, max_files=500) | 显示仓库文件树 |
lgrep_get_file_outline(path) | 显示一个文件的符号轮廓 |
lgrep_get_repo_outline(path, max_files=500) | 显示回购的符号轮廓 |
lgrep_search_symbols(query, path, limit=20, kind?) | 按名称搜索符号 |
lgrep_search_text(query, path, max_results=50) | 搜索文字文本 |
lgrep_get_symbol(symbol_id, path) | 检索一个符号 |
lgrep_get_symbols(symbol_ids, path) | 检索多个符号 |
lgrep_invalidate_cache(path) | 删除回购的交易品种索引 |
lgrep_prune_orphans(dry_run=True) | 报告(或与 dry_run=False,delete)孤立语义缓存dirs;跳过活动项目和 symbols/ 高速缓存 |
符号ID格式
符号ID使用这种确定性格式:
file_path:kind:name示例:
src/auth.py:function:authenticate
src/auth.py:class:AuthManager
src/auth.py:method:login运输和安保
lgrep 支持两者 stdio 和 streamable-http,但共享HTTP是OpenCode的预期部署模式。
lgrep --transport streamable-http --host 127.0.0.1 --port 6285安全注意事项:
- 默认主机为
127.0.0.1 - HTTP传输上没有内置的身份验证层
lgrep不设置CORS标头,基于浏览器的客户端不应直接连接到可流式传输的HTTP端点- 如果您确实将其置于代理之后,请在那里强制执行您自己的身份验证和来源控制
- 暴露
0.0.0.0是一种非默认、明确的选择加入;在没有反向代理或防火墙的情况下不要这样做
配置
环境变量
| 变量 | 必填 | 默认 | 描述 |
|---|---|---|---|
VOYAGE_API_KEY | 用于语义搜索 | none | Voyage API键 |
LGREP_LOG_LEVEL | 没有 | INFO | 日志冗长 |
LGREP_CACHE_DIR | 没有 | ~/.cache/lgrep | 缓存目录 |
LGREP_WARM_PATHS | 否 | 无 | 科隆分离的项目将在启动时升温 |
LGREP_AUTO_WATCH | 没有 | false | 自动启动预热项目的文件查看器 |
LGREP_TOOL_TIMEOUT_S | 没有 | 45 | 每个工具服务器端超时(秒)。为每个MCP工具调用设置边界。 |
LGREP_PRUNE_MIN_AGE_S | 没有 | 3600 | 宽限期(秒)之前 prune-orphans 将把一个模糊的孤儿(不可读的元/缺失的块)视为可修改的。 0 禁用恩典。 |
LGREP_TRANSPORT | 否(自动设置) | 未设置 | 运输类型(stdio/streamable-http)人口由 lgrep run_server。工具使用此应用运输安全意识。不要手动设置。 |
忽略行为
.gitignore自动遵守.lgrepignore允许您排除其他路径
示例 .lgrepignore 条目:
src/generated/
docs/site/
*.test.data资源配置文件
典型操作模式:
| 资源 | 空闲 | 索引期间 |
|---|---|---|
| RAM | ~300MB | ~500MB |
| CPU | \<1% | 通常本地CPU较低;Voyage承担了大部分语义上的繁重工作 |
| 磁盘 | 每个语义索引约250MB+每个符号索引约5MB | 随着索引项目的增长而增长 |
| 网络 | 最小 | 语义索引和语义查询调用Voyage |
支持的语言
- 语义引擎 -AST感知分块,支持30多种语言,需要时可进行文本回退
- 符号引擎 -树型语言包支持超过165种语言
故障排除
VOYAGE_API_KEY 未设置
在MCP服务器环境中设置密钥。没有它,符号引擎仍然可以工作。
慢速第一语义索引
第一次运行嵌入了整个项目。稍后的运行将使用哈希跳过未更改的文件。
Repository not indexed 来自符号工具
跑 lgrep_index_symbols_folder(path=...) 第一。
陈旧的语义结果
lgrep_search_semantic 现在,每次搜索前都会运行自动过期检查。 如果文件mtimes已经超过索引时间戳,并且内容哈希值已经超过 漂移后,它会自动重新索引。手册 lgrep_index_semantic(...) 是 仅在首次设置或强制刷新时需要; lgrep_watch_start_semantic(...) 仍然可用于在长时间运行的设置上进行主动后台重新索引。
本地依赖构建问题
lgrep 取决于具有本机扩展的包。预制车轮通常可以工作;否则,安装所需的编译器工具链。
从v1.x迁移
语义工具在 v2.0.0:
| v1.x | v2.x |
|---|---|
lgrep_search | lgrep_search_semantic |
lgrep_index | lgrep_index_semantic |
lgrep_status | lgrep_status_semantic |
lgrep_watch_start | lgrep_watch_start_semantic |
lgrep_watch_stop | lgrep_watch_stop_semantic |
发展
git clone https://github.com/Sharper-Flow/lgrep.git
cd lgrep
pip install -e ".[dev]"
pytest -v许可证
麻省理工学院-见 LICENSE.
______________________________________________________________________
