















https://github.com/HKUDS/Fastcode/
fastCode 是一款面向全面代码理解与分析的令牌高效型框架,可为大规模代码库和软件架构提供卓越速度、超高精度与高性价比。
🚀 速度优势显著 —— 运行速度比 Cursor 快 3 倍,比 Claude Code 快 4 倍。
💰 成本大幅降低 —— 费用比 Cursor 低 55%,比 Claude Code 低 44%。
⚡ 精度行业领先 —— 凭借最高准确率表现,优于 Cursor 与 Claude Code。
| 维度 | cocoindex (ccc mcp) | FastCode |
|---|---|---|
| Windows 稳定性 | ❌(你已经遇到) | ✅ |
| MCP 支持 | ⚠️ demo级 | ✅(设计更贴近 agent) |
| 查询延迟 | ⚠️ 中(embedding) | ✅ 更稳定 |
| 大项目 | ⚠️ 容易卡 | ✅ 更可控 |
Get FastCode running in under 2 minutes:
# 1. Clone the repository
git clone https://github.com/HKUDS/FastCode.git
cd FastCode
# 2. Install dependencies
pip install -r requirements.txt
# 3. Configure your API keys
cp env.example .env
# Edit .env with your API keys
# 4. Launch the Web UI
python web_app.py --host 0.0.0.0 --port 5000
# api
cd D:\AI-Local-Tool\FastCode\ && python api.py --host 0.0.0.0 --port 8000
Open http://localhost:5000 and start asking questions about your code! 🎉
Clone FastCode
git clone https://github.com/HKUDS/FastCode.git
cd FastCode
Install Dependencies
Option A: Using uv (Recommended)
# Install uv
pip install uv
# create new env with uv
uv venv --python=3.12
.venv\Scripts\activate
# Install dependencies with uv
uv pip install -r requirements.txt
Option B: Using pip
pip install -r requirements.txt
Configure Environment
copy env.example .env
notepad .env
Add your API keys:
OPENAI_API_KEY=your_openai_api_key_here
MODEL=qwen/qwen3-coder-30b-a3b-instruct
BASE_URL=https://api.openai.com/v1
Launch FastCode
# Web UI (Recommended)
python web_app.py --host 0.0.0.0 --port 5000
# 当前环境
cd D:\AI-Local-Tool\FastCode && python web_app.py --host 0.0.0.0 --port 5000
# Or use the CLI
python main.py query --repo-path C:\path\to\your\repo --query "Your question here"
# 示例
python main.py query --repo-path D:\WorkSpace\pum --query "Your question here"
Troubleshooting:
Troubleshooting: 故障排除:
pip install --upgrade certifipip install --upgrade certififaiss-cpu fails to install: pip install faiss-cpu --no-cache-dirfaiss-cpu安装失败:pip install faiss-cpu --no-cache-dir./run_nanobot.sh (bash script) on Windows, use Git Bash or WSL, and keep .sh files in LF line endings. This repo enforces LF for *.sh via .gitattributes, but older clones may need a one-time re-checkout.如果你在Windows上运行./run_nanobot.sh(bash脚本),.sh文件的行尾保持为LF。此仓库通过.gitattributes强制要求*.sh文件使用LF,但旧版本的克隆可能需要一次性重新检出。![[Pasted image 20260325110134.png]]
2026-03-25 10:50:46,402 - fastcode.cache - INFO - Initialized disk cache at D:\AI-Local-Tool\记忆\FastCode\data\cache
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit)
INFO: 127.0.0.1:53764 - "GET / HTTP/1.1" 200 OK
INFO: 127.0.0.1:53764 - "GET /assets/FastCode.svg HTTP/1.1" 304 Not Modified
2026-03-25 10:50:51,139 - fastcode.vector_store - INFO - Scanning available indexes...
2026-03-25 10:50:51,140 - fastcode.vector_store - INFO - Index scan complete: found 0 repositories
INFO: 127.0.0.1:53764 - "GET /api/status HTTP/1.1" 200 OK
INFO: 127.0.0.1:51442 - "GET /api/sessions HTTP/1.1" 200 OK
INFO: 127.0.0.1:51442 - "GET /api/sessions HTTP/1.1" 200 OK
INFO: 127.0.0.1:52507 - "GET /api/status HTTP/1.1" 200 OK
2026-03-25 10:51:03,200 - web_app - INFO - Indexing 1 repositories
2026-03-25 10:51:03,201 - fastcode - INFO - Loading 1 repositories
2026-03-25 10:51:03,201 - fastcode - INFO - [1/1] Loading repository: file:///D:/WorkSpace/pum/
2026-03-25 10:51:03,201 - fastcode - INFO - [1/1] Auto-detected source type as URL
2026-03-25 10:51:03,202 - fastcode.loader - INFO - Cloning repository from file:///D:/WorkSpace/pum/
2026-03-25 10:51:03,202 - fastcode.loader - WARNING - Repository path D:\AI-Local-Tool\记忆\FastCode\repos\pum already exists, moving to backup: D:\AI-Local-Tool\记忆\FastCode\repo_backup\pum_20260325_105103_202305
2026-03-25 10:51:08,449 - fastcode.loader - INFO - Successfully cloned to D:\AI-Local-Tool\记忆\FastCode\repos\pum
2026-03-25 10:51:08,579 - fastcode.loader - INFO - Scanning files in D:\AI-Local-Tool\记忆\FastCode\repos\pum
2026-03-25 10:51:08,580 - fastcode.loader - INFO - Loaded 56 patterns from .gitignore
2026-03-25 10:51:11,837 - fastcode.loader - INFO - Found 1326 supported files (17.59 MB total)
2026-03-25 10:51:11,837 - fastcode - INFO - Indexing repository: pum
2026-03-25 10:51:11,837 - fastcode.vector_store - INFO - Initializing vector store with dimension 384
2026-03-25 10:51:11,837 - fastcode.vector_store - INFO - Initialized HNSW index with cosine distance
2026-03-25 10:51:12,566 - fastcode.indexer - INFO - Starting repository indexing
2026-03-25 10:51:12,566 - fastcode.loader - INFO - Scanning files in D:\AI-Local-Tool\记忆\FastCode\repos\pum
2026-03-25 10:51:12,567 - fastcode.loader - INFO - Loaded 56 patterns from .gitignore
2026-03-25 10:51:15,599 - fastcode.loader - INFO - Found 1326 supported files (17.59 MB total)
2026-03-25 10:51:15,599 - fastcode.indexer - INFO - Indexing 1326 files for repository: pum
2026-03-25 10:51:15,613 - fastcode.repo_overview - INFO - Generating overview for repository: pum
2026-03-25 10:51:15,700 - fastcode.vector_store - INFO - Saved repository overview for pum
2026-03-25 10:51:15,700 - fastcode.indexer - INFO - Generated and saved repository overview for pum
Indexing files: 100%|██████████████████████████████████████████████████████████████| 1326/1326 [00:19<00:00, 68.66it/s]
2026-03-25 10:51:35,013 - fastcode.indexer - INFO - Indexed 6713 code elements for pum
2026-03-25 10:51:35,013 - fastcode.indexer - INFO - Generating embeddings for code elements
2026-03-25 10:51:35,248 - fastcode.embedder - INFO - Generating embeddings for 6713 code elements
Batches: 50%|███████████████████████████████████▌ | 105/210 [10:09<10:43, 6.13s/it]
最后,配置MCP。(#放弃)
{
"mcpServers": {
"fastcode": {
"command": "python",
"args": [
"D:/AI-Local-Tool/FastCode/mcp_server.py"
],
"env": {
"MODEL": "qwen3-coder-plus",
"BASE_URL": "https://apis.iflow.cn/v1",
"OPENAI_API_KEY": "sk-fd89e9c7402b782b44acde88e71521"
}
}
}
}
或者使用命令
python D:\AI-Local-Tool\FastCode\main.py query --repo-path D:\WorkSpace\pum\ --query "Your question here"
python D:\AI-Local-Tool\FastCode\main.py query --repo-path D:\WorkSpace\pum\ --query "分析订单编辑页面 edit.cshtml 的保存功能实现,查找:\n1. Save 方法的入口和实现\n2. 订单项目明细(OrderItem/ItemList)的数据处理逻辑\n3. IsDelete 字段的使用场景\n4. 数据保存流程中涉及的 Service 层方法"
D:\AI-Local-Tool\FastCode\fastcode\loader.py
原代码 :
if os.path.exists(repo_path):
self._backup_existing_repo(repo_path)
return repo_path
改为 :
if os.path.exists(repo_path):
self.logger.info(f"Repository path {repo_path} already exists, using
existing repository")
return repo_path
return repo_path
这样修改后,FastCode 会:
先启动
cd D:\AI-Local-Tool\FastCode\ && python api.py --host 0.0.0.0 --port 8000
写一个python放到项目根目录
fastcode_client.py
#!/usr/bin/env python
# ================================================================================
# -*- coding: utf-8 -*-
"""
FastCode API Client - PUM 项目代码搜索工具
================================================================================
命令汇总
================================================================================
# 状态查询
python fastcode_client.py --status # 查看API状态
python fastcode_client.py --status -o json # JSON格式查看状态
# 仓库加载与索引
python fastcode_client.py --init # 初始化仓库(加载+索引)
python fastcode_client.py --load-and-index # 一步完成加载和索引
python fastcode_client.py --force # 强制重新索引
# 仓库管理
python fastcode_client.py --delete-repos "d:\\WorkSpace\\pum-index-fastcode" # 删除仓库及索引
python fastcode_client.py --load-repos "pum-index-fastcode" # 加载多个已索引的仓库
# 代码查询
python fastcode_client.py -q "搜索内容" # 单次查询
"python fastcode_client.py -q "搜索内容" -s "session-name"" # 指定会话ID
python fastcode_client.py -q "搜索内容" -m # 多轮对话模式
python fastcode_client.py -q "搜索内容" -o json # JSON格式输出
# ================================================================================
使用方法:
python fastcode_client.py --question "搜索问题" [--session-id "session-name"] [--multi-turn]
示例:
python fastcode_client.py --question "分析订单保存功能"
python fastcode_client.py --question "OrderController Save方法" --session-id "order-analysis" --multi-turn
"""
import argparse
import json
import requests
import sys
from typing import Optional, Dict, Any, List
class FastCodeClient:
"""FastCode API 客户端"""
DEFAULT_URL = "http://localhost:8000"
DEFAULT_REPO_NAME = "pum-index-fastcode"
DEFAULT_REPO_PATH = "d:\\WorkSpace\\pum-index-fastcode"
def __init__(self, base_url: str = None, repo_path: str = None):
self.base_url = base_url or self.DEFAULT_URL
self.repo_path = repo_path or self.DEFAULT_REPO_PATH
self.repo_name = self.DEFAULT_REPO_NAME
self.session = requests.Session()
def load_repo(self) -> Dict[str, Any]:
"""加载仓库"""
url = f"{self.base_url}/load"
payload = {"source": self.repo_path}
response = self.session.post(url, json=payload)
response.raise_for_status()
return response.json()
def index_repo(self, force: bool = False) -> Dict[str, Any]:
"""索引仓库"""
url = f"{self.base_url}/index?force={str(force).lower()}"
payload = {"source": self.repo_path}
response = self.session.post(url, json=payload)
response.raise_for_status()
return response.json()
def get_status(self) -> Dict[str, Any]:
"""获取状态"""
url = f"{self.base_url}/status"
response = self.session.get(url)
response.raise_for_status()
return response.json()
def load_and_index(self) -> Dict[str, Any]:
"""加载并索引仓库(一步完成)"""
url = f"{self.base_url}/load-and-index"
payload = {"source": self.repo_path, "is_url": False}
response = self.session.post(url, json=payload)
response.raise_for_status()
return response.json()
def delete_repos(self, repo_names: List[str], delete_source: bool = True) -> Dict[str, Any]:
"""删除仓库及其索引"""
url = f"{self.base_url}/delete-repos"
payload = {"repo_names": repo_names, "delete_source": delete_source}
response = self.session.post(url, json=payload)
response.raise_for_status()
return response.json()
def load_repositories(self, repo_names: List[str]) -> Dict[str, Any]:
"""加载多个已索引的仓库"""
url = f"{self.base_url}/load-repositories"
payload = {"repo_names": repo_names}
response = self.session.post(url, json=payload)
response.raise_for_status()
return response.json()
def query(
self,
question: str,
session_id: Optional[str] = None,
multi_turn: bool = True,
filters: Optional[Dict] = None,
repo_filter: Optional[List[str]] = None
) -> Dict[str, Any]:
"""
执行查询
Args:
question: 查询问题
session_id: 会话ID(用于多轮对话)
multi_turn: 是否启用多轮对话
filters: 过滤条件
repo_filter: 仓库过滤列表
Returns:
查询结果
"""
url = f"{self.base_url}/query"
payload = {
"question": question,
"filters": filters,
"repo_filter": repo_filter or [self.repo_name],
"multi_turn": multi_turn,
"session_id": session_id or "default-session"
}
response = self.session.post(url, json=payload)
response.raise_for_status()
return response.json()
def ensure_ready(self, force: bool = False) -> bool:
"""确保仓库已加载并索引"""
try:
status = self.get_status()
if status.get("repo_indexed"):
return True
except:
pass
try:
print("正在加载仓库...")
self.load_repo()
print("正在索引仓库...")
self.index_repo(force=force)
print("仓库准备完成!")
return True
except Exception as e:
print(f"仓库准备失败: {e}")
return False
def main():
parser = argparse.ArgumentParser(
description="FastCode API Client - PUM 项目代码搜索工具",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
# 埥询
python fastcode_client.py -q "分析订单保存功能"
# 多轮对话
python fastcode_client.py -q "OrderController Save方法" -s "order-analysis" -m
# 检查状态
python fastcode_client.py --status
# 初始化仓库
python fastcode_client.py --init
# 强制索引
python fastcode_client.py --force
"""
)
parser.add_argument(
"-q", "--question",
type=str,
help="查询问题"
)
parser.add_argument(
"-s", "--session-id",
type=str,
default=None,
help="会话ID(用于多轮对话)"
)
parser.add_argument(
"-m", "--multi-turn",
action="store_true",
default=True,
help="启用多轮对话(默认启用)"
)
parser.add_argument(
"--status",
action="store_true",
help="获取API状态"
)
parser.add_argument(
"--init",
action="store_true",
help="初始化仓库(加载并索引)"
)
parser.add_argument(
"--force",
action="store_true",
help="强制重新索引"
)
parser.add_argument(
"--load-and-index",
action="store_true",
help="加载并索引仓库(一步完成)"
)
parser.add_argument(
"--delete-repos",
type=str,
nargs="+",
help="删除仓库及其索引(提供仓库名列表)"
)
parser.add_argument(
"--load-repos",
type=str,
nargs="+",
help="加载多个已索引的仓库(提供仓库名列表)"
)
parser.add_argument(
"--url",
type=str,
default="http://localhost:8000",
help="FastCode API URL(默认: http://localhost:8000 )"
)
parser.add_argument(
"--repo",
type=str,
default="d:\\WorkSpace\\pum-index-fastcode",
help="仓库路径(默认: d:\\WorkSpace\\pum-index-fastcode)"
)
parser.add_argument(
"-o", "--output",
type=str,
choices=["text", "json"],
default="text",
help="输出格式(默认: text)"
)
args = parser.parse_args()
client = FastCodeClient(base_url=args.url, repo_path=args.repo)
if args.status:
try:
status = client.get_status()
if args.output == "json":
print(json.dumps(status, indent=2, ensure_ascii=False))
else:
print(f"状态: {status.get('status')}")
print(f"仓库已加载: {status.get('repo_loaded')}")
print(f"仓库已索引: {status.get('repo_indexed')}")
if status.get("repo_info"):
info = status["repo_info"]
print(f"仓库名: {info.get('name')}")
print(f"文件数: {info.get('file_count')}")
except Exception as e:
print(f"错误: {e}")
sys.exit(1)
return
if args.force:
try:
print("正在强制重新索引仓库...")
client.index_repo(force=True)
print("索引完成!")
return
except Exception as e:
print(f"索引失败: {e}")
sys.exit(1)
if args.load_and_index:
try:
print("正在加载并索引仓库...")
client.load_and_index()
print("加载并索引完成!")
return
except Exception as e:
print(f"加载并索引失败: {e}")
sys.exit(1)
if args.delete_repos:
try:
print(f"正在删除仓库: {args.delete_repos}...")
client.delete_repos(args.delete_repos)
print("删除完成!")
return
except Exception as e:
print(f"删除失败: {e}")
sys.exit(1)
if args.load_repos:
try:
print(f"正在加载仓库: {args.load_repos}...")
result = client.load_repositories(args.load_repos)
print("加载完成!")
print(json.dumps(result, indent=2, ensure_ascii=False))
return
except Exception as e:
print(f"加载失败: {e}")
sys.exit(1)
if args.init:
try:
client.ensure_ready(force=args.force)
except Exception as e:
print(f"初始化失败: {e}")
sys.exit(1)
return
if not args.question:
parser.print_help()
sys.exit(1)
try:
if not client.ensure_ready():
print("仓库未准备好,请先运行 --init")
sys.exit(1)
result = client.query(
question=args.question,
session_id=args.session_id,
multi_turn=args.multi_turn
)
if args.output == "json":
print(json.dumps(result, indent=2, ensure_ascii=False))
else:
answer = result.get("answer", "")
print(answer)
if result.get("sources"):
print("\n--- 相关文件 ---")
for source in result.get("sources", []):
print(f" - {source}")
except Exception as e:
print(f"查询错误: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。