graphify × Gemini CLI:让 AI 助手优先查询代码知识图谱的 always-on 指令层设计与实践
graphify 会把任意代码库连同其文档、SQL schema、配置文件一起解析为本地确定性 AST 知识图谱。本文以 gemini-md.md 这个 Gemini CLI 专用常驻指令块为主体,逐条拆解它写入项目 GEMINI.md 的四条"图谱优先"工作规则,并结合 install.py 的安装器源码与 test_gemini_hook.py 的测试,说明这套指令如何通过 graphify install --platform gemini 落地、又被 BeforeTool hook 如何实时"提醒"AI 走图谱路径,读完后你可以完整复现 Gemini CLI + graphify 的接入与日常使用闭环。
一、它是什么:写在 GEMINI.md 里的常驻规则块
gemini-md.md 只有短短十行,但它是 graphify 为 Gemini CLI 定制的"always-on"指令块——一段会在每次会话中被 Gemini CLI 读取、并长期生效的行为约束。原文完整内容如下:
## graphify
This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships.
Rules:
- For codebase questions, first run `graphify query "<question>"` when graphify-out/graph.json exists. Use `graphify path "<A>" "<B>"` for relationships and `graphify explain "<concept>"` for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output.
- If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing.
- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context.
- After modifying code, run `graphify update .` to keep the graph current (AST-only, no API cost).
它的定位非常清晰:声明事实 + 四条规则。开头一句向 AI 声明"本项目在 graphify-out/ 目录下已有一份包含 god nodes(枢纽节点)、community structure(社区结构)与跨文件关系的知识图谱";随后四条规则规定了 AI 回答代码库问题时的信息检索次序——先查图谱、再查 wiki 导航、最后才读完整报告,改完代码还要刷新图谱。这四条规则构成了整篇文章的展开主线。
二、四条规则逐条解读
规则 1:代码问题先查图谱——query / path / explain 三级查询
这是四条规则中信息量最大的一条,它给了 Gemini 三个分层工具:
| 命令 | 用途 | CLI 完整用法(摘自 cli.py 的 Usage 提示) |
|---|---|---|
graphify query "<question>" |
面向自然语言问题的范围化子图检索 | graphify query "<question>" [--dfs] [--context C] [--budget N] [--graph path] |
graphify path "<A>" "<B>" |
查询两个节点之间的关系路径 | graphify path "<source>" "<target>" [--graph path] |
graphify explain "<node>" |
聚焦解释某个概念/节点 | graphify explain "<node>" [--graph path] |
规则原文强调的前提是 graphify-out/graph.json exists——即只有当图谱确实构建过,才走查询路径,避免空图查询。三条命令返回的都是"scoped subgraph"(范围化子图),指令块明确指出其体积"通常远小于 GRAPH_REPORT.md 或裸 grep 的输出"。这正是 graphify 的核心卖点:用一份小得多的上下文回答代码库问题,而不是让模型去读整个报告或大海捞针式地 grep。
从源码结构看,query 在 cli.py 中被实现为基于 graphify.serve._query_graph_text 的图上检索,并保持图无向以支持 BFS/DFS 探索;path 与 explain 则强制使用有向视图。三种查询执行后都会调用 querylog.log_query 记录查询日志,并写入查询时间戳,为 hook 的"近期是否查过图"判断提供依据。
规则 2:用 wiki 做宽泛导航
第二条规则要求:如果 graphify-out/wiki/index.md 存在,就用它做宽泛导航,而不是直接翻原始源码。graphify 构建图谱时会同步产出一个 markdown 形式的 wiki 索引(见 wiki.py),相当于给整个代码库生成了一份"目录页"。这条规则的意义在于把"浏览"这一动作从逐文件打开,升级为沿 wiki 层级跳转,既省上下文窗口,也避免模型在目录树里迷路。
规则 3:GRAPH_REPORT.md 只作最后兜底
第三条规则刻意"降权"了 graphify-out/GRAPH_REPORT.md:它只应在两种场景被读取——做全局架构评审时,或者 query / path / explain 三者都没有给出足够上下文时。仓库内 worked/httpx/GRAPH_REPORT.md 这类报告可以看到其形态:整库级的社区划分与枢纽节点综述,信息密度高但体积大,适合作为"地图总览"而非"问题答案"。指令块把阅读次序硬编码为:子图查询 → wiki 导航 → 完整报告,本质是一份针对 AI 的渐进式信息披露(progressive disclosure)策略。
规则 4:改完代码必须 graphify update .
最后一条规则规定了图谱保鲜义务:修改代码之后运行 graphify update .。括号里的 "(AST-only, no API cost)" 点明了它的成本模型——增量更新只走本地确定性 AST 解析,不产生任何 LLM API 费用。这与 graphify"本地解析、每条边可解释、不依赖向量库"的整体设计一致:图谱可以低成本地随代码演进,而不需要重新花钱全量重建。
三、指令块如何进入 GEMINI.md:installer 源码级走读
gemini-md.md 只是"包内的源文件",真正把它变成项目规则的是 install.py 中的 gemini_install(第 707 行起)。执行 graphify install --platform gemini 时会发生三件事:
- 拷贝技能文件:
_copy_skill_file("gemini", ...)把包内skill.md原样拷入~/.gemini/skills/graphify/SKILL.md(项目级安装则是.gemini/skills/graphify/SKILL.md),并附带references/渐进式文档与.graphify_version版本戳; - 写入 GEMINI.md 规则段:以
## graphify作为 section 标记,通过_replace_or_append_section将 gemini-md.md 的内容幂等地写入或替换到项目根目录的GEMINI.md(见 install.py)。"替换"是关键:旧版本安装留下的过时措辞会在升级时被整段覆盖,用户无需卸载重装; - 注册 BeforeTool hook:向
.gemini/settings.json的hooks.BeforeTool数组追加一条钩子(见 install.py)。
其中 section 替换函数 _replace_or_append_section 有一个值得注意的健壮性设计:它只在某一行精确等于 ## graphify(去除首尾空白后)时才算命中,绝不做子串匹配;section 范围延伸到下一个 H2 标题之前。注释里说明这是为了避免历史上"子串误匹配删掉用户手写内容"的缺陷——对用户自维护的 GEMINI.md 来说,精确边界是安全底线。卸载时 gemini_uninstall 用同样精确匹配的 _remove_marker_section 反向清理,若清完后文件为空则直接删除 GEMINI.md。
四、BeforeTool hook:规则 1 的运行时"第二保险"
GEMINI.md 里的规则是"软约束"(依赖模型自觉遵守),graphify 还配了一条"硬提醒"。_gemini_hook(install.py)生成的钩子形如:
{
"matcher": "read_file|list_directory",
"hooks": [{ "type": "command", "command": "<graphify 可执行路径> hook-guard gemini" }]
}
即:每当 Gemini CLI 调用 read_file 或 list_directory 工具前,都会先执行 graphify hook-guard gemini。它的行为由 tests/test_gemini_hook.py 完整固化:
- 永不拦截:无论图谱是否存在,返回的 JSON 恒为
{"decision": "allow"},工具调用不会被 hook 阻断; - 有图谱就提醒:当前目录存在
graphify-out/graph.json时,在additionalContext中追加"先用graphify query"的引导文本(测试test_allows_and_nudges_with_graph断言该文本包含graphify query); - 无图谱则静默:没有图谱时不附加任何上下文,避免噪音;
- 尊重输出目录覆盖:
GRAPHIFY_OUT环境变量生效(测试test_honors_graphify_out_override)。
这个设计与 paths.py 相呼应:输出目录名默认是 graphify-out,但可通过 GRAPHIFY_OUT 环境变量改为任意相对名或绝对路径(适用于 worktree 或共享输出场景),hook 与 CLI 读取的是同一个单一事实来源。项目级安装时,由于 .gemini/settings.json 会被提交进版本库,钩子命令刻意使用裸 graphify 命令而非某台机器的绝对路径,保证换机器后依然可用。
五、这个文件从何而来:skillgen 单一事实源与防漂移
gemini-md.md 并不是手写的散落副本,而是由 tools/skillgen 从人类维护的单一 fragment tools/skillgen/fragments/always-on/gemini-md.md 生成的六个 always-on 块之一(同族还有 claude-md、agents-md、antigravity-rules、kiro-steering、vscode-instructions)。install.py 的 _always_on 函数文档字符串写得很直白:安装包内的六个块必须与 fragment 逐字节一致,由 skillgen --check 的 roundtrip 校验守护漂移。这也解释了为什么 graphify install 能"幂等升级"——只要 fragment 更新,一次重新安装即可让所有项目的 GEMINI.md 段同步到最新措辞。
六、落地清单与自定义
在任意项目根目录,完整接入流程为:
- 安装 Gemini 平台技能(用户级,技能落在
~/.gemini/skills/graphify/):graphify install --platform gemini; - 使用项目级安装(规则、
.gemini/settings.json钩子与.gemini/skills/graphify/SKILL.md全部落在项目内并可提交版本库):graphify install --project --platform gemini,安装器会自动提示git add对应路径; - 首次构建图谱后,项目内即出现
graphify-out/graph.json、GRAPH_REPORT.md与wiki/索引,此后 Gemini CLI 按本文规则 1–3 的次序检索; - 每次改动代码后运行
graphify update .增量刷新; - 需要换输出目录时,在进程启动前设置
GRAPHIFY_OUT环境变量(例如 worktree 隔离或团队共享输出)。
若需调整规则措辞,正确做法是修改 tools/skillgen/fragments/always-on/gemini-md.md 后由 skillgen 重新生成,而不是手改各项目里的 GEMINI.md 段落——否则下次 graphify install 的精确 section 替换会用包内版本覆盖你的手工修改。
小结
gemini-md.md 用十行文字把"图谱优先"的检索次序钉死在 Gemini CLI 的会话规则里:query/path/explain 三级子图查询是默认入口,wiki 索引承担宽泛导航,GRAPH_REPORT.md 退居全局评审兜底,graphify update . 保证图谱零 API 成本地保鲜。配合 install.py 的幂等 section 注入与 hook-guard gemini 的每次读取前提醒,这套机制让 AI 助手在回答代码库问题时,先看到的永远是"小得多、且每条边都有解释"的范围化子图,而不是整个报告或 grep 的洪流。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00