Ghost Monorepo 的 AGENTS.md:AI Agent 协作指南的设计与执行约束
根目录的 AGENTS.md 是 Ghost monorepo 面向 AI Agent 的执行指南,它定义了仓库内必须遵守的工作流(强制使用 pnpm、pnpm setup / pnpm check)、仓库级 Agent 技能(repository skills)的发现与校验机制,以及按子系统路由的任务指引和高价值警告。读完本文,你将理解这份文档如何与仓库脚本、pnpm 工作区配置、技能符号链接体系配合形成一套可被工具链自动验证的 Agent 协作规范,并掌握在多包、多运行时的大型 Node.js monorepo 中约束 Agent 行为的可复用方法。
文档定位:只放路由、约束与警告
AGENTS.md 开篇即声明自身边界:面向 Agent 的执行指引放在这里,而人类可读的环境搭建、工作流程、架构和实践说明放在 docs/README.md 及其引用的各篇文档、以及各包就近的 README 中。文末还给出了自我约束原则:
Keep shared facts in human documentation. This file should contain only routing, agent execution constraints, and high-value warnings that prevent recurring mistakes.
这条原则在仓库里有对应的机器校验:scripts/check-agent-guidance.js 定义了 MAX_AGENT_GUIDANCE_LINES = 150,会扫描 git ls-files 中所有被追踪的 **/AGENTS.md 文件并检查行数上限。也就是说,“Agent 指南必须短小精悍”不只是一句口号,而是被 pnpm lint:agent-guidance(经由根 package.json 的 lint:docs 串联)强制执行的质量门禁。
与之形成对照的是就近覆盖原则:文档要求“在修改某个包或子系统之前,先读最近的 AGENTS.md、CLAUDE.md 和 README,更具体的指引覆盖本文件”。仓库中嵌套 AGENTS.md 的典型例子是 apps/shade/AGENTS.md,它先引导阅读 Shade 的人类文档(README.md、src/docs/introduction.mdx、src/docs/contributing.mdx 等),再给出 Shade 专属的必做工作流(用 shade-component-decision 技能做组件决策、只从层级子路径导入而非根 barrel、使用语义 token 而非原始颜色等)。
另外,根目录的 CLAUDE.md 是指向 AGENTS.md 的符号链接(仓库中可见 CLAUDE.md -> AGENTS.md)。从源码结构看,这是一种“单一事实源 + 多入口别名”的做法:不同 Agent 工具(Claude Code 读 CLAUDE.md,其他 Agent 读 AGENTS.md)读到的是同一份内容,避免双份文档漂移。
阅读顺序:Start with 清单
文档给出了一份固定的阅读顺序,全部指向 docs 目录下的实践文档:
这六份文档覆盖了从克隆仓库到提交 PR 的完整生命周期,AGENTS.md 的作用相当于给 Agent 的“目录页”:先读这些,再进入具体任务。
必做工作流:pnpm、setup 与 check
文档“Required workflow”一节列出了五条硬性规则,每条都能在仓库中找到对应的实现证据。
只用 pnpm,外部依赖版本进 catalog
规则原文:永远使用 pnpm,禁止 npm 或 Yarn;外部依赖的版本号放在 pnpm-workspace.yaml 的 catalogs 中,工作区内部依赖使用 workspace: 版本。
仓库中有两层保障。第一层是拦截:根 package.json 的 preinstall 钩子执行 scripts/enforce-package-manager.js。该脚本通过 npm_config_user_agent 判断调用方是否为 pnpm,若不是则进一步检查是否存在 pnpm_config_* 环境变量作为回退信号(脚本注释说明这是为了应对某些 CI 环境下 user agent 未传递到生命周期脚本的问题),两者都不满足时打印一段包含 corepack enable pnpm 及 yarn 到 pnpm 命令替换对照表的提示并以非零码退出。第二层是配置约束:pnpm-workspace.yaml 设置了 catalogMode: strict,意味着依赖版本应当统一走 catalog;工作区包由 ghost/*、apps/*、e2e、koenig/*、packages/**(排除 packages/_template)、configs/*、scripts 等 glob 定义。同一个文件还启用了 strictDepBuilds: true 和 blockExoticSubdeps: true,并用 allowBuilds 白名单按“包@版本”粒度精确控制哪些依赖允许执行安装期构建脚本(如 sharp@0.35.3、better-sqlite3@12.11.1 允许,sqlite3、ssh2、@sentry/cli 明确为 false),配合 minimumReleaseAge: 4320(3 天,与 Renovate 配置对齐)限制过新版本的引入——从源码结构看,这套配置把“锁版本、防供应链、控构建脚本”三道闸门都固化在了工作区配置层,Agent 无需理解细节也不会误操作。
全新检出先跑 pnpm setup
pnpm setup 的定义在根 package.json:
pnpm install && git submodule update --init --recursive && git config --local blame.ignoreRevsFile .git-blame-ignore-revs
它做了三件事:安装依赖、初始化 git submodule(Ghost 的仓库结构中包含子模块)、配置 blame.ignoreRevsFile 指向 .git-blame-ignore-revs(用于在 git blame 中忽略批量格式化等提交)。对 Agent 的意义在于:不先跑 setup 就执行其他命令,可能因缺少子模块内容或依赖而得到误导性报错。
pnpm check 作为默认全量校验
check 脚本的展开是:
pnpm format:check && pnpm lint && pnpm test
其中 format:check 使用 oxfmt --check;lint 串联 nx run-many -t lint lint:boundaries、lint:packages(内部包检查)与 lint:docs(后者又包含 lint:agent-skills、lint:agent-guidance、lint:markdown、lint:doc-links,即 Agent 相关门禁本身也是 pnpm check 的一部分);test 通过 nx 在全部工作区跑 test target,但显式排除了 @tryghost/e2e 和 ghost-admin 两个项目——这正对应文档中“Browser E2E 和 Ember Admin 测试单独运行,遵循测试指南(docs/contributing/testing.md)”的说明:浏览器 E2E 需要完整的 Docker 基础设施与浏览器环境,Ember Admin 测试走独立 runner,两者都不适合混在默认校验里。
提交时加载 commit 技能
规则要求“提交时加载并遵循 .agents/skills/commit/SKILL.md”。该技能规定了提交前检查 git status / git diff / git log -5 --oneline、只 stage 与本次改动相关的文件、以 .github/CONTRIBUTING.md#commit-messages 为提交约定的事实源、区分“需要发布的包”(README 会随包发布,需要 release intent)与纯仓库 Markdown(如 AGENTS.md、CLAUDE.md、changelog 不需要)、提交后确认结果,以及两条红线:用户不要求就不 push,hooks 失败就修复后重新提交、绝不绕过 hooks。
Repository Skills:.agents/skills/ 与符号链接校验
仓库技能集中存放在 .agents/skills/ 下,当前包含约 20 个技能目录,覆盖面包括:
- 高风险操作类:
add-admin-api-endpoint、create-database-migration、add-private-feature-flag、tinybird、tinybird-cli-guidelines - 包迁移类:
migrate-internal-package、convert-internal-package-to-typescript - UI 组件类:
shade-component-decision、shade-new-component、shade-imports、shade-tokens-not-hex、shade-no-dark-variants、shade-shadcn-install、shade-page-templates、shade-dropdown-surface-contract、shade-input-surface-recipe、shade-use-primitives - 通用类:
commit、format-number
文档规定的新增技能流程是两步:技能实体放在 .agents/skills/<name>/,同时创建指向 ../../.agents/skills/<name> 的 .claude/skills/<name> 符号链接,再运行 pnpm lint:agent-skills 验证可发现性。当前仓库的 .claude/skills/ 目录下 20 个条目全部是指向 ../../.agents/skills/* 的符号链接,与该约定一致。
这个约定的机器校验实现在 scripts/check-agent-skill-links.js:它遍历 .agents/skills/ 的每个子目录,逐一检查 (1) 存在 SKILL.md 且为普通文件;(2) .claude/skills/<name> 存在且是一个符号链接;(3) 链接目标恰为 ../../.agents/skills/<name>。任何一条不满足都会报错并直接打印修复命令(例如 ln -s ../../.agents/skills/<name> .claude/skills/<name>)。从源码结构看,这套“实体目录 + 符号链接 + 脚本校验”的组合,让同一个技能目录同时被 .agents(通用约定)和 .claude(Claude Code 约定)两套发现机制引用,而校验脚本保证两者不会脱节。
文档还明确了必须“先加载对应技能再动手”的四类场景:新增 Admin API 端点(add-admin-api-endpoint,其目录含 SKILL.md、reference.md、validation.md、permissions.md 四个文件)、新增数据库迁移(create-database-migration,含 rules.md 与 examples.md)、新增私有 feature flag(add-private-feature-flag)、新增 Shade 组件或内部包(对应 shade 系列与 migrate 系列技能)。
任务路由与高价值警告
文档“Task routing and important warnings”一节按子系统给出了路由规则和防止反复踩坑的警告,每条都指向具体的参考文档:
Admin UI
读 apps/admin/README.md 和 apps/shade/AGENTS.md。新特性用 React 构建,API 层使用 admin-x-framework(对应 apps/admin-x-framework 包),UI 层使用 Shade。关键警告:Admin 与 Core 是独立部署的,因此前端必须 feature-detect 后端能力,并专门测试“旧版本后端”的场景——这条针对的是 monorepo 中前后端版本错位这一典型故障源。
嵌入式 Admin CSS 警告
禁止从嵌入式应用(embedded app)导入 @tryghost/shade/styles.css:Admin 独占唯一的 Tailwind 与 Shade CSS 通道(CSS lane)。从源码结构看,这与 apps/shade/AGENTS.md 中“不要在嵌入的 Admin 应用里导入该样式表或再加一层 ShadeApp 包装”是同一约束的两处表述,目的是避免多份 Tailwind/样式运行时共存导致的样式冲突与体积膨胀。
翻译(i18n)
遵循 docs/practices/internationalization.md:修改 t() 调用后必须运行提取命令(仓库的 packages/i18n 提供 i18next-parser 相关配置与 311 个 locale 文件),并且绝不把一句话拆进多个翻译调用——拆分会破坏翻译上下文的完整性。
Public apps(公开应用)
先读对应应用的 README 与 发布指南。apps/ 下的 portal、comments-ui、signup-form、sodo-search、announcement-bar、admin-toolbar 等公开应用的发布节奏与 CSS 通道和 Admin 不同,不能套用 Admin 的流程。
Ghost Core
新增服务前先查 monorepo 结构中的 Ghost Core 部分 和 services 指南。约束包括:新的独立服务使用 TypeScript 编写,CommonJS 只保留在既有的 require() 边界;服务初始化由 Boot 统一负责,禁止在首次请求时懒初始化(从源码结构看,这是为避免请求路径上的首次调用开销和初始化顺序不可控问题)。
ESLint 配置
使用 configs/eslint/README.md 中的共享工厂与依赖规则;手写的 ESLint 配置必须在本地声明它导入的每一个插件。仓库内各包(如 apps/shade/eslint.config.js、apps/admin/eslint.config.js)都遵循这一约定,且 configs/eslint-react 提供 React 侧的共享工厂。
Analytics
从 pnpm dev:analytics 起步(对应根 package.json 中的脚本,通过 DEV_COMPOSE_FILES='-f compose.dev.analytics.yaml' 叠加 compose.dev.analytics.yaml 启动 Tinybird 等依赖),并遵循 ghost/core/core/server/data/tinybird/ 下的就近 README。
对 Agent 工程实践的三点启示
- 文档分层,各负其责。 人类文档(docs/、README)承载共享事实,AGENTS.md 只承载路由、约束、警告,并用 150 行上限(scripts/check-agent-guidance.js)防止 Agent 指南膨胀成第二份重复文档。
- 约定必须可被脚本验证。 pnpm 强制(
preinstall钩子)、技能符号链接(lint:agent-skills)、catalog 严格模式(catalogMode: strict)、文档链接(lint:doc-links使用remark-validate-links --frail)——每一条规则都有对应的自动检查,pnpm check一次性跑完,Agent 与人遵守的是同一套门禁。 - 高风险操作前置技能清单。 数据库迁移、Admin API 端点、feature flag、Shade 组件这类“做错代价高”的操作,通过强制加载
.agents/skills/下带规则与验证清单的技能目录来约束流程,而不是依赖 Agent 的临场判断。
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 StartedRust0627
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