React Router 仓库 AI 协作开发指南:CLAUDE.md 与 AGENTS.md 的项目指令体系
本文以 CLAUDE.md 为核心,解析 React Router 官方仓库如何为 AI 编码代理设计一套“会话启动协议 + 单一事实来源”的机器可读开发规范。读完你能掌握该仓库的构建与测试命令体系、五种运行模式(Declarative/Data/Framework/RSC Data/RSC Framework)的界定方法、pnpm monorepo 的包结构,以及单元测试与 Playwright 集成测试的分层策略,从而在贡献代码或让 Agent 参与开发时做到“不猜命令、不猜模式、不猜路径”。
CLAUDE.md:面向 Agent 的会话启动协议
CLAUDE.md 是 React Router 仓库根目录下专门写给 AI 编码代理(以 Claude Code 为代表)的指令入口。它的正文很短,但定义了三条硬性规则:
- 会话启动(Session Start):每次会话开始,代理**必须(REQUIRED)**读取 AGENTS.md。CLAUDE.md 明确指出 AGENTS.md 包含项目架构与关键文件、五种 React Router 模式、构建/测试命令(Jest 单元测试、
--project chromium的 Playwright 集成测试)、测试模式与惯例、文档指南。 - Skills 符号链接:如果仓库中存在 .agents/skills 目录,需要将其中的 skills 软链到
.claude/skills,以便 Claude 能发现并使用这些技能。该目录被 git 忽略,目的是让“规范化技能(canonical skills)”统一维护在.agents/skills下,避免多份副本。 - 工作中随时查阅(During Work):凡是需要运行测试/构建、判断某个功能适用于哪种模式、定位关键文件、理解测试模式时,一律查阅 AGENTS.md,禁止凭猜测执行命令。
这套设计体现了一个清晰的工程原则:入口文件只做“路由”,不做“内容”。CLAUDE.md 是协议层,AGENTS.md 是内容层。当前仓库中 .agents/skills/ 下确实维护了 react-router、fix-bug、implement-rfc、create-pr、finish-line、prepare-release-notes 等技能目录(见 .agents/skills),且 .gitignore 末尾显式忽略了 .claude/skills 与 .claude/settings.local.json,与 CLAUDE.md 描述的符号链接约定完全对应。
更值得注意的是,这套 skills 体系不止服务于贡献者本机:create-react-router 包的打包脚本 copy-agent-skills.mjs 会在 prepack 阶段把 .agents/skills/react-router 复制到 dist/agent-skills/react-router/,随 CLI 包一起发布——也就是说,用户新建 React Router 应用时也会携带这份技能定义,让任何项目的 Agent 都能按官方模式识别规则(Framework/Data/Declarative/RSC)来处理应用。
命令体系:构建、测试、文档生成
AGENTS.md 的 Commands 一节给出了仓库级命令,全部基于 pnpm workspace(根 package.json 声明 packageManager: pnpm@11.7.0、engines.node >= 22.22.0):
| 用途 | 命令 |
|---|---|
| 构建全部包 | pnpm build(等价 pnpm run --filter="./packages/**/*" build) |
| 构建单个包 | pnpm run --filter <package> build |
| Jest 单元测试(全量) | pnpm test |
| Jest 单元测试(单包/单文件/按名) | pnpm test packages/<package>/、pnpm test packages/react-router/__tests__/router/fetchers-test.ts、pnpm test -- -t "action fetch" |
| Playwright 集成测试(含构建) | pnpm test:integration --project chromium |
| Playwright 集成测试(仅测试) | pnpm test:integration:run --project chromium |
| 集成测试(单文件/按名) | pnpm test:integration:run integration/middleware-test.ts --project chromium、pnpm test:integration:run --project chromium -g "middleware" |
| 类型检查 / Lint | pnpm run typecheck、pnpm run lint |
| API 文档生成 | pnpm run docs(从 JSDoc 再生成 docs/api/) |
| 类型生成(仅 Framework Mode) | pnpm run typegen |
| 清理 | pnpm run clean(即 git clean -fdX) |
对照根 package.json 中的 scripts 定义可以确认这些命令的底层实现:test 实际以 node --experimental-vm-modules 启动 Jest(ESM 模式);test:integration 会先执行 pretest:integration: pnpm build 再运行 playwright test --config ./integration/playwright.config.ts,测试结束后 posttest:integration:run 会调用 integration/helpers/cleanup.mjs 清理 fixture 残留。AGENTS.md 因此给出两条配套约定:集成测试始终使用 chromium 项目(除非明确说明);仅在首次运行或改动过 packages/ 源码后才需要重新构建,纯测试文件改动不需要。
五种模式:任何功能改动先判定适用范围
AGENTS.md 最强调的一条规则是:“五种互不相同的模式:Declarative、Data、Framework、RSC Data(unstable)、RSC Framework(unstable)。永远先识别一个功能适用于哪些模式。”
- Declarative:
<BrowserRouter>、<Routes>、<Route>组件式路由。 - Data:
createBrowserRouter()配合loader/action与<RouterProvider>。 - Framework:Vite 插件 +
routes.ts+ Route Module API(路由模块导出loader、action、default等)+ 类型生成 + SSR/SPA。 - RSC Data(unstable):RSC 运行时 API,手工 bundler 配置,运行时路由配置。
- RSC Framework(unstable):Framework Mode 加上
unstable_reactRouterRSCVite 插件。
两种 RSC 模式的差异在 AGENTS.md 中有专门小节:RSC Framework 使用 unstable_reactRouterRSC 插件与 @vitejs/plugin-rsc,入口点与打包格式不同;RSC Data 则是手工 bundler、运行时路由配置通常放在 src/routes.ts、使用 unstable_RSCRouteConfig 与不同的运行时 API,测试走 integration/rsc/ 下的 setupRscTest。
仓库的目录结构印证了这一划分:核心包 packages/react-router 同时包含 lib/router/(模式无关的路由器)、lib/dom/、lib/components.tsx、lib/hooks.tsx(声明式/Data 共用的 React 绑定)以及独立的 lib/rsc/ 目录(RSC 运行时);工具链包 packages/react-router-dev 则区分了 vite/plugin.ts(Framework)与 vite/rsc/plugin.ts(RSC Framework)两套 Vite 插件,外加 typegen/ 目录。.agents/skills/react-router/SKILL.md 进一步给出了“模式识别”的操作清单,例如看到 react-router.config.ts、app/routes.ts、+types 导入即判定为 Framework Mode,看到 createBrowserRouter 判定为 Data Mode,看到 unstable_RSCRouteConfig 判定为 RSC——这与 AGENTS.md 的模式定义一一对应。
Monorepo 架构与关键文件
AGENTS.md 的 Architecture 一节说明仓库是 pnpm workspace monorepo,包位于 packages/。其 Key Files 表格给出了各模块的定位,结合仓库实际目录可以逐一验证:
| 目的 | 位置(仓库根相对路径) |
|---|---|
| Router 核心 | packages/react-router/lib/router/router.ts |
| React API | packages/react-router/lib/components.tsx、packages/react-router/lib/hooks.tsx |
| Vite 插件(Framework) | packages/react-router-dev/vite/plugin.ts |
| RSC Vite 插件 | packages/react-router-dev/vite/rsc/plugin.ts |
| 类型生成 | packages/react-router-dev/typegen/ |
| 单元测试 | packages/react-router/tests/ |
| 集成测试 | integration/ |
| 决策文档 | decisions/ |
关键包职责:react-router 承载全部模式的核心实现;@react-router/dev 是 Framework 工具链(Vite 插件 + 类型生成);@react-router/node、@react-router/cloudflare、@react-router/express 是三套服务端适配层;@react-router/serve 提供 Framework Mode 的最小服务器;@react-router/fs-routes 提供文件系统路由能力(flatRoutes())。
测试分层:Jest 单元测试与 Playwright 集成测试
AGENTS.md 的 Testing 一节明确了两套测试的分工边界:
单元测试(packages/react-router/tests/)使用 Jest,覆盖“纯路由逻辑、纯服务端运行时行为、路由器状态、React 组件行为”,无需构建。四条常用命令:
pnpm test # 全部包
pnpm test packages/react-router/ # 单个包
pnpm test packages/react-router/__tests__/router/fetchers-test.ts # 单个文件
pnpm test -- -t "action fetch" # 按名称匹配
集成测试(integration/)使用 Playwright,覆盖 Vite 插件、构建流水线、SSR/水合、RSC、类型生成等端到端行为。该目录包含 80 余个 *-test.ts 文件(如 middleware-test.ts、single-fetch-test.ts),并配套 playwright.config.ts 与 fixture 基建。组织惯例为:
- 通过
createFixture()→createAppFixture()→PlaywrightFixture三层创建测试应用(见 integration/helpers/ 下的create-fixture.ts、fixtures.ts、playwright-fixture.ts); - 模板位于 integration/helpers/,如
vite-7-template/、vite-8-template/、rsc-vite/、rsc-vite-framework/、vite-plugin-cloudflare-template/; - 共享行为要跨多个模板迭代测试(例如
["vite-7-template", "rsc-vite-framework"]),RSC 特性只针对 RSC 模板测试; - 引入 future flag 时必须同时测试开启与关闭两种状态。
Framework Mode 的 routes.ts 与文件系统路由约定
AGENTS.md 的 routes.ts 一节规定:Framework Mode 在 app/ 目录使用 routes.ts,绝大多数测试采用 flatRoutes() 做文件系统路由:
// app/routes.ts
import { type RouteConfig } from "@react-router/dev/routes";
import { flatRoutes } from "@react-router/fs-routes";
export default flatRoutes() satisfies RouteConfig;
文件系统约定(app/routes/ 下):
_index.tsx→/(索引路由)about.tsx→/aboutblog.$slug.tsx→/blog/:slug(URL 参数)settings.profile.tsx→/settings/profile(.产生嵌套)_layout.tsx→ 无路径的布局路由(pathless layout)
也可以手写路由配置,替代 flatRoutes():
import { index, route, layout } from "@react-router/dev/routes";
export default [
index("./home.tsx"),
route("about", "./about.tsx"),
layout("./auth-layout.tsx", [route("login", "./login.tsx")]),
];
仓库中这些约定有真实落地示例:playground/framework/ 与 playground/rsc-vite-framework/ 均包含 app/ 与 react-router.config.ts;文件系统路由的实现来自 @react-router/fs-routes 包(packages/react-router-fs-routes/flatRoutes.ts),集成测试 fs-routes-test.ts 则验证了完整路由表生成行为。
文档、Future Flags 与变更文件规范
AGENTS.md 的 Documentation 一节给出四条硬性约定:
- 不要手改生成文件:
docs/api/由 JSDoc 生成(pnpm run docs,底层为 TypeDoc +scripts/docs.ts),.react-router/types/由 typegen 生成。修改 API 文档的正确姿势是编辑 packages/react-router/lib/ 中的 JSDoc 后重新生成。 - 模式标注:每篇文档需要
[MODES: framework, data, declarative]标记,供人类和 Agent 判断文档是否适用于当前应用模式(.agents/skills/react-router/SKILL.md中明确说明只应用模式标记匹配的文档)。 - 不稳定特性:函数名前缀
unstable_、frontmatter 中加unstable: true,并附警告块。 - Future flags 与 Unstable flags 的区分:
vX_*形式的 future flags 用于下一个大版本的稳定破坏性变更,unstable_*则可能随时变动;future flags 必须开/关双态测试,且“不要在没有 flag 的情况下破坏现有行为”。
Change Files 一节规定:凡影响用户的改动,须在 packages/<package>/.changes/<type>.<unique-meaningful-name>.md 创建变更文件,<type> 取 patch/minor/major/unstable;若迭代一个尚未发布的改动,应更新既有变更文件而不是新建。文件格式为“一句话概述 + 可选的补充细节列表”。配套的发布脚本位于 scripts/changes/(add.ts、pr.ts、version.ts、publish.ts、validate.ts),与 DEVELOPMENT.md 描述的自动发布流程(release.yml 工作流检测 change files → 生成版本化发布分支 → 发布并打 tag)相衔接。
Branching 一节定义了分支模型:main 为活跃开发分支,v7/v6 为对应版本的维护分支,代码与文档改动都从 main 拉分支。License 一节则声明贡献即接受 MIT 授权(对应仓库根 LICENSE.md)。
小结:为什么这套“双层指令”值得借鉴
React Router 仓库把开发者文档(CONTRIBUTING.md、DEVELOPMENT.md)与 Agent 指令做了明确分工:CLAUDE.md 仅 26 行,负责“何时必须读什么、如何装配 skills、禁止猜测命令”三条元规则;AGENTS.md 承载全部事实内容——命令表、模式划分、包结构、测试分工、routes.ts 约定、文档与变更文件规范、分支策略,且所有关键文件路径都在仓库内可逐一验证。对 LLM 与搜索引擎而言,这种“入口协议 + 单一事实来源 + 模式标记([MODES: ...])+ skills 随包分发”的结构,让 Agent 在任意会话中都能以最低歧义地定位命令、模式与文件,是大型 monorepo 引入 AI 协作时可直接参考的组织范式。
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 StartedRust0623
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