mcpField
G
github-twin

github-twin

本地服务
github.com/ChristopherDavenport记忆与知识017 周前更新

关于 github-twin

github-twin 为编码 Agent 索引 GitHub 提交、代码和评审记录,支持个人或组织范围的检索。混合搜索结合 BM25 与向量检索,索引在本地运行,嵌入和 LLM 后端可配置。

主要功能

  1. 01索引提交、代码和评审记录
  2. 02结合 BM25 与向量的混合搜索
  3. 03支持 AST 的代码检索
  4. 04按仓库或作者筛选结果
  5. 05增量同步 GitHub 数据
  6. 06通过 MCP 提供检索工具

适用场景

  1. 01为新 diff 查找过往评审意见
  2. 02编写代码时查找个人代码示例
  3. 03搜索组织代码和评审历史
  4. 04为编码任务检索相关规则

MCP 相关

stdio MCP 服务向客户端提供检索、评审结果预测、模式摘要和同步工具。检索使用本地 SQLite 索引。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"christopherdavenport-github-twin": {
"command": "uvx",
"args": [
"github-twin"
],
"env": {
"GITHUB_TOKEN": "<GITHUB_TOKEN>",
"ANTHROPIC_API_KEY": "<ANTHROPIC_API_KEY>",
"GEMINI_API_KEY": "<GEMINI_API_KEY>",
"GT_PATHS__DATA_DIR": "<GT_PATHS__DATA_DIR>"
}
}
}
}
启动命令uvx github-twin
需要配置的环境变量
GITHUB_TOKEN密钥GitHub personal access token. Optional: github-twin can also pick the token up from `gh auth token` or from its own OAuth device-flow login (`gt auth login`).
ANTHROPIC_API_KEY密钥Optional. Enables the Claude backend for `gt summarize`, `gt distill`, and `gt eval`. Defaults to local Ollama when unset.
GEMINI_API_KEY密钥Optional. Enables the Gemini backend for embedding and the LLM seam. Vertex AI ADC via `GT_GEMINI_PROJECT` is also supported.
GT_PATHS__DATA_DIROptional. Override the on-disk data directory holding the SQLite index, embeddings, and cached GitHub responses. Defaults to `$XDG_DATA_HOME/github-twin`.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypigithub-twin0.0.17

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

github-twin

PyPI version Python versions CI License: MIT

六个月前,你审查过一项权限检查。Claude 不记得了。 github-twin 会记得——它会为你的提交和审查评论建立索引,并在 Agent 按照你的风格编写或审查新代码时,将相关内容作为检索结果呈现出来。

gt stats + gt eval search 返回真实语料库中的检索结果

Claude Code 通过 find_review_comments 工具引用过去的审查评论

现在就通过 Claude Code 试用——将以下内容放入 ~/.claude.json 并重新加载:

{
  "mcpServers": {
    "github-twin": { "command": "uvx", "args": ["github-twin", "serve"] }
  }
}

你的代码会留在本机。 嵌入在本地计算 (Ollama 或 sentence-transformers);只有 LLM 接口(gt summarize、 gt distill、gt eval)会选择性地调用托管服务商,而且也可以 切换为本地 Ollama。gemini 嵌入器是唯一的例外——仅限主动选择启用。


基于你的 GitHub 历史记录构建的个人 RAG,可作为 stdio 服务提供给 Claude Code(或任何 MCP 客户端)。两种范围,一套代码库:

  • 用户模式——为你自己的提交和审查评论建立索引。当 Agent 编写或审查新代码时,会呈现你过去的代码作为风格示例,并将你过去的评论作为审查提示。
  • 组织模式——为整个 GitHub 组织中所有成员的 HEAD 文件、提交和 PR 审查建立索引。查询可按仓库、语言或审查者登录名限定范围。

检索采用混合方式(BM25 + 通过 RRF 进行向量检索),使用 tree-sitter 感知 AST,支持 python/scala/javascript/typescript/go/rust,并在嵌入时通过每个分块的标头和可选的 LLM 生成摘要,添加上下文信息。

安装

最快的方式是使用 uvx——无需管理虚拟环境,每个工具都彼此隔离:

# One-shot
uvx github-twin --help

# Pinned version
uvx [email protected] --help

# With sentence-transformers for the alt embedder
uvx --with 'github-twin[st]' github-twin --help

如果你更喜欢在项目本地安装:

uv add github-twin            # or: pip install github-twin
gt --help

gt 和 github-twin 是同一个 Typer 应用——根据你的使用习惯任选其一。

身份验证

选择最省事的方式——github-twin 会按以下顺序尝试:

  1. OAuth 设备授权流程(无需安装 gh):
    uvx github-twin auth login        # opens browser, persists token
    uvx github-twin auth status       # show which source is active
    
    令牌会保存到操作系统密钥环(macOS Keychain / Linux Secret Service / Windows Credential Manager);若不可用,则保存到数据目录下权限为 0600 的文件中。
  2. 已有的 gh CLI:如果你已经运行过 gh auth login, gt 会通过 gh auth token 获取令牌——无需额外操作。
  3. GITHUB_TOKEN 环境变量:经典 PAT 也可使用;适用于 CI / 无头环境 / docker。所需范围:repo、read:org、user:email。

接入 Claude Code

MCP 服务通过 github-twin serve(或 gt serve)使用 stdio 运行。 在将要托管该服务的机器上运行一次 uvx github-twin auth login。

选项 A——通过 Claude Code 插件市场(最省事):

/plugin marketplace add ChristopherDavenport/christopherdavenport-marketplace
/plugin install github-twin@christopherdavenport

这会自动注册 MCP 服务条目;请在环境中(或在 ~/.claude.json 中该服务的 env 块里)设置 GT_PATHS__DATA_DIR,指向数据库目录。

选项 B——手动配置:向 ~/.claude.json(或 你的 mcp_servers.json)添加条目:

{
  "mcpServers": {
    "github-twin": {
      "command": "uvx",
      "args": ["github-twin", "serve"],
      "env": {
        "GT_PATHS__DATA_DIR": "/path/to/your/github-twin-data"
      }
    }
  }
}

如果你不想持久保存令牌,而是希望在调用时直接提供(CI、 临时容器),请在该 env 块中添加 "GITHUB_TOKEN": "ghp_...";它会作为优先级最低的备用令牌。

重新启动 Claude Code;届时即可使用 find_*、predict_review_outcome、 summarize_review_patterns 和 sync 工具。

快速入门

选择一个目录来存放 SQLite 数据库、配置和摄取缓存 — 每个数据目录中的所有内容都位于这个根目录下:

export GT_PATHS__DATA_DIR=~/github-twin-data
uvx github-twin auth login                 # one-time OAuth (or set GITHUB_TOKEN)

# user mode (your own GitHub history)
uvx github-twin init                       # discover identity via /user
uvx github-twin sync                       # ingest + summarize + embed
uvx github-twin serve                      # MCP server over stdio

# layer an org into the SAME DB
uvx github-twin init --kind org --org http4s
uvx github-twin sync

# OR keep the org in its own DB by switching data dirs
GT_PATHS__DATA_DIR=~/twin-http4s \
  uvx github-twin init --kind org --org http4s
GT_PATHS__DATA_DIR=~/twin-http4s uvx github-twin sync

后续运行时,gt sync 会增量同步。

config.toml 与数据库位于同一目录,即 <data_dir>/config.toml,并在首次调用 gt init --embed-backend ... 时创建。若未设置 GT_PATHS__DATA_DIR,默认 <data_dir> 为 $XDG_DATA_HOME/github-twin(或 ~/.local/share/github-twin)。

LLM 提供方矩阵

检索接口(find_*、predict_review_outcome)始终在 SQLite 索引上本地运行 — 不会调用 API。只有在以下三个场景中才会调用 LLM:

  • gt distill — 将审查评论/提交聚类为规则。
  • gt summarize — 生成每个分块的自然语言摘要,用作嵌入时的前缀。
  • gt eval reviews / eval predictions — 对留出数据进行 RAG 与基线评分。

每个操作都会按 Claude → Gemini → Ollama 的优先顺序选择后端(使用已设置 API 密钥的提供方),也可以显式指定后端。

提供方环境变量用途
Anthropic(Claude)ANTHROPIC_API_KEY蒸馏/摘要/评估 LLM。质量最佳。
Google(Gemini,API 密钥)GEMINI_API_KEY 或 GOOGLE_API_KEY蒸馏/摘要/评估 LLM。免费层额度充足。
Google(Gemini,Vertex/ADC)GT_GEMINI_PROJECT(+ 可选的 GT_GEMINI_LOCATION,默认为 us-central1)使用相同后端,但通过 gcloud auth application-default login 进行身份验证 — shell 中无需密钥。如果两者都已设置,则优先使用 API 密钥。
Ollama(本地)OLLAMA_HOST(默认为 http://127.0.0.1:11434)蒸馏/摘要/评估 LLM。完全离线。

Vertex/ADC 路径需要在项目中启用 aiplatform.googleapis.com API,且即使是“免费”的 Gemini 模型也需要付费 — AI Studio 免费层不适用于 Vertex。项目 ID 不属于机密;凭据本身存放在 ~/.config/gcloud/application_default_credentials.json,并由 gcloud 刷新。

嵌入器后端

嵌入器后端与 LLM 后端彼此独立。请选择一个:

  • 默认 — Ollama(nomic-embed-text,768 维,每个分块约 50 毫秒)。 需要运行中的 Ollama 守护进程。零成本,完全本地运行。
  • 替代方案 — sentence-transformers(uv add 'github-twin[st]', 会拉取 torch)。当无法使用 Ollama 守护进程,或你想使用特定的 HuggingFace 模型时很有用。本地运行。
  • 替代方案 — Gemini(默认使用 3072 维的 gemini-embedding-001)。 使用已安装的 google-genai 依赖;通过 GEMINI_API_KEY/GOOGLE_API_KEY 进行身份验证,或者通过 GT_GEMINI_PROJECT
    • ADC(gcloud auth application-default login)路由至 Vertex AI,无需管理密钥。远程 — 这是唯一会将分块文本发送到本机之外的嵌入器。如果你有 Gemini 身份验证,但没有 Ollama/[st] 安装,并且可以将语料库分享给 Google,请选择此方案。

嵌入器是每个数据库的一项固定选择 — sqlite-vec 会在首次创建时将向量维度写入表中。请在初始化时将选择写入 <data_dir>/config.toml,以便后续每条命令都能使用该设置:

gt init --embed-backend gemini                              # gemini-embedding-001, 3072
gt init --embed-backend gemini --embed-dim 1536            # request shorter output
gt init --embed-backend sentence_transformers \
        --embed-model BAAI/bge-small-en-v1.5 --embed-dim 384

使用相同的值重新运行不会产生任何变化;若对已有的 config.toml 使用不同的值运行,则会明确报错,而不会悄悄更改语料库。GT_EMBED__* 环境变量仍可用于单次覆盖和 CI。

“仅使用云端 LLM”的配置需要嵌入器进程(Ollama/[st]),或选择远程 Gemini 嵌入器。

GitHub 令牌所需权限范围

运行 gt init 时,GH 客户端需要以下权限:

  • repo — 访问私有仓库及其 PR 评论
  • user:email — 用于用户模式身份信息扫描的已验证电子邮件地址
  • read:org — 列出组织成员并发现组织的私有仓库

细粒度 PAT 和经典令牌均可使用。

检索

默认使用混合搜索:BM25(SQLite FTS5)和向量相似度并行运行,然后通过 Reciprocal Rank Fusion(k=60)融合结果。向量检索部分匹配语义意图;BM25 部分则能捕捉向量搜索经常漏掉的精确标识符(getUserById、SQLITE_OPEN_READWRITE)。设计参考:Anthropic — Contextual Retrieval。

嵌入时,每个分块前都会加上确定性标头:# path :: symbol_name (node_kind),以及函数开头的文档字符串/注释(如果有),和可选的 LLM 生成摘要(参见 gt summarize)。标头可让向量查询命中正文只包含标识符的分块(例如,针对 VaultSecretEq 函数的自然语言查询)。

默认启用 BM25 查询扩展(cfg.retrieval.query_expansion = "rule"),仅对 BM25 部分应用基于规则的代码形式同义词——嵌入本身已能捕捉同义关系,因此扩展不会影响向量查询。切换为 "ollama" 可在此基础上添加 LLM 生成的替代查询,并按词元缓存在磁盘上。

predict_review_outcome 仍使用纯向量检索,因为其反距离投票权重依赖经过校准的 L2 距离。

MCP 工具

所有检索工具均接受可选的 repo= 和 author_login= 筛选条件。

工具返回内容
find_review_comments(diff_hunk, language?, repo?, author_login?, k=5)与输入相似的差异中,过去的评审评论。
find_style_examples(query, language?, repo?, author_login?, k=5)与描述匹配的过往代码分块。
find_code(query, language?, repo?, path_glob?, node_kind?, k=5)HEAD 中文件的源代码片段(组织模式)。
find_applicable_rules(query, language?, repo?, author_login?, k=5)与编码任务相关的提炼代码模式规则。
predict_review_outcome(diff_or_summary, language?, repo?, author_login?, k=20)对最相近的过往 PR 进行加权预测:{approved, changes_requested, commented}。
summarize_review_patterns(language?, limit=20)从聚类后的评审评论中提炼规则(请先运行 gt distill)。
sync(since?)增量导入 + 摘要生成 + 嵌入。

命令行

gt init [--kind user|org|repo] [--org N] [--repo owner/name]
gt repos                                       # list discovered org repos
gt ingest                                      # backfill
gt summarize [--limit N] [--backend ...]       # LLM NL summaries per chunk
gt embed                                       # embed pending chunks
gt sync [--skip-summarize]                     # incremental: ingest → summarize → embed
gt stats                                       # corpus counts
gt distill [--backend ...] [--author ...]      # rule extraction
gt clones prune [--older-than-days N]          # GC the persistent clone cache
gt eval reviews     --since DATE [...]         # held-out RAG-vs-baseline eval
gt eval predictions --since DATE [...]
gt eval search evals/queries/default.yaml      # retrieval-quality dogfood
gt serve                                       # MCP stdio server

github-twin <command> 和 gt <command> 可以互换使用。

可插拔后端

接口环境变量/配置项默认值备选项
LLM(cfg.distill.backend、cfg.summarize.backend)ANTHROPIC_API_KEY/GEMINI_API_KEY(或 GT_GEMINI_PROJECT + ADC)/Ollamaauto(云端优先于本地)强制使用 claude/gemini/ollama
嵌入模型(cfg.embed.backend)—/GEMINI_API_KEY(或 GT_GEMINI_PROJECT + ADC)ollama(nomic-embed-text)通过 [st] extra 使用 sentence_transformers,或使用 gemini(gemini-embedding-001,远程)
向量存储(cfg.vector_store.backend)—sqlite-vec(暴力 KNN)通过 [faiss] extra 使用 faiss
BM25 查询扩展(cfg.retrieval.query_expansion)—rule(确定性)ollama(LLM,缓存)或 off

所有设置均按以下层级应用:默认值 → <data_dir>/config.toml(或显式指定的 --config PATH)→ 前缀为 GT_ 的环境变量(嵌套配置使用 __,例如 GT_EMBED__BACKEND=sentence_transformers)。

留出集评估

gt eval 使用相同提示词,分别在启用和不启用检索的情况下运行,并衡量 RAG 在真实留出数据上的准确率提升:

# Review-comment voice match (cosine distance to ground truth)
uvx github-twin eval reviews --since 2025-01-01 --limit 100

# Org-mode: scope to one reviewer (and optionally one repo)
uvx github-twin eval reviews     --since 2025-01-01 --author alice --repo http4s/http4s
uvx github-twin eval predictions --since 2025-01-01 --author alice

# Retrieval-quality dogfood (per-tier, per-backend pass rates)
uvx github-twin eval search evals/queries/default.yaml --mode all

评估框架会预先检查符合条件的数据量,因此拼错的 --author 或 --repo 会立即报错,不会浪费 LLM 调用。裁判嵌入模型默认与检索器使用不同模型(安装 [st] extra 后使用 sentence-transformers BGE-small),以避免测量检索器对自身输出的聚类效果。

可观测性(OpenTelemetry)

每次 MCP 工具调用、每次嵌入器调用以及每个检索阶段都会生成 Span,并通过 OTLP 导出。自动检测——除非配置了环境,否则不会触发任何操作。具体如下:

  1. 安装 [otel] 附加组件(包含 SDK 和 HTTP OTLP 导出器):

    uvx --with 'github-twin[otel]' github-twin serve
    
  2. 通过环境变量指定 OTLP HTTP 收集器:

    export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
    export OTEL_SERVICE_NAME=github-twin            # optional
    

即使设置了端点,OTEL_SDK_DISABLED=true 也会强制禁用它。

如果没有 [otel] 或没有端点环境变量,代码路径仍会运行,但每个 Span 都会由 opentelemetry-api 的内置追踪器免费空操作。即使启用了遥测,也绝不会使用 stdout——因为 MCP 使用 stdin/stdout 传输 JSON,意外的控制台导出器会破坏通信通道。OTLP HTTP 导出器会向你的收集器发送数据;SDK 警告则会通过 Python logging 路由到 stderr。

已接入 Claude Code:

{
  "mcpServers": {
    "github-twin": {
      "command": "uvx",
      "args": ["--with", "github-twin[otel]", "github-twin", "serve"],
      "env": {
        "GITHUB_TOKEN": "ghp_...",
        "GT_PATHS__DATA_DIR": "/path/to/twin-data",
        "OTEL_EXPORTER_OTLP_ENDPOINT": "http://localhost:4318",
        "OTEL_SERVICE_NAME": "github-twin"
      }
    }
  }
}

Span 名称和可用于筛选的关键属性:

Span有用的属性
mcp.tool.{find_review_comments,find_style_examples,find_code,find_applicable_rules,predict_review_outcome,summarize_review_patterns,sync}gh_twin.tool.k、gh_twin.filter.*、gh_twin.result.count(predict 时则为 .prediction/.confidence)
embedder.embedgh_twin.embed.input_chars、gh_twin.embed.model
retrieval.hybrid_searchgh_twin.retrieval.{chunk_kind,k,expander,hits,top_distance}
retrieval.vector_search(predict_review_outcome)属性结构相同,但没有 expander

收集器故障或无法访问时,每次刷新尝试都会输出一条 Failed to export span batch 日志,并且绝不会传播到工具处理程序——这一点由 tests/test_observability.py 保证。

gRPC 用户:除 [otel] 附加组件外,还需安装 opentelemetry-exporter-otlp-proto-grpc,SDK 会根据 OTEL_EXPORTER_OTLP_PROTOCOL=grpc 自动启用它。

存储

一个数据库可以容纳多个目标(用户 + N 个组织 + N 个仓库);若要隔离这些目标,请为每个数据库使用单独的 GT_PATHS__DATA_DIR。数据目录的解析不受环境影响:

  • 设置了 GT_PATHS__DATA_DIR 时使用该目录
  • 否则,如果设置了 XDG_DATA_HOME,则使用 $XDG_DATA_HOME/github-twin/
  • 否则使用 ~/.local/share/github-twin/

不会读取当前工作目录。

目录结构——每个数据库的所有内容都位于同一个根目录下:

<data_dir>/
  db.sqlite                  # artifacts + chunks + vectors + FTS5 index
  config.toml                # written by `gt init --embed-backend ...`
  raw/                       # on-disk cache of raw GitHub responses
  clones/                    # persistent shallow clones (if cache_clones=true)
  wiki/                      # `gt wiki export` default output
  auth/token.json            # OAuth file fallback
  query_expansion_cache.sqlite  # only when retrieval.query_expansion=ollama

如果你运行过会将 ./config.toml 或 ./data/ 写入当前工作目录的旧版本,那么每次调用 CLI 时都会记录一次性 WARN,并附上准确的 mv 命令用于迁移。

发布

版本通过 hatch-vcs 从 git 标签获取。 发布只需一条命令:

git tag v0.2.0    # PEP 440 forms: v0.2.0, v0.2.0a1, v0.2.0rc1, v0.2.0.post1
git push --tags

推送 v* 标签会触发 .github/workflows/release.yml,该工作流会:

  1. 在 Python 3.12 / 3.13 上运行 pytest + ruff + uv build。
  2. 通过 Trusted Publishing (OIDC) 将 wheel + sdist 发布到 PyPI。仓库机密中不会存储 PyPI 令牌——PyPI 会根据你在项目页面上注册的 Trusted Publisher,验证由 GitHub 签名的 OIDC 令牌(工作流文件名 release.yml,环境 pypi)。
  3. 创建带有自动生成说明(自上一个标签以来的 PR)的 GitHub Release,并附上 wheel + sdist。预发布标签(a/b/rc)会标记为预发布,因此不会取代“Latest”。
  4. 更新 main 上的 .claude-plugin/plugin.json,使其与标签版本一致——设置 version,并将 MCP 服务调用固定为 uvx [email protected] serve。市场会从 HEAD 获取清单,因此用户的市场缓存刷新后就会获得此版本。

每个仓库只需进行一次的首次设置:

  1. 将项目推送到 GitHub(任意账号 / 组织均可)。
  2. 在 PyPI 上注册 Trusted Publisher:
    • https://pypi.org/manage/account/publishing/
    • Owner:你的 GitHub 用户名 / 组织;Repository:github-twin; Workflow:release.yml;Environment:pypi。
    • (如果项目尚未在 PyPI 上创建,也可以使用“Pending Publisher”流程。)
  3. 在 GitHub 上:Settings → Environments → 新建环境 pypi。将自己添加为 Required Reviewer,以便在每次发布前增加审批步骤(可选,但建议)。

.github/workflows/ci.yml 会在每个 PR 以及推送到 main 时运行——发布工作流会在发布前重新运行相同的检查,因此有问题的 main 不会产生发布版本。

设计说明

  • 嵌入时前缀(embed.prefix.prefix_chunk):按类型生成的标头,会在嵌入时拼接到每个分块的文本之前,且不会写回 chunk.text。形状发生变化时会递增 EMBED_TEXT_VERSION,以便下一次 gt embed 重新生成向量。
  • AST 分块(process.chunkers):tree-sitter 遍历会按可声明单元生成分块;对于不支持的语言或解析失败的情况,则回退到按行窗口分块。
  • 非对称查询扩展 (store.query_expansion):仅应用于 BM25 部分,向量部分始终使用原始嵌入——由 test_hybrid_search.py 固定验证。

原始设计方案见 getting_started.md,其中包含完整的演练说明。

许可证

MIT — 详见 LICENSE。

mcp-name: io.github.ChristopherDavenport/github-twin

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。