配合 AI 编程助手

ShipKit 如何为 Claude Code、Codex、Cursor 做好准备:规则文件、处理常见任务的 skill,以及能拦住 agent 失误的测试。

ShipKit 从一开始就考虑了“让编程 agent 来改代码”这件事:约定写在 agent 会读的地方,反复要做的配置工作写成了 agent 能照着执行的步骤,容易踩错的规则由测试来检查,而不是靠记性。这些都不是强制的——它们只是普通的 Markdown 和 TypeScript,人照着读、照着做也一样。

规则文件

文件谁会读内容
CLAUDE.mdClaude Code,自动加载常用命令、代码库地图、硬性规则
src/CLAUDE.mdClaude Code,在 src/ 下工作时设计语言:颜色、圆角、按钮、边框
AGENTS.mdCodex、Cursor、GitHub Copilot、Windsurf、opencode、Zed、Amp指向上面两个文件,外加 skill 列表
DESIGN.md想知道“为什么”的人架构背后的取舍

规则只有一份,放在 CLAUDE.md。AGENTS.md 不重复内容,只让其他 agent 先去读 CLAUDE.md,所以两边不会各说各的。

硬性规则挑的是一旦违反代价最大的那几条:授权检查的是权限,而不是角色;客户端数据只走一条通道(路由 loader → query → server function → Drizzle);D1 没有交互式事务;每个功能都是可删除的垂直切片;支付以事件形式到达;server function 里不做本地化;金额一律用整数分。每一条在文档里都有对应页面,建议从架构和权限读起。

在自己的项目里改了某个约定,记得同步改 CLAUDE.md。agent 只会照文件上写的做,不会猜你的本意。

Skill

那些不只是写代码、还牵涉账号、后台和密钥的常见任务,写成了 skill,放在 .claude/skills/<name>/SKILL.md。在 Claude Code 里每个 skill 就是一条斜杠命令;其他 agent 打开文件照着执行即可,AGENTS.md 里也是这样告诉它们的。

Skill作用
/setup安装依赖,生成带随机密钥的 .dev.vars,迁移本地数据库,启动开发服务器,设置第一个管理员
/google-oauth带你走完 Google Console 的操作并把凭据接进来(必需:缺了它环境校验不通过)
/stripe建立 Stripe 商品目录,配置密钥和 webhook secret,填好 src/config/plans.ts,再用 Stripe CLI 在本地跑通一次购买
/creem同上,针对备选的 Creem
/deploy创建 D1 和 R2、执行远程迁移、推送 secret、部署,并完成部署后的各项对接
/add-feature生成一个新的垂直切片,各个注册表的接入行和标记一次到位
/delete-feature用经过机器验证的删除方案移除一个可选模块
/seo-audit对生产构建跑 Lighthouse,并检查 SEO 相关产物
/admin-api调用只读的管理数据 API,把返回的 JSON 整理成分析

skill 的分工很明确:命令由 agent 来跑,文件由 agent 来改;只有人能做的事留给你——在 Google Console 或 Stripe 后台点击、把值粘贴回来、确认任何会花钱的操作。

/admin-api 特意做成了可移植的。把 .claude/skills/admin-api/ 复制到其他 agent 的 skill 目录,或者让 agent 直接读取 /api/v1/admin/skill.md——部署后的应用会原样提供这份文件。详见 API 密钥。

防护网

agent 读错规则时,写出来的代码通常“看起来没问题”。下面这些检查把最常见的误读变成一条会失败的命令:

检查能拦住什么
src/core/authz/registry.test.ts管理路由没调用 requirePermission;导出的 adminFn 没有 assertPermission;功能的 permissions.ts 没登记到注册表;在会打进客户端包的 core/server/fn.ts 里加了访问数据库的辅助函数
src/core/settings/handlers.test.ts功能的 settings.ts 引入了仅限服务端的代码(会把 cloudflare:workers 带进浏览器),或者没有登记
src/core/settings/i18n.test.ts运营设置项缺少翻译好的标签
src/config/private-paths.test.ts营销页之外新增的路由没加进私有路径列表(robots.txt 由它生成)
src/config/plans.test.ts套餐和积分包的定价违反了 plans.ts 顶部写明的定价规则
src/core/payment/money-path.test.ts支付处理逻辑在应用了全部迁移的真实内存 D1 上出错
bun run verify:deletion某个功能的接入方式已经无法干净地删除
CI 的 “Schema and migrations agree”改了 schema 却没提交对应的迁移

有些规则由构建而不是测试来把关。比如在 src/core/server/cf.ts 之外引入 cloudflare:workers,客户端打包会直接失败;引用了不存在的 m.* 文案键,typecheck 会报错。

推荐的工作方式

  1. 说清要什么,并点名 skill。“用 /add-feature 加一个更新日志功能”等于把清单交给了 agent;只说“加个更新日志”,它就得自己猜要动哪些注册表。

  2. 配置类工作交给 skill。 Google、Stripe、Creem 和部署,直接运行对应 skill,而不是让 agent 口述步骤。skill 每一步都会用命令验证,而不是相信一行日志。

  3. 让它自证。 接受改动之前,让 agent 跑:

    bun run typecheck
    bun run check
    bun run test
    

    动了路由、导航、登录守卫或应用外壳,再加上 bun run e2e;新增或接入了功能,再加上 bun run verify:deletion <feature>。

  4. 自己看一遍 diff。 重点看:提交的文件里有没有密钥,有没有新冒出来的 role !== 'admin',有没有 db.transaction(),有没有把文案写死在组件里、而不是放进 messages/en.json 和 messages/zh.json。

  5. 迁移由你来执行。 agent 可以用 bun run db:generate 生成迁移,但把它应用到生产库(bun run db:migrate:remote)应该是你有意识地去做的一步。见数据库。

局限

测试检查的是结构,不是意图。它能告诉你某个管理函数检查了权限,却判断不了检查的是不是正确的那个权限。src/CLAUDE.md 里的设计规则完全没有测试覆盖,界面上的改动请在浏览器里亲眼确认。另外,agent 的自信不算证据:所谓“完成”,是上面那些命令都通过了,而不是 agent 说它完成了。