团队里用 Copilot 写代码,最头疼的不是它写不出来,而是写出来的东西“能跑但不像自己人写的”。命名风格飘忽、错误处理随手 try-catch、目录放错位置,review 时反复提同样的问题。根因在于 Copilot 默认只根据当前文件和少量上下文推断意图,它不知道你们团队约定俗成的规范。解决办法不是每次在 prompt 里重复交代,而是把规范沉淀到项目级配置文件中,让 Copilot 在生成时尽可能读取。
需要先说明一个事实边界:截至本文撰写时,输入资料中仅有搜索需求信号,没有官方一手文档确认 .github/copilot-instructions.md 的具体路径、自动加载行为或项目级优先级。因此下文涉及该文件的内容,均属于社区常见实践与工程探索方向,具体机制请以你所用工具的官方文档为准。
一、自定义指令的定位:写给 AI 看的项目约定
社区中较常见的做法是在仓库根目录维护 .github/copilot-instructions.md,将其作为项目级自定义指令的候选载体。它本质上是一份写给 AI 看的“项目约定说明书”,而不是给人看的文档。因此写法要具体、可执行,避免“代码要优雅”这类无法落地的描述。
在官方文档确认之前,建议把它当作“可尝试的工程实践”而非“已确认的产品能力”。你可以先在一个仓库试点,观察生成结果是否变化,再决定是否推广。
二、指令文件通常覆盖的四类信息
以下内容为示例约定,不是官方推荐标准,请按团队实际情况替换。
第一是命名约定:组件用 PascalCase、工具函数用 camelCase、常量用 UPPER_SNAKE_CASE、文件名用 kebab-case 还是 snake_case。
第二是错误处理:是抛异常还是返回 Result 对象,日志用哪个 logger,是否允许空 catch。
第三是目录结构:新增组件放 src/components,API 封装放 src/services,类型定义放 src/types。
第四是依赖与风格:优先用项目已有的工具库而不是引入新依赖,格式化交给 Prettier,不要手动调缩进。
三、写法建议:短句、可匹配、可执行
写法上建议用“必须/禁止”的短句,而不是长篇解释。例如:
- 所有异步函数必须使用 async/await,禁止 .then() 链式调用。
- 错误必须通过 throw new AppError(code, message) 抛出,禁止直接 throw new Error。
- 新增 React 组件必须放在 src/components// 下,文件名使用 PascalCase。
- 禁止引入 lodash,使用 src/utils 下已有工具函数。
注意:上述 AppError(code, message)、React 目录结构等均为示例约定,不是官方推荐标准。这种写法对 Copilot 的约束效果可能好于自然语言描述,因为它把判断条件收敛成了可匹配的模式。
四、与 lint、CI、code review 形成闭环
指令文件不是写完就一劳永逸,也不能替代 lint 和测试。它需要和 lint、code review 形成闭环。
第一步,把指令文件纳入版本控制,任何规范变更都通过 PR 修改,保证团队共识。
第二步,在 CI 中运行 ESLint、Prettier、TypeScript 检查,Copilot 生成的代码如果违反硬性规则会在流水线被拦下。
第三步,在 code review 中只关注 lint 覆盖不到的语义问题,比如错误处理是否合理、目录划分是否恰当,而不是重复纠正格式。
第四步,把 review 中反复出现的问题反哺回指令文件,让它逐步收敛。
需要强调:lint、CI 和 code review 是最终防线,指令文件只是前置引导。
五、边界与工程取舍
自定义指令影响的是生成建议,不是强制门禁。Copilot 仍可能忽略指令,尤其是当当前文件上下文与指令冲突时。因此不能把规范执行完全寄托在指令文件上。
另外,指令文件过长可能稀释每条规则的影响力,建议控制在几十行以内,只保留高频、易错的约定。
工程上还有一个取舍:指令文件是项目级还是用户级。项目级放在仓库里,团队共享,适合统一规范;用户级放在个人配置中,适合个人偏好。两者是否可以叠加、优先级如何,需以官方文档确认。对于多仓库团队,可以把公共规范抽成模板,各仓库按需覆盖。
六、如何核验自定义指令是否生效
在官方文档确认之前,建议用以下检查清单验证:
- 确认文件路径与文件名是否与官方文档一致;
- 在空文件或新文件中让 Copilot 生成一个组件或函数,观察命名、错误处理和目录引用是否符合预期;
- 对比开启与关闭指令文件时的生成差异;
- 检查规则是否写得足够具体,避免模糊描述;
- 如果不符合预期,先确认该机制在当前工具版本中是否受支持,再调整规则写法。
把这件事当成持续维护的工程实践,而不是一次性配置,才能真正降低 AI 生成代码的返工成本。