用 AI 写前端的人,大概都经历过这两种翻车现场。
引子:两个让我决定动手的场景
场景 A(静态盲区):让 AI 改 .btn-primary 的圆角。它 grep 出 6 个候选文件、逐一 Read,然后告诉你"这几处可能互相覆盖"——十几个工具调用之后,级联关系还是要你自己判断。
场景 B(运行期盲区):问 AI"为什么 .sidebar 在 1280px 宽度下会溢出",它读完一圈 CSS 给不出结论。因为溢出是运行期行为——容器宽度、滚动链、containing block 劫持——静态代码里根本没有答案。
AI 写前端已经很强,但在 CSS 这件事上,它获取信息的方式是残缺的:看不到结构(图谱),也看不到现场(渲染)。
所以我做了两个开源工具,一个负责静态、一个负责运行期:
- cssgraph — 把样式表解析成知识图谱,通过 MCP 提供给 AI Agent;
- cssprobe-cli — 用真实浏览器做运行时探针,把"页面实际渲染成什么样"变成结构化输出。
cssgraph:给 AI 一张 CSS 地图
它索引什么
索引覆盖面:CSS / SCSS / Less / Sass (indented) / PostCSS、CSS Modules、CSS-in-JS、JSX/TSX 里的 className 引用、ERB / Haml / HTML 模板的 class 提取,以及 Tailwind v3(JS config)和 v4(CSS @theme)。
索引结果落在一个本地 SQLite 知识图谱里:每个 className、属性、变量、at-rule 都是节点,引用 / 覆盖 / 级联是边。
性能参考(来自项目 README 的实测表):
| 项目规模 | 文件数 | 首次索引耗时 | 节点 | 边 |
|---|---|---|---|---|
| 小型项目 | ~50 | ~15s | ~16K | ~50K |
| 生产级 monorepo | ~11K | 3–5 min | ~780K | ~2200万 |
100% 本地运行,没有网络请求,不上传任何样式代码。
MCP:13 个工具
对外接口是 MCP(Model Context Protocol),核心工具包括:
cssgraph_rule:精确查找某个选择器(O(1)),返回 loose / strict 两级影响范围cssgraph_explore:一次拿全 —— 属性、覆盖关系、特异性、引用组件cssgraph_impact:评估"改这个 className 会影响哪里"
安装与接入:
npm i -g cssgraph
cd your-project
cssgraph init --workers 8 # 建立索引(workers 控制并行解析)
cssgraph mcp-install # 自动写入 MCP 配置 + Agent Skill
mcp-install 会自动识别并配置 Claude Code、Cursor、Codex CLI、opencode、Gemini CLI、Antigravity 等 8 种客户端,同时写入一个 Agent Skill(SKILL.md + pitfalls),教 agent 何时用哪个工具、如何串联、哪些坑不要踩。
文件监听默认开启:你改 CSS,agent 同时在查——索引永远是新的,不存在"过期索引"问题。
效果
Agent 问"哪些代码引用了 .btn-primary":
以前:grep → 6 个文件 → 逐一 Read → 手工拼级联 → 猜测。
现在:一次 cssgraph_rule 调用,返回 properties / overrides / specificity / callers / impact。
cssprobe-cli:给 AI 一双眼睛
它解决什么
溢出、滚动链、containing block 劫持、字号继承链……这些问题的答案只存在于真实渲染里。
cssprobe-cli 打开一个真实 Chromium(基于 Playwright),注入收集器读取 computed styles 和元素度量,再由纯 Node 函数分析器输出结论。每条结论都带置信度分级:
- DEFINITE:可以证明的结论
- INDEFINITE:有证据但存在解释分支
- UNVERIFIABLE:静态无法证明,显式标记"需要运行时验证"
这个置信度设计是我最喜欢的一部分:它诚实——不把"猜测"包装成"结论",agent 拿到之后知道哪些可以信、哪些要再验证。
用法
npm i -g cssprobe-cli
cssprobe-cli open https://example.com # 启动 daemon 会话 + 浏览器
cssprobe-cli inspect .sidebar # 检查:DOM 树 + 布局 + findings
cssprobe-cli layout .sidebar # 只看 ASCII 布局图
cssprobe-cli findings .sidebar # 只看问题清单
cssprobe-cli close # 关闭会话
输出支持 JSON,可以直接喂给 agent 或者用 jq 处理:
cssprobe-cli inspect body --json | jq '.findings[] | {id, confidence, message}'
需要登录的页面也能处理:
cssprobe-cli open https://mysite.com --headed # 手动登录
cssprobe-cli state-save --name mysite # 保存会话状态
cssprobe-cli open https://mysite.com --state state.json # 之后免登录复用
一起用:一静一动的完整链路
AI Agent
│
├─ "这个 className 的样式从哪来?" ──▶ cssgraph(静态图谱)
│ 一次调用:属性 / 覆盖 / 特异性 / callers / impact
│
└─ "页面实际渲染成什么样?" ──▶ cssprobe-cli(运行时探针)
真实 Chromium:布局 / 溢出 / 滚动链 / 置信度分级结论
典型修复流程:
- 要改
.card的样式 →cssgraph一次调用拿全定义与影响面 - 改完验证渲染 →
cssprobe-cli inspect .card看实际布局与 findings - 修复后对照 findings 确认问题消除
静态管线管"改得对",运行时管线管"跑得对"。
为什么不用现成的东西
- 为什么不用 grep / Read:不是慢一点的问题——CSS 的答案(覆盖关系、特异性)需要跨文件重建,这恰好是模型最不擅长、token 花得最多的地方。
- 为什么不用 DevTools:DevTools 是给人看的,交互式面板对 agent 不可读;cssprobe 的输出是结构化的、带置信度的、可以直接进上下文的。
- 为什么坚持本地:样式表是私有资产,不适合拉到云端做索引。两个工具都 100% 本地,无账号、无 API key、无遥测负担。
开源信息
两个项目都是 MIT 协议,欢迎 issue、PR 和 star:
- cssgraph:github.com/mack-peng/c…
npm i -g cssgraph(Node >= 22.5,用了node:sqlite) - cssprobe-cli:github.com/mack-peng/c…
npm i -g cssprobe-cli(Node >= 18)
cssgraph 已发布到官方 MCP Registry(io.github.mack-peng/cssgraph),在 Claude Code / Cursor / Codex 里都可以直接接入。
如果你也在用 AI 写前端,并且受够了"跟 AI 争论 CSS 到底谁覆盖了谁",这两个工具应该能省下你不少时间。用起来有任何问题,评论区见——有问必回。