🚀 RepoMap - 命令行工具與MCP服務器
RepoMap是一款強大的工具,主要用於幫助大語言模型(LLMs)理解和導航複雜的代碼庫。它既可以作為命令行應用程序進行按需分析,也可以作為MCP(模型上下文協議)服務器,為其他應用程序提供持續的代碼庫映射功能。通過生成軟件代碼庫的“地圖”,RepoMap能夠突出顯示重要文件、代碼定義及其相互關係。它利用Tree - sitter進行精確的代碼解析,並使用PageRank算法按重要性對代碼元素進行排序,確保始終優先顯示最相關的信息。
🚀 快速開始
RepoMap功能強大且易於使用。你可以通過命令行快速對代碼庫進行分析,也可以將其作為MCP服務器為其他應用提供服務。以下是一些基本的使用示例:
python repomap.py .
python repomap.py src/ --map-tokens 2048
✨ 主要特性
- 智能代碼分析:使用Tree - sitter解析源代碼並提取函數/類定義。
- 相關性排序:採用PageRank算法按重要性對代碼元素進行排序。
- 令牌感知:考慮令牌限制,以適應大語言模型的上下文窗口。
- 緩存機制:持久緩存,加快後續運行速度。
- 多語言支持:支持Python、JavaScript、TypeScript、Java、C/C++、Go、Rust等多種語言。
- 重要文件檢測:自動識別並優先處理重要文件(如README、requirements.txt等)。
📦 安裝指南
使用以下命令安裝所需依賴:
pip install -r requirements.txt
💻 使用示例
基礎用法
python repomap.py .
python repomap.py src/ --map-tokens 2048
python repomap.py file1.py file2.py
python repomap.py --chat-files main.py --other-files src/
python repomap.py --mentioned-files config.py --mentioned-idents "main_function"
python repomap.py . --verbose
python repomap.py . --force-refresh
python repomap.py . --model gpt-3.5-turbo
python repomap.py . --max-context-window 8192
python repomap.py . --exclude-unranked
該工具按以下順序對文件進行優先級排序:
--chat-files:這些文件優先級最高,因為它們被認為是你當前正在處理的文件。
--mentioned-files:這些文件優先級較高,因為它們在當前上下文中被明確提及。
--other-files:這些文件優先級最低,用於提供額外的上下文信息。
高級用法
python repomap.py . --verbose
python repomap.py . --force-refresh
python repomap.py . --model gpt-3.5-turbo
python repomap.py . --max-context-window 8192
python repomap.py . --exclude-unranked
python repomap.py . --mentioned-files config.py --mentioned-idents "main_function"
📚 詳細文檔
工作原理
- 文件發現:掃描代碼庫以查找源文件。
- 代碼解析:使用Tree - sitter解析代碼並提取定義/引用。
- 圖構建:創建一個圖,其中文件為節點,符號引用為邊。
- 排序:應用PageRank算法按重要性對文件和符號進行排序。
- 令牌優化:使用二分查找將最重要的內容適配到令牌限制內。
- 輸出生成:將結果格式化為可讀的代碼地圖。
輸出格式
該工具生成代碼庫的結構化視圖,顯示以下內容:
- 文件路徑和重要代碼段。
- 函數和類定義。
- 代碼元素之間的關鍵關係。
- 根據實際使用和引用進行優先級排序。
依賴項
tiktoken:用於各種大語言模型的令牌計數。
networkx:圖算法(PageRank)。
diskcache:持久緩存。
grep - ast:用於代碼解析的Tree - sitter集成。
tree - sitter:代碼解析框架。
pygments:語法高亮和詞法分析。
緩存機制
該工具使用持久緩存來加快後續運行速度:
- 緩存目錄:
.repomap.tags.cache.v1/
- 文件更改時自動失效
- 可以使用
--force - refresh清除緩存
支持的語言
目前支持具有Tree - sitter語法的語言:
- arduino
- chatito
- commonlisp
- cpp
- csharp
- c
- dart
- d
- elisp
- elixir
- elm
- gleam
- go
- javascript
- java
- lua
- ocaml_interface
- ocaml
- pony
- properties
- python
- racket
- r
- ruby
- rust
- solidity
- swift
- udev
- c_sharp
- hcl
- kotlin
- php
- ql
- scala
許可證
此實現基於Aider項目的RepoMap設計。
作為MCP服務器運行
RepoMap還可以作為MCP(模型上下文協議)服務器運行,允許其他應用程序訪問其代碼庫映射功能。
設置
- RepoMap MCP服務器使用STDIO(標準輸入/輸出)進行通信。傳輸層無需額外配置。
- 要將RepoMap設置為與Cline(或類似工具如Roo)配合使用的MCP服務器,請在Cline設置文件(例如
cline_mcp_settings.json)中添加以下配置:
{
"mcpServers": {
"RepoMapper": {
"disabled": false,
"timeout": 60,
"type": "stdio",
"command": "/usr/bin/python3",
"args": [
"/absolute/path/to/repomap_server.py"
]
}
}
}
請將"/absolute/path/to/repomap_server.py"替換為你實際的repomap_server.py文件路徑。
使用
- 運行
repomap_server.py腳本:
python repomap_server.py
- 服務器將啟動並通過STDIO監聽請求。
- 其他應用程序可以使用服務器提供的
repo_map工具生成代碼庫映射。它們必須將project_root參數指定為要映射項目的絕對路徑。
變更日誌
2025年7月13日 - 移除了project.json依賴項。修復了MCP服務器,使其在文件名處理方面對大語言模型更友好。
🔧 技術細節
開發背景
RepoMap完全基於Aider的Repo map功能,但我認為它與Aider沒有共享任何代碼。最初,我試圖從Aider中提取RepoMap類,移除所有與Aider特定的依賴項,然後將其變成一個命令行工具。但由於Python不是我的母語,我在實現過程中遇到了很大困難。
幾小時前,我有了一個不同的想法。我從Aider中提取了RepoMap及其相關代碼,並將其提供給一個大語言模型(可能是Claude或Gemini 2.5 Pro,記不清了),讓它為這個應用程序生成規範。它生成了一個非常詳細的應用程序規範(不包括MCP部分),然後我將其提供給Aider和Claude 3.7,由它們構建了這個命令行版本。
之後,我結合使用了Aider和Claude 3.7、Cline和Gemini 2.5 Pro Preview、Gemini 2.5 Flash Preview、Phind.com、Gemini.com、Claude.com和ChatGPT.com,經過幾個小時的努力,終於完成了MCP服務器的開發。需要再次強調的是,Python並非我的母語。
示例輸出
> python repomap.py . --chat-files repomap_class.py
Chat files: ['/mnt/programming/RepoMapper/repomap_class.py']
repomap_class.py:
(Rank value: 10.8111)
36: CACHE_VERSION = 1
39: TAGS_CACHE_DIR = os.path.join(os.getcwd(), f".repomap.tags.cache.v{CACHE_VERSION}")
40: SQLITE_ERRORS = (sqlite3.OperationalError, sqlite3.DatabaseError)
43: Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
46: class RepoMap:
49: def __init__(
93: def load_tags_cache(self):
102: def save_tags_cache(self):
459: def get_ranked_tags_map_uncached(
483: def try_tags(num_tags: int) -> Tuple[Optional[str], int]:
512: def get_repo_map(
utils.py:
(Rank value: 0.2297)
18: Tag = namedtuple("Tag", "rel_fname fname line name kind".split())
21: def count_tokens(text: str, model_name: str = "gpt-4") -> int:
35: def read_text(filename: str, encoding: str = "utf-8", silent: bool = False) -> Optional[str]:
importance.py:
(Rank value: 0.1149)
8: IMPORTANT_FILENAMES = {
27: IMPORTANT_DIR_PATTERNS = {
34: def is_important(rel_file_path: str) -> bool:
56: def filter_important_files(file_paths: List[str]) -> List[str]:
...
...
...