
github-twin
io.github.ChristopherDavenport由 GitHub 帳號 ChristopherDavenport 發布v0.0.17更新於 Oct 24, 2026
Personal RAG over your GitHub history (commits, code, reviews), served to Claude Code over MCP.
概覽
將你的 GitHub 提交、程式碼與審查評論索引到本機 RAG 儲存,並向 MCP 用戶端提供檢索工具。
- 可以做什麼
- github-twin 將你的 GitHub 歷史記錄匯入本機 SQLite 索引,並透過 stdio 提供給 Claude Code 或任何 MCP 用戶端(R14)。工具包括 find_review_comments、find_style_examples、find_code、find_applicable_rules、predict_review_outcome、summarize_review_patterns 與 sync(R99、R100、R101、R102、R103、R104、R105)。檢索採 BM25 與向量混合並以倒數排名融合,對多種語言進行 AST 感知分塊(R87、R169)。支援索引個人歷史的使用者模式與索引整個組織的組織模式(R16、R18)。
- 適用情境
- 當助理撰寫或審查程式碼、而你希望它參考你過去的提交、程式碼風格與審查意見時使用(R4、R5、R6)。適合個人或組織層級的程式碼庫,讓過去的審查決定與慣例影響新工作(R17、R18)。如果只需要即時 GitHub API 存取而非本機檢索索引,則無需安裝。
- 執行需求
- 以本機 stdio 程序執行,透過 uvx github-twin serve 啟動(R7、R32),需要 Python 與 uv/uvx。需要 GitHub 權杖,可透過 OAuth 裝置流程、gh CLI 或 GITHUB_TOKEN 環境變數提供(R25、R26、R28、R29)。需要嵌入後端:預設使用執行中的 Ollama 守護程序,或安裝 sentence-transformers 附加元件(R65、R66、R68)。選用 ANTHROPIC_API_KEY、GEMINI_API_KEY 或 GT_GEMINI_PROJECT 啟用託管 LLM 後端(R52、R54、R56)。GT_PATHS__DATA_DIR 指定資料目錄(R140)。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 github-twin,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
github-twin
[PyPI version] [Python versions] [CI] [License: MIT]
You reviewed a permission check six months ago. Claude doesn't remember it. github-twin does — it indexes your commits and review comments, and surfaces them as retrieval hits whenever an agent writes or reviews new code in your style.
[gt stats + gt eval search returning hits against a real corpus]
[Claude Code citing a past review comment via the find_review_comments tool]
Try it now from Claude Code — drop this into ~/.claude.json and reload:
Your code stays on your box. Embeddings are computed locally (Ollama or sentence-transformers); only the LLM seam (
gt summarize,gt distill,gt eval) optionally calls a hosted provider, and even that's swappable to local Ollama. Thegeminiembedder is the one exception — opt-in only.
A personal RAG over your GitHub history, served to Claude Code (or any MCP client) as a stdio server. Two scopes, one codebase:
- User mode — index your own commits + review comments. Surfaces your past code as style examples and your past comments as review hints when an agent is writing or reviewing new code.
- Org mode — index a whole GitHub org's files-at-HEAD, commits, and PR reviews across every member. Queries scope by repo, language, or reviewer login.
Retrieval is hybrid (BM25 + vector via RRF), AST-aware via tree-sitter for python/scala/javascript/typescript/go/rust, and contextually enriched at embed time with per-chunk headers + optional LLM-generated summaries.
Install
The fastest path is uvx — no virtualenv to manage, isolated per-tool:
If you prefer a project-local install:
gt and github-twin are the same Typer app — use whichever fits your
muscle memory.
Authenticate
Pick whichever is least friction — github-twin tries them in this order:
- OAuth device flow (no
ghinstall needed): Token persists in the OS keyring (macOS Keychain / Linux Secret Service / Windows Credential Manager) or, when unavailable, a 0600 file under your data dir. - Existing
ghCLI: if you've already rungh auth login,gtpicks up the token viagh auth token— nothing to do. GITHUB_TOKENenv var: a classic PAT works too; useful for CI / headless / docker. Required scopes:repo,read:org,user:email.
Wire into Claude Code
The MCP server runs over stdio via github-twin serve (or gt serve).
Run uvx github-twin auth login once on the box that will host the
server.
Option A — via the Claude Code plugin marketplace (lowest-friction):
This registers the MCP server entry automatically; set
GT_PATHS__DATA_DIR in your environment (or in ~/.claude.json's
env block for this server) to point at the DB directory.
Option B — manual wiring: add an entry to ~/.claude.json (or
your mcp_servers.json):
If you'd rather not persist a token and instead supply it inline (CI,
ephemeral container), add "GITHUB_TOKEN": "ghp_..." to that env
block; it acts as the lowest-priority fallback.
Restart Claude Code; the find_*, predict_review_outcome,
summarize_review_patterns, and sync tools will be available.
Quickstart
Pick a directory to hold the SQLite DB, config, and ingested cache — everything per-data-dir lives under this one root:
gt sync is incremental on subsequent runs.
config.toml lives next to the DB at <data_dir>/config.toml and is
created on the first gt init --embed-backend ... call. Default
<data_dir> is $XDG_DATA_HOME/github-twin (or ~/.local/share/github-twin)
when GT_PATHS__DATA_DIR is unset.
LLM provider matrix
The retrieval surface (find_*, predict_review_outcome) always runs locally on the SQLite index — no API call. LLM calls only happen in three places:
gt distill— clusters review comments / commits into rules.gt summarize— generates per-chunk NL summaries used by the embed-time prefix.gt eval reviews/eval predictions— held-out RAG-vs-baseline scoring.
Each picks a backend by precedence Claude → Gemini → Ollama (whichever API key is set), or you can force one explicitly.
The Vertex / ADC path needs the aiplatform.googleapis.com API enabled
on your project, and billing applies even for "free" Gemini models —
the AI Studio free tier does not extend to Vertex. Project IDs are not
secrets; the credential itself lives at
~/.config/gcloud/application_default_credentials.json and is refreshed
by gcloud.
Embedder backends
We keep the embedder backend separate from the LLM backend. Choose one:
- Default — Ollama (
nomic-embed-text, 768-dim, ~50ms/chunk). Requires a running Ollama daemon. Zero cost, fully local. - Alternative — sentence-transformers (
uv add 'github-twin[st]', pullstorch). Useful when an Ollama daemon isn't available or you want a specific HuggingFace model. Local. - Alternative — Gemini (
gemini-embedding-001at 3072-dim by default). Uses thegoogle-genaidep that's already installed; auth viaGEMINI_API_KEY/GOOGLE_API_KEY, or viaGT_GEMINI_PROJECT- ADC (
gcloud auth application-default login) to route through Vertex AI without managing a key. Remote — this is the only embedder that sends chunk text off-box. Pick it when you have Gemini auth but no Ollama /[st]install, and your corpus is okay to share with Google.
- ADC (
The embedder is a per-DB commitment — sqlite-vec bakes the vector
dimension into the table at first creation. Stamp the choice into
<data_dir>/config.toml at init time so every subsequent command
picks it up:
Re-running with the same values is a no-op; running with different
values against an existing config.toml fails loud rather than
silently changing the corpus. GT_EMBED__* env vars still work for
one-off overrides and CI.
A "cloud-LLM only" setup either needs an embedder process (Ollama /
[st]) or has to opt into the remote Gemini embedder.
Required GitHub token scopes
When you gt init, the GH client needs:
repo— private repos and PR comments on themuser:email— verified email addresses for the user-mode identity sweepread:org— org member listing and private org repo discovery
A fine-grained PAT works; classic tokens too.
Retrieval
Hybrid search by default: BM25 (SQLite FTS5) and vector similarity run in
parallel, then fuse via Reciprocal Rank Fusion (k=60). The vector leg
matches semantic intent; the BM25 leg catches exact identifiers
(getUserById, SQLITE_OPEN_READWRITE) that vector search routinely
misses. Design reference: Anthropic — Contextual
Retrieval.
At embed time, each chunk gets a deterministic header prepended:
# path :: symbol_name (node_kind), plus the function's leading
docstring/comment when present, plus an optional LLM-generated summary
(see gt summarize). The header lets vector queries land on chunks
whose bodies only contain identifiers (e.g. natural-language queries
against a VaultSecretEq function).
BM25 query expansion is on by default (cfg.retrieval.query_expansion = "rule"), with rule-based code-shaped synonyms applied only to the
BM25 leg — embeddings already capture synonymy, so expansion never
touches the vector query. Switch to "ollama" to add LLM-generated
alternates on top, cached on disk per-token.
predict_review_outcome stays on pure vector retrieval because its
inverse-distance vote weighting depends on calibrated L2 distance.
MCP tools
All retrieval tools accept optional repo= and author_login= filters.
CLI
Use github-twin <command> interchangeably with gt <command>.
Pluggable backends
All settings are layered: defaults → <data_dir>/config.toml (or the
explicit --config PATH) → env vars prefixed GT_ (nested via __,
e.g. GT_EMBED__BACKEND=sentence_transformers).
Held-out evaluation
gt eval runs the same prompt with and without retrieval and measures
RAG's accuracy lift on real held-out data:
The harness pre-flights eligibility counts so typo'd --author or
--repo fail fast without burning LLM calls. The judge embedder
defaults to a different model than the retriever
(sentence-transformers BGE-small with the [st] extra installed) to
avoid measuring how well retrieval clusters its own outputs.
Observability (OpenTelemetry)
Spans for every MCP tool call, every embedder call, and every retrieval leg, exported via OTLP. Auto-detected — nothing fires unless the environment is configured. Specifically:
-
Install the
[otel]extra (carries the SDK + HTTP OTLP exporter): -
Point at an OTLP HTTP collector via env vars:
OTEL_SDK_DISABLED=true forces it off even when an endpoint is set.
Without [otel] or without an endpoint env var, the code paths
still run but every span is a free no-op from opentelemetry-api's
built-in tracer. stdout is never used — even with telemetry on —
because MCP speaks JSON over stdin/stdout and a stray console exporter
would corrupt the channel. The OTLP HTTP exporter posts to your
collector; SDK warnings route through Python logging (stderr).
Wired into Claude Code:
Span names + key attributes you can pivot on:
A broken or unreachable collector emits a single Failed to export span batch log line per flush attempt and never propagates into the
tool handler — pinned by tests/test_observability.py.
gRPC users: install opentelemetry-exporter-otlp-proto-grpc alongside
the [otel] extra and the SDK picks it up automatically based on
OTEL_EXPORTER_OTLP_PROTOCOL=grpc.
Storage
One DB can hold many targets (user + N orgs + N repos); use a separate
GT_PATHS__DATA_DIR per DB when you want them isolated. The resolved
data dir is pure with respect to env:
GT_PATHS__DATA_DIRwhen set- else
$XDG_DATA_HOME/github-twin/whenXDG_DATA_HOMEis set - else
~/.local/share/github-twin/
The current working directory is never consulted.
Layout — everything per-DB lives under one root:
If you ran an older release that wrote ./config.toml or ./data/ into
the current working directory, every CLI invocation logs a one-time WARN
with the exact mv command to migrate.
Releasing
Versions come from git tags via hatch-vcs. Cutting a release is one command:
The push to a v* tag triggers .github/workflows/release.yml, which:
- Runs pytest + ruff +
uv buildacross Python 3.12 / 3.13. - Publishes the wheel + sdist to PyPI via Trusted Publishing
(OIDC). No PyPI token
is stored in repo secrets — PyPI verifies the GitHub-signed OIDC
token against the Trusted Publisher you register on the project
page (workflow filename
release.yml, environmentpypi). - Creates a GitHub Release with auto-generated notes (PRs since the
previous tag) and attaches the wheel + sdist. Pre-release tags
(
a/b/rc) are flagged so they don't replace "Latest". - Bumps
.claude-plugin/plugin.jsononmainto match the tag — setsversionand pins the MCP server invocation touvx [email protected] serve. The marketplace fetches the manifest from HEAD, so this is what users get when their marketplace cache refreshes.
First-time setup, once per repo:
- Push the project to GitHub (any account / org).
- Register the Trusted Publisher on PyPI:
- https://pypi.org/manage/account/publishing/
- Owner: your GitHub user/org, Repository:
github-twin, Workflow:release.yml, Environment:pypi. - (Or use the "Pending Publisher" flow if the project doesn't exist on PyPI yet.)
- On GitHub: Settings → Environments → New environment
pypi. Add yourself as a Required Reviewer for an extra approval step before each publish (optional but recommended).
.github/workflows/ci.yml runs on every PR and push to main — the
release workflow re-runs the same checks before publishing, so a
broken main never produces a release.
Design notes
- Embed-time prefix (
embed.prefix.prefix_chunk): per-kind header spliced before each chunk's text at embed time, never written back tochunk.text. BumpsEMBED_TEXT_VERSIONwhenever the shape changes so the nextgt embedre-derives vectors. - AST chunking (
process.chunkers): tree-sitter walks emit chunks per declarable unit; falls back to line-window for unsupported languages or parse failures. - Asymmetric query expansion
(
store.query_expansion): BM25 leg only, vector leg always sees the raw embedding — pinned bytest_hybrid_search.py.
The original design plan lives in
getting_started.md along with the full
walkthrough.
License
MIT — see LICENSE.
mcp-name: io.github.ChristopherDavenport/github-twin
來源:README.md,提交 a078be8
工具
0版本歷史
1- v0.0.17最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分