Skip to main content
Glama
README.md
# repo-scout —— 计划-执行-反思的代码库调研 Agent + MCP Server

[![CI](https://github.com/RexVane/repo-scout/actions/workflows/ci.yml/badge.svg)](https://github.com/RexVane/repo-scout/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](pyproject.toml)

> 给它一个本地仓库路径,它像新人 onboarding 一样自主调研:
> **规划要看什么 → 用只读工具(list_tree/read_file/grep_files)渐进式探索 → 反思还有什么没搞清
> → 在预算内继续 → 产出带 `file:line` 引用的架构/关键模块/如何跑起来/风险点报告**。
>
> 整体可打包成 **MCP Server**,在 Claude Desktop / Cursor 里直接调用 —— 缩小版的 Claude Code。

这是配套 [`agent-kernel`](https://github.com/RexVane/agent-kernel)(手写 Agent 内核)的第二个项目:agent-kernel 讲清"Agent 的核心循环怎么转",repo-scout 在它之上回答"**面对装不下上下文的真实仓库,Agent 怎么治理上下文、怎么保证结论有据可查、怎么防止跑飞烧钱**"。

## 架构

```
                    python main.py <仓库路径>  /  MCP: investigate_repo(...)
                                    ▼
┌──────────────── scout/pipeline.py:PLAN → EXPLORE → REFLECT → REPORT ────────────────┐
│                                                                                       │
│  PLAN    只读 README + 目录树(便宜的概览) ──► 模型列出"要调查清楚的问题清单"           │
│    │                                                                                  │
│    ▼                                                                                  │
│  EXPLORE 带着问题跑工具调用循环:grep 定位 → read 精读,每个结论落到 file:line         │
│    │      (循环预算:每问题 N 步 × 未解问题数,不超过全局步数上限)                     │
│    ▼                                                                                  │
│  REFLECT 模型自查:"哪些问题还没有 file:line 证据支撑?" ──┐                             │
│    │                                                     │ 有未解 & 预算未尽          │
│    │  全解决 / 反思额度用尽 / 预算耗尽                    └──► 带提示回到 EXPLORE      │
│    ▼                                                          (最多 2 轮反思)          │
│  REPORT  汇总成结构化 onboarding markdown,每个结论带 file:line,未解问题诚实单列      │
│                                                                                       │
└──── scout/tools.py:list_tree / read_file(带行号) / grep_files —— 只读,锁死在仓库内 ──┘
```

## 快速开始

```bash
pip install -r requirements.txt
cp .env.example .env       # 填 API Key(Anthropic 或 DeepSeek 等国产模型二选一)

# 调研一个仓库,报告打印到终端(进度打到 stderr)
python main.py D:/AIApp/agent-kernel

# 带侧重点、写到文件、收紧预算
python main.py D:/AIApp/agent-kernel --focus "重点看核心循环与上下文压缩" --out report.md --max-steps 30

python -m pytest tests/ -q   # 离线单测(FakeProvider,无需 Key,真实工具在临时仓库上跑)
```

## 模型接入(双通道,与 agent-kernel 同源)

| 通道 | 配置 |
|------|------|
| Anthropic Claude | `LLM_PROVIDER=anthropic` + `ANTHROPIC_API_KEY`(默认 `claude-opus-4-8`,自适应思考) |
| OpenAI 兼容(国产) | `LLM_PROVIDER=openai_compat` + `OPENAI_API_KEY` + `OPENAI_BASE_URL`(DeepSeek/Qwen/GLM/Kimi) |

`scout/llm.py` 用统一的内部消息格式把两家 Function Calling 的线上差异隔离在 Provider 层,业务代码不感知厂商 —— **切模型只改环境变量**。

## 它如何模仿 Claude Code 的上下文治理

一个真实仓库有几千个文件、几十万行代码,**整库塞进上下文既超窗又烧钱**,这是所有"代码 Agent"的第一道坎。repo-scout 的做法和 Claude Code 同一个思路 —— **渐进式披露(progressive disclosure)**,绝不一次性喂全部:

1. **先概览,不读正文**:PLAN 阶段只读 `README` + 两层目录树,用最小的 token 建立"这仓库大概长什么样"的心智模型,再让模型据此列出要调查的问题。
2. **按需检索,而非全量加载**:EXPLORE 阶段先 `grep_files` 定位(只回 `file:line:内容`),锁定后才 `read_file` 精读**相关片段**(带行号、超 8KB 截断可翻页)。上下文里只留下与当前问题相关的少量代码,而不是整个文件、整个目录。
3. **发现落盘、跨轮累积**:每轮探索的结论沉淀进 `findings`(带 `file:line`),下一轮反思/探索基于它继续,而不是把原始工具输出无限堆在对话里。

对照 agent-kernel 里的"滑动窗口 + 中段摘要"压缩:那是**被动**地在上下文超阈值时压缩历史;这里是**主动**地一开始就控制"什么该进上下文"。两者互补 —— 真正的 Claude Code 两者都做。

## 接入 Claude Desktop(MCP)

把 repo-scout 作为 MCP Server 挂到 Claude Desktop,就能在对话里让 Claude 直接"调研某个本地仓库"。编辑配置文件:

- macOS:`~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows:`%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "repo-scout": {
      "command": "python",
      "args": ["-m", "scout.mcp_server"],
      "cwd": "D:\\AIApp\\repo-scout",
      "env": {
        "LLM_PROVIDER": "anthropic",
        "ANTHROPIC_API_KEY": "sk-ant-xxxx",
        "ANTHROPIC_MODEL": "claude-opus-4-8"
      }
    }
  }
}
```

重启 Claude Desktop 后会多出这些工具:

| 工具 | 作用 |
|------|------|
| `investigate_repo(repo_path, focus?)` | 高层:跑完整的计划-执行-反思流水线,直接给一份 onboarding 报告 |
| `list_tree` / `read_file` / `grep_files` | 低层:三个只读工具,让 Claude 自己驱动探索 —— 等于一个锁定在目标仓库内、带路径穿越防御的**安全只读文件浏览器** |

> 高层工具会消耗自身的模型 token(它内部要调 LLM);低层工具不消耗、纯本地读文件。两个层次都暴露,是为了展示 MCP "既能封装完整能力、又能暴露原子能力"的弹性。

## 面试怎么讲(每个设计点对应的考题)

| 设计点 | 对应面试题 | 你能讲的点 |
|--------|-----------|-----------|
| 四阶段状态机 | Claude Code 是怎样的多层架构?核心循环? | 感知(工具观察)→决策(LLM)→行动(工具)→反思,用一个 `dataclass` 状态 + `while` 驱动;节点/边/条件边一一对应 |
| PLAN 只读概览 | 上下文窗口管理?不能整库塞怎么办? | 渐进式披露:先 README+目录树,再按需 grep/read,只把相关片段进上下文 |
| REFLECT 自省 | 怎么让 Agent 不"假装做完"? | 让模型逐题自查"有没有 file:line 证据",未解的带提示回到探索 —— 用模型自己找盲点 |
| 循环预算 | 怎么防止 Agent 跑飞烧钱? | 步数上限(每问题 N 步 × 问题数、封顶全局)+ token 统计;熔断后仍产出报告而非崩溃 |
| 只读工具 + 路径防御 | 工具的安全边界在哪? | 安全边界在框架侧不在模型侧:resolve 后前缀校验锁死仓库目录;只读,天然无破坏面 |
| MCP Server | MCP / Function Calling / Skills 区别? | FC 是"模型表达调用意图"的机制,MCP 是"工具跨应用接入"的传输协议,Skills 是能力包 |
| 双通道 Provider | 国内外模型怎么切? | 统一内部消息格式,厂商差异关进 Provider,切模型只改环境变量 |

### 难点(主动讲)

- **上下文窗口管理**:最核心的难点。真实仓库装不下,所以设计成"概览→按需检索→发现落盘",把"什么进上下文"当成一等公民来管,而不是等超窗了再压缩。
- **反思环节让模型自省找盲点**:一次性的探索很容易"看起来查完了、其实关键问题没证据"。REFLECT 逼模型对每个问题给出"有/无 file:line 证据"的裁决,把未解问题带着"还缺什么"的提示送回探索 —— 这是从"像做完了"到"真做完了"的关键一跳。
- **循环预算防跑飞**:Agent 最怕在大仓库里无限 grep/read 烧钱。用"每问题 N 步 × 未解问题数、且不超过全局步数上限"双重封顶,预算耗尽就收尾出报告,绝不崩。

### 追问(想清楚再答)

- **agentic 检索 vs 向量 RAG,各自适用场景?**
  向量 RAG 是"离线切块→embedding→按相似度召回",适合**语义模糊、无结构、召回一段就够**的场景(问答、文档检索);agentic 检索是"模型带着目标,用 grep/read 等精确工具多步导航",适合**代码这种强结构、要精确定位到 file:line、且一个结论依赖多跳跳转**的场景。代码库调研里 grep 一个符号能精确命中定义处,比"把代码切块做 embedding 再模糊召回"更准、更可解释、也不用维护向量库。实践中常**混用**:向量召回粗定位候选文件,再用 agentic 工具精读求证 —— 这正是配套项目 `rag-quality-lab` 要探讨的检索质量问题。
- **反思成本怎么控?**
  反思每轮都要再调一次模型,不加限制会翻倍烧钱。三个手段:(1) 反思轮数封顶(默认 2 轮);(2) 反思只喂"问题清单 + 精简 findings"、不重放整段探索历史;(3) 反思输出结构化 JSON 裁决(而非长篇大论),输出 token 小。更进一步可以用小模型/低 effort 专门做反思裁决 —— 反思是"判断有没有证据"的轻任务,不需要旗舰模型。

## 项目结构

```
scout/
├── llm.py          # 双通道 Provider(Anthropic / OpenAI兼容 / FakeProvider),与 agent-kernel 同源
├── tools.py        # 只读三件套 list_tree/read_file/grep_files,锁死仓库目录 + 路径穿越防御
├── pipeline.py     # 核心:PLAN→EXPLORE→REFLECT→REPORT 状态机 + 循环预算(注释含 LangGraph 对应)
└── mcp_server.py   # FastMCP(stdio) 暴露 investigate_repo 及三个低层只读工具
main.py             # CLI 入口
tests/test_scout.py # 工具安全 + 流水线行为单测(FakeProvider,无需 Key)
```

## 已知边界(被追问时的诚实回答)

- **不执行、不写入**:只读探索,不跑构建/测试。所以"如何跑起来"是从代码与配置**推断**出来的,不是实测验证的。要更可靠可加一个受控的 `run_command` 工具(需沙箱)。
- **token 统计是用量估算**:成本用固定价目表乘 token 数报量级,以官网实时价格为准。
- **反思质量取决于模型**:REFLECT 靠模型自省,模型若过度自信也可能误判"已解决"。生产可加"证据必须包含真实存在的 file:line"的机械校验兜底。
- **单仓库、单次会话**:没有跨会话记忆/增量更新。仓库很大时靠 `--focus` 和预算收敛范围。