glyphtrail/glyphtrail
GitHub: glyphtrail/glyphtrail
本地代码智能图构建与分析工具。
Stars: 2 | Forks: 0
# Glyphtrail
,
# index it there, and register it (shallow by default; --full for history)
glyphtrail analyze https://github.com/owner/repo
glyphtrail analyze git@github.com:owner/repo.git --full
glyphtrail remote list # cloned remotes + their local paths
glyphtrail remote remove # delete a clone (files + index) + unregister
# (glyphtrail remote remove --all clears them all)
# Outline the shape of a file or directory (symbols + signatures)
glyphtrail outline src/api.rs # standard detail
glyphtrail outline src --detail minimal # names only, whole directory
# Query the graph
glyphtrail query def # locate a definition
glyphtrail query callers # who calls it
glyphtrail query callees # what it calls
glyphtrail query neighbors # direct graph neighbours
glyphtrail query search # full-text search (names + doc comments)
glyphtrail query impact # transitive blast radius if it changes
glyphtrail query history # commits that touched the symbol across
# all branches, each flagged in HEAD or not — finds a fix parked on an
# unmerged branch ("where did that fix go?"); add --prs to map it to an open PR
# add --json (or --yaml, compact for agents) for machine-readable output
# Impact analysis (blast radius from a symbol, file, or change set)
glyphtrail impact # seed: a symbol
glyphtrail impact --file src/api.rs # seed: every symbol in a file
glyphtrail impact --since main..HEAD # seed: changed symbols vs a git range
glyphtrail impact --staged | --diff # seed: staged / working-tree changes
# reports a risk level (LOW/MEDIUM/HIGH/CRITICAL) and, for a large blast radius,
# a capped summary — add --details (full list) or --limit N
# [--cross-boundary] reach API consumers (HANDLES/INVOKES/EXPOSES/MOUNTS)
# [--edges calls,refs,imports,impl,api] [--depth N] [--min-confidence extracted|inferred]
# [--format text|json|md] [--gate] exit 2 when the change touches the API surface
# Visualize
glyphtrail viz --output graph.html # self-contained interactive page
glyphtrail serve --port 7700 # live explorer at http://127.0.0.1:7700
# Agent integration (Model Context Protocol)
glyphtrail mcp # MCP server over stdio (query/endpoints/impact/…)
# `glyphtrail serve` also exposes the same tools at POST /mcp (JSON-RPC)
glyphtrail setup --local # onboard agents in THIS repo: write
# .claude/skills + a managed CLAUDE.md/AGENTS.md section pointing them at the
# MCP/CLI, and gitignore the index. Idempotent and stats-free.
glyphtrail setup --user # same, but user-wide in your home dir
# (pick --local and/or --user explicitly — a repo-local install lands in commits)
glyphtrail setup --local --gitignore # keep it local-only: write the skill but
# gitignore it, skip the CLAUDE.md/AGENTS.md patch, and strip a section a prior
# run added (so nothing glyphtrail-related is committed).
# Generate a docs wiki from the graph via an LLM
glyphtrail wiki --provider claude # or openai / openrouter (reads *_API_KEY)
glyphtrail wiki --dry-run # write the prompts only (no network/keys)
# --base-url lets an OpenAI-compatible gateway (e.g. Kilo) stand in
# Stats (also reports index freshness: fresh / stale / unknown)
glyphtrail status
# read commands (query, impact, outline, drift, cypher) print a stderr note
# when the index looks stale (HEAD moved, uncommitted changes, or analyzer
# upgraded) so you know to re-run `glyphtrail analyze`
# Inspect/edit the per-repo config (glyphtrail.toml) without hand-editing
glyphtrail config show
glyphtrail config set security.record_sensitive_files true # validated before write
glyphtrail config get impact.test_globs
glyphtrail config unset impact.test_globs
```
### 将glyphtrail注册为MCP服务器
`glyphtrail mcp`通过stdio使用[模型上下文协议](https://modelcontextprotocol.io)
,向代理公开查询/影响/大纲/端点工具。
首先索引仓库(`glyphtrail analyze`),然后注册服务器。每个代理连接MCP服务器的方式不同:
**Claude Code**(CLI)——将其添加到系统:
```
claude mcp add -s user glyphtrail -- glyphtrail mcp
```
或者,如果您愿意,仅添加到特定仓库:
```
claude mcp add glyphtrail -- glyphtrail mcp --repo .
```
**Claude Desktop**——从[发布](https://github.com/glyphtrail/glyphtrail/releases)下载您平台上的`glyphtrail--.mcpb`包,并打开它(设置→扩展,或双击)。该包包含`glyphtrail`二进制文件;无需安装任何其他内容。由于桌面扩展是全局的,它**无需**固定仓库:代理在每次工具调用时命名目标`repo`(一个已注册的名称或路径),`list_repos`工具发现已索引的内容。要手动连接,请将以下内容添加到`claude_desktop_config.json`(传递`--repo`以固定一个仓库,或省略它以获得与包相同的仓库-per-调用行为):
```
{
"mcpServers": {
"glyphtrail": {
"command": "glyphtrail",
"args": ["mcp", "--repo", "/path/to/your/repo"]
}
}
}
```
**Cursor / Windsurf / VS Code / Codex**——将客户端指向相同的stdio命令。例如,项目范围的Cursor `.cursor/mcp.json`:
```
{
"mcpServers": {
"glyphtrail": {
"command": "glyphtrail",
"args": ["mcp", "--repo", "."]
}
}
}
```
**OpenCode / Kilo Code**——这些使用不同的形状和位置:在`type: "local"`服务器下,一个单独的`command`数组(程序+参数一起),分别在`~/.config/opencode/opencode.json`或`~/.config/kilo/kilo.jsonc`中:
```
{
"mcp": {
"glyphtrail": {
"type": "local",
"enabled": true,
"command": ["glyphtrail", "mcp", "--repo", "."]
}
}
}
```
确切的键、格式和配置位置因客户端而异(一些拆分`command`/`args`,一些接受一个数组;一些是项目范围的,一些是全局的)——但服务器始终相同:在stdio上运行`glyphtrail mcp --repo `。
省略`--repo`(与桌面包一样)并服务器不固定任何仓库:每个工具调用都必须命名一个`repo`,`list_repos`列出已索引的仓库。
(`glyphtrail serve`还通过HTTP在`POST /mcp`上公开相同的工具,供更喜欢URL的客户端使用。)
如果您希望它被管理,请使用`glyphtrail setup --local`(或`--user`以进行全局安装)编写代理技能以及一个`CLAUDE.md`/`AGENTS.md`部分,该部分将编码代理指向这些工具。
### 配置
所有每个仓库的设置都存储在一个文件中:仓库根目录下的`glyphtrail.toml`(已提交,团队共享),以及可选的`.glyphtrail/glyphtrail.toml`个人覆盖(gitignored)合并到上面——分析设置覆盖,`[[links]]`联合。每个字段都有一个默认值,因此文件仅用于更改一个。它包含:
- `[[api.schemas]]`——受祝福的API模式(OpenAPI / GraphQL SDL / protobuf / Hasura),用于将代码端点与之关联并解决`glyphtrail drift`。
- `[[languages]]`——在运行时加载的额外tree-sitter语法。
- `[impact] test_globs`——标记文件为影响报告中测试的glob。
- `[security] record_sensitive_files`——将敏感文件记录为无内容节点(见下文)而不是跳过它们。
- `[[links]]`——手动跨仓库链接提示(见[跨仓库爆炸半径](#cross-repo-blast-radius)),使用`glyphtrail repo link`编辑。
无需手动编写TOML即可编辑它;在写入之前,每个更改都会与模式进行验证,因此错误的键或类型会被拒绝,文件保持不变:
```
glyphtrail config show # current settings (or "defaults in effect")
glyphtrail config set security.record_sensitive_files true
glyphtrail config set impact.test_globs '["**/*_test.rs","tests/**"]'
glyphtrail config get impact.test_globs
glyphtrail config unset impact.test_globs
glyphtrail config set --local security.record_sensitive_files true # personal override
```
值被解析为TOML,因此`true`、`42`和`["a","b"]`保留其类型。(旧的拆分文件——`.glyphtrail/config.toml`、`glyphtrail.links.toml`、`.glyphtrail/links.toml`——仍然被读取,并在下一次`config`/`link`编辑时折叠到`glyphtrail.toml`中。)
### 排除敏感文件
`analyze`尊重`.gitignore`/`.git/info/exclude`,跳过点文件,并从`.glyphtrailignore`、`.aiignore`、`.aiexclude`和`.claudeignore`中读取排除列表。在列表中列出任何包含机密/密钥材料的文件,以将其完全排除在索引之外——因此也排除在所有代理面对的表面(wiki、MCP)之外。
在`~/.glyphtrailignore`的**用户范围**排除文件应用于您分析的每个仓库——在批量索引整个工作目录时很有用。它做两件事:
- **gitignore格式模式**(例如`*.generated.rs`)排除每个仓库的walk中匹配的文件;一个仓库的自己的忽略文件可以使用`!`重新包含。
- **绝对(或`~/…`)路径行**排除整个仓库/树——分析它,或其任何子文件夹,都不会做任何事情。在批量扫描工作目录时跳过几个大型仓库很有用。
### CI中的影响报告
从拉取请求的diff中播种影响分析,并发布Markdown摘要,可选地当更改触及公共API/模式表面(漂移门)时使作业失败:
```
# .github/workflows/impact.yml
name: impact
on: pull_request
jobs:
impact:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # need the base ref for the diff
- run: cargo install --path crates/glyphtrail-cli # or download a release binary
- run: glyphtrail analyze .
- name: Impact report
run: |
glyphtrail impact --since "origin/${{ github.base_ref }}...HEAD" \
--cross-boundary --format md >> "$GITHUB_STEP_SUMMARY"
# Optional: fail the job if the PR changes the API/contract surface.
- name: Drift gate
run: |
glyphtrail impact --since "origin/${{ github.base_ref }}...HEAD" \
--cross-boundary --gate
```
### 跨仓库爆炸半径
注册一次仓库,然后追踪更改的影响*跨*它们——当您更改其他本地索引仓库依赖的crate时(通过crates.io、git或路径依赖),`impact --downstream`报告哪些仓库会损坏以及在哪里,而不仅仅是您的自己的。
```
glyphtrail repo add . # register the current repo
glyphtrail repo scan ~/code # register already-indexed repos under a tree
glyphtrail repo scan ~/code --analyze # index each repo found, then register it
glyphtrail repo scan ~/code --all # register every repo, indexed or not
glyphtrail repo list # registered repos + health + forge ids
glyphtrail repo list --mine # only repos you've contributed to
glyphtrail group add svc api core # optional: a named subset to scope to
glyphtrail analyze . # index each repo as usual
# Blast radius extended into downstream repos that depend on this one:
glyphtrail impact MySymbol --downstream # federate over the registry
glyphtrail impact --since main..HEAD --group svc # scope to a group
glyphtrail impact MySymbol --downstream --deep # re-read identities from each
# member store (not the cached shortcut) and include indexed repos beside this
# one that were never `repo add`ed — for when the cache may be stale/incomplete
```
跨仓库链接通过包名(Cargo、npm、Go、Python、.NET)匹配:消费者的依赖与发布它的包的生成者仓库相关联。
MCP `impact`工具采用相同的`downstream`/`group`参数,`list_repos`列出注册表,因此代理在一次调用中就得到跨仓库爆炸半径。
**手动链接提示**。一些真实关系不能通过包名匹配——一个服务通过HTTP从另一个仓库调用,但没有共享包。将这些声明为`[[links]]`在`glyphtrail.toml`(已提交)和/或`.glyphtrail/glyphtrail.toml`(个人);两者都是联合的,并随着自动解决的链接一起输入到联邦影响中。`from`是消费者,`to`是生产者(更改`to`影响`from`);每边的`repo`默认为`.`(此仓库),因此您只需命名另一个即可。省略`symbol`以获得粗略的整个仓库链接。使用`glyphtrail repo link add/list/remove`(对同一文件的薄包装)编辑它们。
```
# in web-client's glyphtrail.toml: we call user-svc's endpoint (no shared package)
[[links]]
from = { symbol = "fetchUser" } # repo "." = here
to = { repo = "user-svc", symbol = "get_user" }
```
使用`glyphtrail repo link`无需手动编写TOML即可编辑提示:
```
glyphtrail repo link add user-svc --to-symbol get_user --from-symbol fetchUser
glyphtrail repo link add user-svc # coarse whole-repo link
glyphtrail repo link add user-svc --local # write the gitignored personal override
glyphtrail repo link list # show hints (shared + local) with indices
glyphtrail repo link remove 1 # drop a hint by index
```
#### 工作原理(许多本地数据库,一个注册表)
没有中央数据库。每个仓库都拥有其索引,位于`/.glyphtrail/ladybug`,由`analyze`独立构建。唯一共享的状态是用户范围的注册表,位于`~/.glyphtrail/registry.json`,它仅将仓库名称映射到其根(加上forge id和组)——它不包含图数据。
联邦查询(`impact --downstream`/`--group`,或MCP `impact`工具)在查询时将那些独立索引拼接在一起:
1. **选择成员**——整个注册表,或一个命名组。当前仓库(通过路径匹配到注册条目)始终包含在内。
2. **以只读方式打开每个成员的索引**并提取其持久化的*包标识*:它发布的包(及其公共导出)和其*外部使用*(引用已声明依赖的导入)。这两者都是在该仓库自己的`analyze`期间计算和存储的。
3. **通过将消费者的外部使用与引用其包名称(和导出符号)的生产者仓库匹配来解决跨仓库链接**。这产生了从生产者的导出到使用它的确切消费者符号的边(当无法确定符号时,回退到文件级,然后是crate级)。
4. **遍历**联合,其中那些跨仓库边连接每个仓库的图,并按仓库分组报告爆炸半径(起源首先,然后是下游)。
因为链接是从包元数据派生的,所以只有在被分析(因此其标识在磁盘上)并注册后,仓库才参与其中;没有与其他仓库识别出包/依赖关系关系的仓库简单地不贡献任何跨边。链接目前仅限于Cargo。
`repo scan`遍历版本控制根(`.git`/`.svn`/`.bzr`/`.hg`),跳过点目录(使用`--hidden`包括它们),并将每个仓库视为一个边界(使用`--recursive`也可以找到嵌套仓库/子模块)。子模块的代码永远不会作为其父模块的一部分被索引——分析在嵌套仓库边界处停止——因此它只出现在其自己的索引中。遍历和每个仓库的工作显示进度,这在慢速网络支持的驱动器上很重要。
### 仓库标识
每个已注册的仓库都获得从其git远程派生的稳定的**forge标识**,因此它在文件夹重命名、多个克隆和与发布crate的名称冲突中都被识别——以及一个仓库的镜像(例如,GitHub origin加上Codeberg镜像)都解析到同一个仓库。两种类型,在`repo add`中记录:
- **Slug**(始终,离线):每个远程的`host/owner/repo`→UUIDv5。
- **Numeric**(可选,重命名证明):forge的数字仓库ID通过其API,它在forge上的重命名中幸存。仅在提供令牌时解析,每个forge:
| Forge | Host | Token env var |
| --- | --- | --- |
| GitHub | `github.com` | `GITHUB_TOKEN`(否则回退到`gh` CLI) |
| GitLab | `gitlab.com` | `GITLAB_TOKEN` |
| Gitea / Forgejo | `codeberg.org` | `CODEBERG_TOKEN` |
数字ID完全是可选的:没有令牌(也没有`gh`),只有slug ID被记录。令牌从环境变量中读取,永远不会被记录。
`glyphtrail repo refresh [name]`从注册的仓库中重新推导出注册的ID,就地——当远程更改或要修复由旧版本写入的ID时很有用。
同一个仓库可以存在于多个路径中——一个符号链接、第二个克隆、备份副本。Glyphtrail为每个仓库保留**一个条目**:当您注册的路径与现有条目的forge ID共享时,它作为额外的位置折叠进来(在`repo list`中显示为`also at …`),而不是一个重复项,因此仓库不会被双重计数在联邦影响中。符号链接通过路径规范自动折叠。
每个仓库在注册时记录其顶级git作者,因此`repo list --mine`(或`--author `)将大型注册表缩小到您已工作的仓库,而无需扫描每个仓库的历史记录。
对于在非标准环境变量下的令牌,或工具无法通过主机识别的自托管Gitea/GitLab/Forgejo实例,可以在`~/.glyphtrail/forge.toml`中映射它们:
```
[hosts."codeberg.org"]
token_env = "CODEBERG_READ_ONLY_PAT" # use this var instead of CODEBERG_TOKEN
[hosts."git.example.com"]
kind = "gitea" # github | gitlab | gitea
token_env = "EXAMPLE_TOKEN"
```
### 并发写入和恢复
注册表(`~/.glyphtrail/registry.json`)和组文件在可移植锁文件(`registry.lock`)下更新,该文件在网络/FUSE/sync文件系统(例如pCloud)上工作,其中OS建议锁(`flock`)不可靠,可以在写入者死亡时留下*永久*锁。锁自我修复:在此主机上由已死亡进程持有的锁,或比几分钟旧,在下次运行时自动窃取,因此崩溃的`repo add`永远不会卡住注册表。
如果锁确实忙(另一个`repo add`正在进行写入),`repo add`**不会失败或阻塞**——它将条目写入注册表旁边的溢出文件(`registry.spill.*.json`),下一次运行锁的运行将合并它。溢出是原子性地编写的(临时+重命名),因此读者永远不会看到半写文件。这使得批量注册(同时索引许多仓库)即使在慢速或争用的驱动器上也是无损失的。
作为一个手动逃生孔,`glyphtrail repo unlock`强制释放锁。由于上面的自我修复,它很少需要,并且仅删除锁文件。
## 语言
覆盖率由tree-sitter语法注册表驱动。内置:
Rust、Python、JavaScript、TypeScript/TSX、Go、Java、C、C++、C#、Ruby、Kotlin、Bash、PHP、Scala、OCaml、Haskell、Lua、Swift、Elixir、Zig、R、Dart。添加内置语言是一个语法在`glyphtrail-parse/src/registry.rs`中,以及一个查询文件在`glyphtrail-parse/queries/`。
也可以在运行时加载额外的语言而不需要重新构建——将`glyphtrail.toml`指向一个tree-sitter语法和一个查询(语法按需编译;需要一个C工具链):
```
[[languages]]
name = "ruby"
extensions = ["rb"]
grammar = "grammars/tree-sitter-ruby/src" # dir with parser.c + grammar.json
query = "queries/ruby.scm" # @def./@call/@import/…
```
## 图模型
- **节点**:仓库、文件、模块、函数、方法、类/结构体/接口/枚举/特质,以及设计-理由注释(`NOTE`/`WHY`/`HACK`/`TODO`/`FIXME`)。
- **边**:`contains`、`calls`、`imports`、`extends`、`implements`、`documents`。每条边都标记为`extracted`(直接从AST中提取)或`inferred`(通过跨文件启发式解决)。
## 架构
一个Cargo工作空间:
| Crate | 责任 |
|-------|----------------|
| `glyphtrail-core` | 领域模型、语言检测、配置 |
| `glyphtrail-parse` | tree-sitter注册表、提取、图构建 |
| `glyphtrail-store` | LadybugDB(Cypher)存储和图查询 |
| `glyphtrail-viz` | Cytoscape图渲染(HTML/JSON) |
| `glyphtrail-server` | `axum`服务器,用于交互式探索器 |
| `glyphtrail-mcp` | 模型上下文协议服务器(stdio),公开查询工具 |
| `glyphtrail-cli` | `glyphtrail`二进制文件 |
存储位于`GraphStore`特质之后。**LadybugDB**(Cypher,本地图遍历)是存储后端;`.glyphtrail/ladybug`索引是真相的来源。
```
glyphtrail analyze . # writes .glyphtrail/ladybug
glyphtrail cypher "MATCH (n:Node) RETURN n.name LIMIT 10" # raw Cypher
```
LadybugDB链接到`lbug`crate,它下载预构建的`liblbug`或通过**cmake + C/C++工具链**(clang/gcc)从源代码构建——如果预构建存档不可用,请安装它们(例如`apt-get install cmake clang build-essential`)。
## 开发
### 先决条件
- Rust工具链:从[rustup.rs](https://rustup.rs/)安装
- [task](https://taskfile.dev/#/installation) - 任务运行器(`Taskfile.dist.yaml`)
- `prek` - 快速Rust-native预提交钩子运行器(`cargo install prek`)
### 设置
```
# Clone and build
git clone https://github.com/glyphtrail/glyphtrail
cd glyphtrail
cargo build --workspace
# Install pre-commit hooks (runs on every `git commit`)
prek install
```
### 检查
```
task fmt # format in place
task lint # clippy -D warnings
task test # full test suite
task ci # fmt:check + lint + test (mirrors CI)
# Run hooks manually against all files
prek run --all-files
```
CI矩阵针对`stable`和MSRV(`1.95`)运行。
## 许可证
[欧洲联盟公共许可证1.2](LICENSE-EUPL-1.2)
标签:CLI, MCP服务器, Rust, Tree-sitter, WebSocket, WiFi技术, 云安全监控, 代码分析, 代码库索引, 代码搜索, 代码智能, 代码智能代理, 代码知识库, 依赖分析, 凭证管理, 可视化界面, 开源, 影响分析, 数据管道, 本地化, 网络流量审计, 软件工程, 通知系统, 静态分析