项目规则是 .trae/rules/ 里的 Markdown。个人规则放在 ~/.trae-cn/user_rules——不要把数据范围写进去,换一台机器或换一个同学就丢了。创建规则时先选定生效方式,TraeCode 会自动改 alwaysApply:始终生效为 true,指定文件生效为 false 并把 globs 填好,多个通配符用逗号分隔,例如 backend/**/*.go。
有三种情况会打开这一页:想让某条约定只在改后端时生效 → 看「四种生效方式与对应字段」,照「指定文件生效」那一行配;规则写了却从没被助手引用 → 走「改完怎么确认它真的生效」的四步;从 Claude Code 或 Cursor 转过来,不知道该写 globs 还是 paths → 看「规则在三个工具里的差别」。
写错最多的是三处,先记住。字段写错不会报错,只是不生效;globs 里的路径相对项目根匹配,写成 *.go 只匹配根目录;规则改完当前这轮对话里还是旧内容,要开一轮新对话再试。还有一条:根上的 AGENTS.md 已经写过的句子,规则里不要再抄一遍。
改 backend/ 下的一个 .go 文件,开一轮新对话,助手会不会主动提到规则里那句 scope_id?
答「不会」,先看 globs 相对项目根能不能匹配到改的那个路径。规则不生效时不会报错,只能靠一次实验确认。
生效方式决定这条规则什么时候进上下文,也就决定它占多少上下文。alwaysApply 不用手写:创建规则时选完生效方式,由 TraeCode 改。四种里本课只用第二种。
| 生效方式 | alwaysApply | 还要填什么 | 什么时候加载 | 本课用它吗 |
|---|---|---|---|---|
| 始终生效 | true | 不填 | 当前项目的每一次对话都加载 | 不用,只有全局性偏好才值得 |
| 指定文件生效 | false | globs,多个通配符用 , 分隔 | 对话里提到匹配的文件时才加载 | 用这个,只对后端或前端成立的约定 |
| 智能生效 | false | 只填 description | 由模型判断相关性 | 不用,它和技能的 description 抢同一件「什么时候想起」的事 |
| 手动触发生效 | false | 不填;对话里用 #Rule 点名 | 点名的那一轮 | 偶尔才翻的长说明用它 |
目录还有两点:.trae/rules/ 下可以再建子目录分类,最多识别 3 层嵌套;只在某个模块生效的规则,也可以直接放在该模块目录下的 .trae/rules/。本课不依赖这两条——要按文件范围生效,就用 globs,路径清楚、一处可见。嵌套层数和字段不用背:建一份规则,跑一遍「改完怎么确认它真的生效」的四步,实测一次就知道了。
三家的目录、扩展名和限定方式都不同。转工具时先看「限定文件范围」这一行:Claude Code 用 paths:,另两家都用 globs:。
| 项 | Claude Code | Cursor | TraeCode |
|---|---|---|---|
| 项目位置 | .claude/rules/,可再分 backend/、frontend/ | .cursor/rules/*.mdc | .trae/rules/*.md |
| 个人位置 | ~/.claude/rules/ | —— | ~/.trae-cn/user_rules |
| 限定文件范围 | 前置元数据 paths:(glob 列表) | globs: 配 alwaysApply: false | alwaysApply: false 配 globs:(逗号分隔多个通配符) |
| 不带范围时 | 每次会话开始就加载,和仓库说明一样占上下文 | alwaysApply: true 时始终生效 | 创建时选定生效方式,由 TraeCode 改 alwaysApply |
| 手动点名 | —— | —— | 对话里用 #Rule 点名 |
只填 description | —— | 不写 globs、也不始终生效的规则,会和技能的 description 抢「什么时候想起」;Cursor 也把这类规则视为可迁到技能 | 同上,本课不用 |
| 篇幅 | —— | 一份规则宜 50 行以内 | —— |
| 改完怎么验证 | —— | —— | 开一轮新对话再试 |
扩展名是最容易漏的一处:Cursor 是 .mdc,另两家是 .md。从 Cursor 转过来,先改这一处。整体对照见TraeCode 总览的七处位置总表。
根上的 AGENTS.md 已经写了数据范围。下面两份只补某一端才会做错的事实,抄的时候不要把根文件再抄一遍。两份都写 alwaysApply: false,靠 globs 决定何时进来。
--- alwaysApply: false globs: backend/**/*.go description: 改 Go 后端时的存储约定 --- 数据库是 MySQL。主键沿用现有脚本,所属范围列名为 scope_id,不要改成 UUID。 上传文件放在 UPLOAD_DIR,文件字节不写入 SQL。 若使用向量库,点的 id 与数据库切片 id 相同,payload 带上 scope_id。 改查询或检索时,测试覆盖两件事:当前所属范围读得到,其他所属范围读不到。 新增列时同步更新 .env.example 里的连接串占位符,不要把口令写进源码或迁移脚本。
--- alwaysApply: false globs: frontend/src/**/*.ts,frontend/src/**/*.tsx description: 改前端页面时的数据来源 --- 只通过后端接口访问数据。 不要在浏览器里直连 MySQL 或 Qdrant。 数据范围来自登录会话,不要用地址栏里的 id 切换范围。 密钥和网关地址不要打进前端包。 接口返回空列表和返回「记录不存在」要用同一套文案,不要让前端靠响应内容区分两者。
规则不生效时不会报错,只能靠一次有针对性的实验来确认。
backend/ 下的一个 .go 文件,或在前端页面里写一个直连数据库的调用。scope_id。没提到,先检查 globs 是否匹配提到的文件路径。#Rule 选中这条规则。点名后才生效、按文件匹配时不生效,问题就在 globs 的写法上,不在规则内容。下面四条覆盖了规则写不对的多数情况。看到现象先对号。
| 现象 | 原因 | 修法 |
|---|---|---|
| 只写了后端才该遵守的约定,改前端时助手也照着做 | 创建时选了「始终生效」,alwaysApply 还是 true | 改成 alwaysApply: false 并填 globs: backend/**/*.go,开一轮新对话 |
globs 填了 *.go,backend/ 下的文件触发不了 | globs 相对项目根匹配,*.go 只匹配根目录下的文件 | 写成 backend/**/*.go;多个范围用逗号分隔,如 backend/**/*.go,shared/**/*.go |
| 规则文件改了,当前这轮对话里助手还是按旧规则 | 历史上下文里还留着改之前的规则 | 开一轮新对话再试,不要在旧对话里继续 |
只填了 description 的规则,有时生效有时不生效,还和技能抢触发 | 「智能生效」由模型判断相关性,和技能 description 判断的是同一件事 | 本课不用智能生效:按文件范围就用 globs,偶尔才翻的用手动 #Rule 点名 |