Skip to content

Commit bb4c2f5

Browse files
authored
Add 仓库透视 Repo X-Ray (repo-xray) (#30)
* Add 仓库透视 Repo X-Ray (repo-xray) Understand a codebase from its Git history: a code map you can drill into, hotspots and bug magnets, high-risk files, owners and knowledge loss, commit rhythm and firefighting, and the tech stack, for GitHub, GitLab, and local repositories. Analysis runs locally with the user's git: blob-less bare clones inside context.dataDir, network only to the repository hosts the user adds, tokens kept in the Node process, no Agent turns. * repo-xray: keep the welcome icon at a fixed size The welcome page put the icon in a .brand-mark <span> with no display value. Inside the sidebar's flex row that span is blockified, so its size applies; on the welcome page it stayed inline, its width was ignored, and the image's width: 100% filled the whole column (up to 880px). .brand-mark is now inline-block, and the welcome icon has a fixed 56px size in CSS instead of an inline style. Also shorten the input placeholder so it fits the right panel next to the sidebar (the focused input clipped the last characters), and add text-overflow: ellipsis for when the input is not focused. * repo-xray: address review: no redirects with a token, 0600 JSON, Host/Origin check - netEnv(): with a token attached, set http.followRedirects=false. The unscoped http.extraHeader went with every request, and after a redirect git kept talking to the new host, so a 302 to another host received the token on POST git-upload-pack. A redirect now fails with a message asking for the repository's new address. - writeJsonAtomic() creates files with mode 0600 (config.json holds pasted tokens); start() also tightens an existing config.json. - Every route answers 403 unless Host is a loopback name and Origin, when sent, is this listener (same check as cq-viewer). - git() drops inherited GIT_DIR and the rest of `git rev-parse --local-env-vars`, GIT_CONFIG_KEY_n/VALUE_n, and GIT_TRACE*. - parseTarget() validates the host with the Settings host rule for every form, so "git@github.com@evil.example:a/b" is rejected; gh tokens are only used for github.com and hosts in gh's hosts.yml. - readBlobs() checks sizes first and reads only blobs under 512KB. - Removing a repository waits for its running job to finish before deleting the clone and report. - README (en, zh-CN): Data & access updated to match. * repo-xray: kill git's whole process group on abort; bound the DELETE wait Aborting killed only the direct git child. git-remote-https shares its stdout/stderr pipes, so 'close' waited until the remote answered: with a remote that accepts the connection and never responds, DELETE (which now awaits the job) hung and the helper was left running, also after dispose(). - git() spawns git in its own process group on POSIX (detached) and the abort, timeout, and overflow paths kill the group (killTree); Windows keeps the plain kill. dispose() uses the same kill. - git() rejects at once when its signal is already aborted, so a job that resumes after an abort never starts another git command. - DELETE saves the config before waiting, and waits at most 5 s: the cap bounds the gh / glab / scutil lookups, which do not take the signal.
1 parent 1e37335 commit bb4c2f5

22 files changed

Lines changed: 11217 additions & 0 deletions

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ The MiniMax Code Agent communicates through the host MCP client. Business reques
7575
| [心屿 / Xinyu Island](plugins/yujiachen-y/xinyu-daily/) | A cozy daily-mood island that plays like an indie game: an inspiration card shaped by your answers, mood stickers, a joy jar, a decision slot machine, a Book of Answers, and 20 hidden secrets guarded by a grumpy crab. Optionally, Xiaoyu writes you a daily letter and chats with you using your model. Requires MiniMax Code 3.1.2 or later | [yujiachen-y](https://github.com/yujiachen-y) |
7676
| [MoMo Collab](plugins/amszuidas/momo-collab/) | A project steward that turns stray thoughts, screenshots, and links into ideas, writes clear ideas up as tasks, runs each task in its own Agent session with a full handoff, checks the result against your done criteria, and tracks everything on a board. Requires MiniMax Code 3.1.2 or later | [amszuidas](https://github.com/amszuidas) |
7777
| [Anatomy Gallery](plugins/zch0227/anatomy-gallery/) | A gallery for interactive isometric figures made with the anatomy skill: hang them in rooms you organize, view light and dark editions full screen, keep every version, and have an Agent create or edit figures from the gallery with a per-run process log. The anatomy skill is bundled. Requires MiniMax Code 3.1.2 or later | [zch0227](https://github.com/zch0227) |
78+
| [仓库透视 / Repo X-Ray](plugins/yujiachen-y/repo-xray/) | Understand a codebase from its Git history: a code map you can drill into, hotspots and bug magnets, high-risk files, owners and knowledge loss, commit rhythm and firefighting, and the tech stack. Works with GitHub, GitLab, and local repositories; analysis runs on your machine | [yujiachen-y](https://github.com/yujiachen-y) |
7879

7980
<details>
8081
<summary>Preview: Token Usage Board</summary>

‎README.zh-CN.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ MiniMax Code Agent 通过宿主 MCP 客户端与 MiniApp 协作。业务请求
7676
| [心屿](plugins/yujiachen-y/xinyu-daily/README.zh-CN.md) | 像独立小游戏的每日心情小岛:由你的回答决定的今日灵感卡、心情贴纸、小确幸罐子、纠结老虎机、答案之书,还有坏脾气螃蟹藏起来的 20 个秘密;可选开启小屿陪伴,借用你的模型每天写信、陪你聊天。需要 MiniMax Code 3.1.2 或更高版本 | [yujiachen-y](https://github.com/yujiachen-y) |
7777
| [协作 · MoMo](plugins/amszuidas/momo-collab/README.zh-CN.md) | 项目管家 MoMo:把随手的想法、截图和链接攒成想法,写清后变成任务,派 Agent 会话带着完整背景去执行,按验收标准核对结果后交你审核,进展在看板上一眼可见。需要 MiniMax Code 3.1.2 或更高版本 | [amszuidas](https://github.com/amszuidas) |
7878
| [Anatomy 画廊](plugins/zch0227/anatomy-gallery/README.zh-CN.md) | 集中展示 anatomy 技能做出的交互式等距图解:按自建展区挂墙,全屏查看明暗两版,保留全部历史版本;在画廊里让 Agent 新建或修改作品,每次运行都有过程记录。自带 anatomy 技能。需要 MiniMax Code 3.1.2 或更高版本 | [zch0227](https://github.com/zch0227) |
79+
| [仓库透视](plugins/yujiachen-y/repo-xray/README.zh-CN.md) | 从 Git 历史看懂一个代码仓库:可逐层下钻的代码地图、热点与 Bug 磁铁、高风险文件、负责人与知识流失、提交节奏与救火记录、技术栈;支持 GitHub、GitLab 和本机仓库,全部在本机分析 | [yujiachen-y](https://github.com/yujiachen-y) |
7980

8081
<details>
8182
<summary>预览:Token 用量看板</summary>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"schemaVersion": 1,
3+
"name": "repo-xray",
4+
"displayName": "仓库透视",
5+
"version": "1.0.0",
6+
"description": "从 Git 历史看懂一个代码仓库:代码地图、热点与 bug 磁铁、高风险文件、负责人与知识流失、提交节奏和技术栈。支持 GitHub / GitLab 仓库和本地仓库,全部在本机计算。",
7+
"author": "yujiachen-y",
8+
"icon": "icon.png",
9+
"category": "Code",
10+
"exampleQueries": ["打开仓库透视", "打开仓库透视,看看这个仓库的代码地图和高风险文件", "用仓库透视看看这个仓库主要是谁在维护"],
11+
"apps": [],
12+
"mcpServers": [],
13+
"skills": []
14+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 yujiachen-y
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# 仓库透视 Repo X-Ray (`repo-xray`)
2+
3+
English | [简体中文](README.zh-CN.md)
4+
5+
Understand an unfamiliar codebase from its Git history before you read any code. Add a GitHub or
6+
GitLab repository, or pick one on your machine, and Repo X-Ray turns the commit log into a code map
7+
you can drill into, a short list of high-risk files, who maintains what, how the team ships, and
8+
what the project is built with.
9+
10+
Analysis runs locally with your own `git`. Nothing is uploaded, and the page loads no remote
11+
resources. The metrics follow the rules of
12+
[codebase-recon-skill](https://github.com/yujiachen-y/codebase-recon-skill), and the Markdown export
13+
uses that skill's report format. The interface is in Chinese.
14+
15+
![Repo X-Ray code map with synthetic data](docs/preview.jpg)
16+
17+
*Preview uses synthetic data: a fictional monorepo generated for the screenshot.*
18+
19+
## What you can do
20+
21+
- **Overview**: key numbers, the main problems found by deterministic rules, recommendations, what
22+
changed since the previous analysis, and a small code map that links into the full one.
23+
- **Code map**: a treemap of the repository's directories that you can drill into. Colour it by
24+
change heat, bug-fix share, owner, last change, knowledge loss (the share of a directory's history
25+
written by people with no commits in the last 3 months), or file type. Size blocks by file count
26+
or by changes, and limit the window to 3, 6, or 12 months or all history. Works with the keyboard.
27+
- **High-risk files**: files that rank both as change hotspots and as bug magnets (most often
28+
touched by commits whose message mentions fix, bug, or broken), with their owners.
29+
- **Contributors**: ranking by non-merge commits, how concentrated the work is, who was active in
30+
the last 3 months, and bots and token accounts listed separately. Identities with the same name or
31+
email are merged by default; you can switch to one identity per author name.
32+
- **Rhythm and firefighting**: monthly commit trend, a commit calendar, and revert, hotfix,
33+
emergency, and rollback commits.
34+
- **Tech stack**: languages, frameworks, and tools detected from manifests such as `package.json`,
35+
`go.mod`, `Cargo.toml`, `pyproject.toml`, `pom.xml`, and `Gemfile`.
36+
- Search repositories, every file in history, and contributors with ⌘K. Copy or download the report
37+
as Markdown, or put a prepared prompt into the conversation input so the Agent reads the riskiest
38+
files for you; you review the text and send it yourself.
39+
- Suggestions of recently used local repositories, light and dark themes, keyboard shortcuts (press
40+
`?`), and `prefers-reduced-motion` support.
41+
42+
## Requirements
43+
44+
- `git` on `PATH`. Remote repositories need Git 2.31 or later, because credentials and the proxy are
45+
passed to git through `GIT_CONFIG_COUNT` environment variables.
46+
- Private repositories: if the `gh` (GitHub) or `glab` (GitLab) CLI is installed and logged in, the
47+
app reuses that login. Otherwise paste an access token for the host in Settings.
48+
49+
## Install
50+
51+
Copy this directory, including the hidden `.minimax-plugin/`, into the MiniMax Code plugins
52+
directory as `repo-xray/` (`~/.minimax/plugins/repo-xray/` by default; see the root README's Install
53+
section). Restart MiniMax Code, then open 仓库透视 from the Mini App entry in the right panel or ask
54+
the Agent to "打开仓库透视".
55+
56+
## Tested environment
57+
58+
- MiniMax Code 3.1.3-preview.4675 on macOS 27 with Git 2.54. Installed through the Host publish flow
59+
(also re-installed directly from this repository directory), opened in the right panel.
60+
- Exercised: a public GitHub repository, a self-hosted GitLab repository using the `glab` login, and
61+
local repositories, including re-analysis; every tab; every code-map colouring, size, and time
62+
option, drilling in and out with the mouse and the keyboard; the ⌘K search; the Markdown export;
63+
light and dark themes. No console errors or failed requests.
64+
- Not exercised: popping the page out into its own window (`surface.window`, sized 1360×900); the
65+
append into the conversation input, which asks the Host for confirmation; `prefers-reduced-motion`;
66+
Windows and Linux.
67+
68+
## Data & access
69+
70+
- Files read:
71+
- Repositories you add. A local repository is read in place with the read-only git commands
72+
below; the app only looks at the history of `HEAD`, never fetches, and never writes into it.
73+
- Local repository suggestions: lists directories under the scan roots (default `~/Workspace`,
74+
`~/workspace`, `~/code`, `~/Code`, `~/src`, `~/Projects`, `~/projects`, `~/Developer`, `~/dev`,
75+
`~/repos`, `~/GitHub`, `~/git`; up to 10 custom roots can be set in Settings), at most 4 levels
76+
deep, 4000 directories, and 300 repositories, skipping hidden directories and folders such as
77+
`node_modules`. For each directory it only checks for a `.git` entry and the modification times
78+
of `.git/FETCH_HEAD`, `.git/index`, and `.git/HEAD`.
79+
- The host names in `glab`'s config file (`$GLAB_CONFIG_DIR/config.yml`,
80+
`~/.config/glab-cli/config.yml`, or `~/Library/Application Support/glab-cli/config.yml`) and in
81+
`gh`'s `hosts.yml` (`$GH_CONFIG_DIR`, `$XDG_CONFIG_HOME/gh`, or `~/.config/gh`), to know which
82+
hosts these CLIs are logged in to. Tokens are not read from these files.
83+
- Whether `gh` and `glab` exist on `PATH`, `/opt/homebrew/bin`, `/usr/local/bin`, `/usr/bin`,
84+
`~/.local/bin`, or `~/.local/share/mise/shims`.
85+
- Files written, all inside the Host-provided `context.dataDir` (atomic write through a temporary
86+
file; JSON files are owner-only, mode `0600`):
87+
- `config.json`: the repository list and settings (scan roots, proxy, and any access tokens you
88+
paste in Settings, stored in plain text in this file).
89+
- `reports/<id>.json`: the analysis result for each repository.
90+
- `repos/<id>.git`: a bare, blob-less clone of each remote repository. It holds commits and trees,
91+
plus only the manifest and README-type files used for the tech stack and directory descriptions.
92+
- Removing a repository deletes its report and, for a remote repository, its clone. Local
93+
repositories are never modified.
94+
- Network: only `git` goes online, over HTTPS, to the host of each remote repository you add: clone
95+
and fetch, `ls-remote` to follow a renamed default branch, and fetching the few manifest and README
96+
files above. `git@host:path` and `ssh://` addresses are converted to HTTPS URLs; host names are
97+
validated first. If a proxy is set, git connects through it; the proxy comes from Settings, then
98+
`HTTPS_PROXY` / `https_proxy` / `HTTP_PROXY` / `http_proxy`, then the macOS system HTTPS proxy.
99+
The page loads only the app's own same-origin files and `/api/` routes. Links to repository pages
100+
on GitHub or GitLab open in your browser only when you click them. No telemetry.
101+
- Local server: it answers only requests whose `Host` is a loopback name and whose `Origin`, when
102+
sent, is the page itself; anything else gets `403`.
103+
- Processes, all started with an argument array and never through a shell. Addresses and paths you
104+
enter are validated and passed as separate arguments, never in an option position:
105+
- `git`: `clone --bare --filter=blob:none`, `fetch`, `ls-remote`, `log`, `ls-tree`, `cat-file`,
106+
`rev-parse`, `for-each-ref`, `symbolic-ref`, and `config` (reads `remote.origin.url` of a local
107+
repository to build web links; sets `remote.origin.fetch` and `HEAD` only inside the app's own
108+
clones). Inherited variables that would point git at another repository (`GIT_DIR` and the rest
109+
of `git rev-parse --local-env-vars`) or trace requests (`GIT_TRACE*`) are removed.
110+
- `gh auth token --hostname <host>` for `github.com` and hosts in `gh`'s `hosts.yml`, and
111+
`glab config get token --host <host>` for hosts in `glab`'s config, only when those CLIs are
112+
installed, to reuse your existing login.
113+
- `/usr/sbin/scutil --proxy` on macOS, only when no proxy is set in Settings or the environment.
114+
- Credentials: tokens from `gh`, `glab`, or Settings stay in the Node process. They reach git as an
115+
`http.extraHeader` through `GIT_CONFIG_*` environment variables, never in command-line arguments,
116+
repository config, the page, logs, or the event stream. While a token is attached, git does not
117+
follow HTTP redirects (`http.followRedirects=false`), so the token is only ever sent to the host
118+
you added; a repository that redirects (renamed or moved) has to be added again with its new
119+
address. Tokens from `gh` and `glab` are cached in memory only. Git credential helpers and
120+
interactive prompts are turned off for these commands.
121+
- Agent turns: none. No `agentAccess` and no MCP endpoints. "发到对话…", "让 Agent 讲解…", and
122+
"让 Agent 读高风险文件…" call `window.mcode.miniapp.message.append` to place a prepared prompt (a
123+
summary of the report and some file paths) in the conversation input after the Host asks you to
124+
confirm; you decide whether to send it. Where that API is unavailable, the text is copied to the
125+
clipboard instead.
126+
- Clipboard: written only when you click a copy action (a SHA, a path, the Markdown report).
127+
- Browser storage: `localStorage` keeps only the theme, the last opened repository, and the identity
128+
merge preference.
129+
- Reset: remove a repository with 移除 on its page; access tokens can be cleared in Settings. Deleting
130+
the app's data directory removes everything it stored.
131+
132+
## Files
133+
134+
```text
135+
.minimax-plugin/plugin.json Plugin manifest
136+
package.json Mini App declaration
137+
miniapp/miniapp.json Payload roots, Node entry, page route, pop-out window size
138+
miniapp/client/index.html Page shell served at /dashboard
139+
miniapp/client/app.js Page logic: routing, tabs, code map, dialogs (no dependencies)
140+
miniapp/client/charts.js Hand-written SVG charts and the treemap layout
141+
miniapp/client/styles.css Styles, light and dark themes
142+
miniapp/client/icon.svg App icon used inside the page
143+
miniapp/node/server.mjs Node entry: start(context) → { dispose }, routes, jobs, SSE
144+
miniapp/node/git.mjs git runner, address parsing, clone and fetch, credentials and proxy
145+
miniapp/node/analyze.mjs Reads the history and computes the report
146+
miniapp/node/codemap.mjs Code map: directory tree, colourings, directory descriptions
147+
miniapp/node/techstack.mjs Tech stack detection from manifests
148+
miniapp/node/util.mjs Date helpers, JSON read and atomic write
149+
miniapp/node/miniapp-api.ts Type declarations for the runtime context
150+
icon.png Plugin icon
151+
docs/preview.jpg README preview (synthetic data)
152+
```
153+
154+
## License
155+
156+
[MIT](./LICENSE)

0 commit comments

Comments
 (0)