glyphtrail/glyphtrail

GitHub: glyphtrail/glyphtrail

本地代码智能图构建与分析工具。

Stars: 2 | Forks: 0

# Glyphtrail

Glyphtrail

[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/) **本地代码智能图,适用于AI编码代理:Tree-sitter静态分析,结构化代码搜索,依赖影响,爆炸半径分析,CLI和MCP服务器。** Glyphtrail是**本地优先的代码智能**:它从您的仓库中构建**代码知识图**,以便AI编码代理(以及您)可以查询结构、追踪血缘关系,并发现跨时间重复出现的想法。[Tree-sitter](https://tree-sitter.github.io/) 基于的静态分析提取符号、调用、导入、继承、设计-理由注释和跨边界API链接到一个每个仓库的LadybugDB图。 在这张图上,它提供了**结构化代码搜索**、**调用图和依赖图**遍历,以及**爆炸半径/影响分析**:一个GraphRAG底层,用于通过**代码智能MCP服务器**或CLI访问的代码库。 用作Claude Code、Cursor、Windsurf和Codex的仓库索引。 原生Rust构建。 ## 安装 Linux、macOS(Intel + Apple Silicon)和Windows的预构建二进制文件附在每个[标记的版本](https://github.com/glyphtrail/glyphtrail/releases)中。 或者从源代码构建: ``` cargo install --git https://github.com/glyphtrail/glyphtrail glyphtrail-cli # or, from a checkout: cargo build --release # binary at target/release/glyphtrail ``` ## 使用 ``` # Index the current repository (writes .glyphtrail/ladybug) glyphtrail analyze . # Re-index only files that changed glyphtrail analyze . --update # Index a whole directory of repositories: discover every repo under the path # (descending into nested repos), analyze each, and register them all glyphtrail analyze ~/code --recursive # add --hidden to scan dot-dirs # Index a remote repository: clone into ~/.glyphtrail/remote/, # 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技术, 云安全监控, 代码分析, 代码库索引, 代码搜索, 代码智能, 代码智能代理, 代码知识库, 依赖分析, 凭证管理, 可视化界面, 开源, 影响分析, 数据管道, 本地化, 网络流量审计, 软件工程, 通知系统, 静态分析