Graphify 解决的是单仓结构查询

Graphify(Graphify-Labs/graphify)把仓库编成一张能查的代码图,让 Agent 少 grep、少读文件。2026 年这一拨工具不少,CodeGraph、GitNexus 也是同一路:本地 tree-sitter 抽出 class / method / import / call,再通过 CLI 或 MCP 交给模型。

FastAPI 那种单仓、源码都在、提交完再问「这个类谁在用」的仓库,这套有用。我日常改的是超大 Android 多仓、默认靠 AAR / Maven 分发的工程,对不上。Java、Kotlin 不是抽不出来,是图的工作方式和日常问题不是一类:

  1. 图抄的是语法树上的直接调用。EventBus、接口回调、匿名 onStart 这种运行时分发,抄不下来。
  2. 图只索引磁盘上已有的 .java / .kt,不索引 AAR / JAR。没打开的仓在图里是空白,而且不标明「这里缺源码」。
  3. 新鲜度默认跟本机 git commit / checkout,不是正在改的工作区,也不是 git push
  4. 建图范围由命令扫到的目录决定,不是由「这次需求涉及哪几个仓」决定。

过期或残缺的图比没有更糟,Agent 会当权威用。这类日常真正缺的是「源码在不在」和「现在这棵树、这一跳运行时对不对」。

Graphify 实际在做什么

产品是 Python 包 graphifyy(CLI 仍叫 graphify),Apache 2.0,YC S26。开源引擎在本地跑。app.graphify.com 是托管版,图会建到云上,未公开的代码不要用。

它分三层:

做什么大仓场景
Pass 1 代码本地 tree-sitter,不走 LLMJava / Kotlin 的 class、method、import、直接 call 能进图
Pass 2 音视频本地 whisper基本用不上
Pass 3 文档 / PDF / 图模型抽 INFERRED 边只有设计文档已经在仓库里的 md / pdf 才有价值

产物在 graphify-out/graph.htmlGRAPH_REPORT.mdgraph.json。边带 EXTRACTED / INFERRED / AMBIGUOUS。纯代码可以 --code-only 离线建图。

它不是 IDE 的 Find Usages,也不是 LSP。官方自己的分界是:LSP 做一跳;图做多跳「改这里会炸什么、A 怎么连到 B」。前提是那一跳得先被 Pass 1 抄下来。Android 超大仓里经常连一跳都不全,不是 MCP 没接好。

AST 抄得下什么,抄不下什么

源码对解析器是一堆文字。tree-sitter 先把它变成语法树,树上挂的是:这是一个类、这是一个方法、这一行在直接调用 foo.bar()。Graphify 建图,基本就是把树上能看见的「谁调用了谁」抄下来。

A 方法里写了 B.doWork()
→ 图上有一条边:A ──调用──► B.doWork

这叫静态、看得见的调用。问「谁调用了 doWork」,图可以给答案。这是 Graphify 的主场。

人追 bug 时问的通常是另一件事:点击、进度、生命周期进来之后,谁在什么时候真正执行。EventBus、接口回调、队列里的匿名 onStart,源码里就不是这种写法。

AST 能抄下直接调用,抄不下运行时分发

EventBus 和接口回调

常见写法:

发:EventBus.getDefault().post(StatusEvent)
收:@Subscribe fun onStatus(e: StatusEvent)

树上能看见的只有:有人调用了 post,有个方法叫 onStatus。没有「post 会跑到 onStatus」这条边。中间是运行时按事件类型去对的,AST 不跑程序,对不上。

所以不是「EventBus 三个字检索不到」,而是:

  • 发事件的那一行、收事件的那个方法,当普通函数,图里可能都在;
  • 「这个 post 会打到那个 subscribe」连不上;
  • 问谁发的、谁收的、中间怎么串,图给不出完整答案。

点击回调一样。图看见的是 setOnClickListener(注册)。真正执行是用户点下去之后系统回头调 listener,图里通常没有「点击 → 业务方法」。了解eventbus观察者模式 讲的就是这类机制:按类型或接口分发,不是写死调用。

匿名对象:图停在准备阶段

Android / Kotlin 里大量逻辑不写在具名 class 里:

queue.add(object : Task(startMs) {
    override fun onStart() {
        runEnterAnim()
    }
})

人读代码会说:入口是 queue.add,真正执行是后面某个时刻调到 onStart()。Graphify 早期 Kotlin 抽取器(issue #2347)抽出外层函数后不往函数体里走,object : Xxx { ... } 不当 class 处理,于是 onStart 和内部调用都不存在。changelog 后来补过成员抽取。节点在了,图仍然很难告诉你谁在什么时候触发 onStart。那是队列、进度、生命周期,不是源码里的直接 calls

具名 object 单例和这种匿名表达式不是一回事,见 Kotlin中的objectdeclaration、objectexpression、companionobject和顶层函数

枚举常量:类型在,状态值曾经不在

状态按钮这类代码问的是 DONE 时走哪段 UI,谁把状态写成 RUNNING。早期图只有枚举类型节点,没有 NONE / RUNNING / DONEissue #1700)。Java 半边在 0.9.10 补了定义节点,Kotlin enum_entry 随后也补了。有定义节点不等于能画出完整状态机。官方自己也说过,usage 边一开始不在范围内。

从入口到真正执行,经常停在这三层:XML / 生命周期触发、EventBus 或接口回调、匿名 override 与枚举分叉。Graphify 擅长的是中间那层具名 class 的 calls / imports。运行时那一跳看不见,图就会停在 queue.addTaskStatus 类型上。

图会装完整:它扫的是磁盘,不是需求

「装完整」不是「每次提问都把 20 个仓塞进模型」。建图和提问是两步:

  1. 建图:把某个目录树里的 .java / .kt 扫进 graph.json
  2. 提问:在这张已经建好的图上走几步,只把相关小块交给模型。

Graphify 不是多仓管理工具,不知道你开了哪些仓。对哪个目录跑 /graphify <路径>,它就扫那个目录下能看见的源码。AAR / JAR / .class 不进图。没打开、不在磁盘上的仓当不存在,也不会标「这里缺源码」。缺口是空白,不是「未索引」。Agent 会以为这个类没有调用方、没有实现,其实实现在没打开的 AAR 后面。

对一个超大多仓工程的日常开发维护来说:已打开源码大约 2 万级 Java+Kotlin 文件,另有大量 XML。日常默认态是聚合工程,大量模块仍是 Maven / AAR,磁盘上只有被切成本地源码的仓。调用链经常是:业务源码 → 接口在 AAR 里 → 实现又在另一个没打开的仓。

反编译 AAR 再喂给 Graphify 理论上能做,但不该当日常:R8 名对不上、没有注释、和当前二进制版本对不齐、体量爆炸。该做的还是反查模块 → 把 AAR 依赖切成本地源码 → 同步真正源码到磁盘。刚打开一个仓,图也不知道,除非再重建。

多仓下的开发问题

开了 20 个仓、需求只用 3 个,这种情况怎么办?

范围可以收,默认不会帮你只扫 3 个。

建图范围由命令目录决定,不是由这次需求决定
怎么跑进图的是什么
多仓工程根目录 /graphify .已经打开、磁盘上有的源码都会扫。开了 20 个就是 20 个
/graphify ./modules/xxx 只指那 3 个目录,或分别建再 merge可以只索引这 3 个
根目录 .graphifyignore 排除另外 17 个也能只留 3 个

graphify query 不会把 20 个仓全文塞进模型。但若图是按 20 个仓建的:建图成本按 20 个付;查询可能串到另外 17 个仓的同名类;那 17 个仓里过期或无关的边仍可能被当成相关。

Graphify 没有「当前任务只用这 3 个子仓」这种一等能力。要窄,得自己选路径或写 ignore。这 3 个仓若还调用第 4 个没打开的 AAR,图在这 3 个仓内部可以较完整,跨到 AAR 的那一跳仍然是断的,看起来像后面没了。

日常工作是某一个已打开的业务仓、一条链路,不是整个超大 App 仓的架构地图。官方 HTML 图大约 5k 节点就开始劝退。XML、skin、资源几乎不进图,而 Android 入口经常在 XML。没有适合「按已打开源码仓」的一等用法。

新鲜度跟 commit,不跟工作区

增量是 --update(按文件 hash),自动更新是本机的 post-commit / post-checkoutgit pull 之后还要自己跑一次 graphify update .git push 对开源引擎什么也不做。本地改了还没 commit、Agent 刚改完下一句就问、刚同步下来一个仓、刚把某个模块切成本地源码,图经常是旧的。

图默认也不是远端图数据库。开源引擎的产物是本机 graphify-out/graph.jsongraphify hook install 装的是这个 clone 的本地 git hook,在你自己的机器上后台重建,不打到一台共享服务器。100 人每人 /graphify 或 commit 一次,默认是 100 台电脑各自改自己的文件,不是 100 次请求去更新同一份库。

官方给团队的三条路:

怎么维护图在哪100 人会怎样
每人自己建各人磁盘上的 graphify-out/互不影响。别人的 commit 不会自动更新你的图,git pull 之后还要自己 graphify update .
graphify-out/ 提交进 git仓库里的文件,靠 pull 同步官方推荐的共享方式。hook 仍在各人机器上跑;并发改 graph.json 靠官方 merge driver 做并集合并。超大仓把这份生成物当公共文件提交,git 历史会很难看
托管版,或自己起一台 MCP云上,或某台 HTTP 服务app.graphify.com 连上仓库后,push 才触发云上重索引。未公开代码不要用。自建 python -m graphify.serve ... --transport http 也可以,但谁 rebuild、图对应哪次 revision,得自己定

没有「每个人敲一次命令,远端图库就更新一次」这种一等能力。要共享,要么提交 graph.json 当文件,要么自己养一台服务。

图找不到时,模型会不会自己再找

会,但有前提。Graphify 默认在劝 Agent 别再找。

情况模型还能不能补
源码在磁盘上,Agent 仍可用 rg / 读文件能。搜事件类名、@Subscribepost(,人怎么追它怎么追
按 Graphify 设计在用(先问图,少 grep)容易停在残缺图上,把「图里没边」当成「没有调用」
源码还在 AAR 里,本地根本没有图找不到,rg 也找不到,模型只能猜

Claude 上甚至有严格模式,第一次读源码会被拦住、改去查图。图越不完整,Agent 越可能自信地错。把 Graphify 当额外工具、仍允许搜文件,关键一跳还是靠原来的办法,只是多付了建图成本。

缺边时图不会报「未索引」或「运行时分发」。它就给出一张残图,Agent 很容易把这张图当成完整知识。

和 CodeGraph、GitNexus 的差别

三者都用 tree-sitter,都宣称省 token,赌注不同。换产品补不上运行时分发和源码不在磁盘这两处,能拉开差距的主要是新鲜度和许可。

GraphifyCodeGraphGitNexus
赌什么范围:代码加文档 / PDF / 图Agent 摩擦:一张活的代码图分析深度:impact / taint / DI
存储graph.jsonSQLite + FTS5LadybugDB
新鲜度git hook / --updateOS file watcher,保存即更新重索引 / detect_changes
JAR / AAR不索引字节码不索引字节码不索引字节码
许可Apache 2.0MITPolyForm Noncommercial

独立评测里有一句很准:过期的代码图比没有更糟。Graphify 默认跟本机 commit 走;CodeGraph 才是为「边改边问」设计的。对未提交改动,CodeGraph 强一档,但 watcher 也只覆盖已经在磁盘上的源文件。仓没打开、还是 AAR,换谁都没用。

GitNexus 更像程序分析,但非商用协议,上班写代码默认不能用,除非单独买商用授权。先排除。

公开数字也要打折。Graphify 的 71.5× token 来自 52 个文件的混合语料,不是 2 万级 Java / Kotlin 的 App 仓。LOCOMO / LongMemEval 是记忆检索榜,不是 Android 调用图质量。CodeGraph 在 OkHttp 上的数字更相关,那也只是单个开源库,不是几万文件的多仓 App 工程。

和现在常用办法比一下:

问题类型现在怎么做上图索引有没有增量
类在 AAR 里,本地没有源码把 AAR 切成本地源码无,图更会漏
单方法 / 单文件rg + 读文件负,多一层过期索引
从入口到触发的完整链路按执行顺序读,区分准备和执行弱,AST 看不到触发
改一个符号的影响面IDE Find Usages / rgCodeGraph 可能有用;Graphify 一般
模块 onboarding + 设计文档已在仓库人读 + 报告Graphify 这才对口
跨仓「谁依赖谁」多仓模块清单 / 依赖图图扫不全没打开的仓

Graphify 想省的是 Agent 少 grep。这边的成本在:源码在不在本地、入口在 XML / 回调里、跨仓跨 AAR、改的是未提交中间态。文档加代码一张图、神节点、社区划分,对写 onboarding 有用,对日常改代码几乎用不上。多数 Agent 也不是官方一等集成,还要自己接 skill / MCP。

什么时候才值得试

默认不需要。尤其不要对超大聚合工程全仓 /graphify .,不要用托管版,不要指望它替代「打开本地源码 → rg → 按执行链路读」,也不要同时装 Graphify + CodeGraph + GitNexus。

值得试的窄场景要同时满足:

  • 单个已经切成本地源码的业务仓,大约几百到两三千源文件;
  • 旁边有能进仓库的 md / 设计文档,不是只在需求平台 / 在线文档里;
  • 问题是「这块模块怎么拼起来的 / 文档和实现对不上」,不是「这个点击从 XML 到 runnable 怎么走」;
  • 接受 --code-only,不把 PDF / 视频塞进去。

以后如果真要上代码图:先把目标仓切成本地源码;只为 Agent 少 grep、看 blast radius,用 CodeGraph 扫那一个仓;文档和代码必须连在一起,再对那个仓 Graphify --code-only + 少量 md。验证也要窄:选一个已打开的业务模块,抽查 EventBus 订阅、layout → Activity、Hilt 注入这三跳在不在图里。这三跳缺了就停,不必再装进默认 MCP。

现在这套(打开本地源码 → rg → 按执行顺序读当前文件)不是落后替代,是更贴场景的办法。差的不是 grep,是图里根本没有那些边。


相关笔记