1. 老项目里写 .cursorrules,为什么越写越乱
给一个跑了五六年的 JSH ERP 老项目配 Cursor,我一开始的想法很朴素:把知道的东西全塞进.cursorrules,让 AI 一次看个够。结果第一版写完 300 多行,AI 反而开始犯迷糊——改个 MyBatis 查询,它顺手把前端 Vue 组件也重构了;让它看jsh-ai-service的接口,它跑去动jshERP-boot的 controller。
问题不在 AI,在规则本身。.cursorrules是每次对话都会注入上下文的文件,你写进去的每一行都在消耗模型的注意力预算。老项目信息密度高、模块多、历史包袱重,全量注入等于让 AI 在噪音里找信号。
这篇就复盘一次完整的.cursorrules书写过程:从规则结构怎么设计,到用 AI 帮你做规则分层,再到通过 TaoToken 统一 Key 管理多模型调用,最后给出可复制的模板和生效验证步骤。适合正在给中大型项目配 Cursor 规则、又不想把规则写成"项目说明书"的开发者。
核心检索词先摆出来:.cursorrules是什么、能做什么、适合谁。它是 Cursor 编辑器读取的项目级规则文件,用来约束 AI 的行为边界、代码风格和验证习惯;适合有明确模块划分、需要 AI 长期协作的工程;不适合把需求文档、接口文档、历史决策全往里塞。
我踩过的第一个坑就是:把"背景知识"和"行为约束"混在一起写。背景知识(比如"这是 Spring Boot 2 + Java 8")AI 不一定每次都需要,但行为约束(比如"controller 保持薄")必须常驻。这两类内容应该分开处理。
2. 规则分层:哪些留 .cursorrules,哪些降级到 .cursor/rules
拿到第一版规则后,我没有直接改,而是先问了大模型一个问题,让它帮我做分类。提问模板是这样的:
以下是我为 JSH ERP 项目写的 .cursorrules 草稿。 请帮我按四类拆分,并说明理由: 1. 必须保留在 .cursorrules.md 的内容 2. 应该降级到 .cursor/rules/*.md 的内容 3. 应该挪到文档库,作为 P3 handle 的内容 4. 应该直接删除的内容模型给出的分类逻辑很清晰,我整理成了一张判断表:
| 判断问题 | 是 → 去向 | 否 → 去向 |
|---|---|---|
| 是否每次任务都必须看到? | .cursorrules | 继续判断 |
| 是否只对某个目录/某类文件生效? | .cursor/rules/*.mdc | 继续判断 |
| 是否只是背景知识,不需要常驻? | 文档库 P3 | 继续判断 |
| 是否已过期、重复、互相矛盾? | 直接删除 | 保留观察 |
按这个逻辑过一遍,原来 300 行的规则被拆成了三块。常驻的.cursorrules只留"改动边界"和"不要改错地方"这类硬约束;模块级的细节(比如jsh-ai-service的 DTO 检查清单)降级到.cursor/rules/;技术栈版本、部署流程这类背景挪到文档库。
这里有个关键点:.cursorrules和.cursor/rules/*.mdc的加载机制不同。前者全局注入,后者可以按 glob 匹配文件路径。所以"只对某个目录生效"的规则,放.mdc里更省上下文。
拆分完之后,还要追问一轮:剩下的文字描述是否合适?我直接把.cursorrules内容贴给模型,问"哪些表述模糊、哪些无法执行、哪些互相冲突"。模型指出"优先做局部修改"太虚,改成"改动前先确认需求属于哪个模块,单次改动不超过两个文件"就可执行多了。
3. 可复制的 .cursorrules 模板与 TaoToken 接入配置
拆分后的.cursorrules我压到了 60 行以内,结构分四块:仓库地图、改动边界、禁区、验证习惯。模板如下,可以直接改项目名复用:
# JSH ERP Agent Guide ## 仓库地图 - jshERP-boot:主 ERP 后端,Spring Boot 2 + Java 8 + MyBatis - jsh-ai-service:AI 服务,Spring Boot 3 + Java 17 + LangChain4j - jshERP-web:前端,Vue 2 + Ant Design Vue ## 改动边界 - 先确认需求属于哪个模块,单次改动不超过两个文件。 - jshERP-boot 中 controller 保持薄,业务逻辑放 service。 - 改 MyBatis 查询时,同时检查 entity、mapper 接口、mapper XML、service 调用链。 - 涉及租户、状态、删除标记、权限过滤的 SQL,修改前先说明影响面。 - jsh-ai-service 通过 HTTP 调用老 ERP,改接口时同步检查 DTO、URL、异常处理。 - jshERP-web 是旧 Vue 2 栈,优先沿用现有结构和接口调用方式。 ## 不要改错地方 - 不要手改 target/、压缩包和其他构建产物。 - 不要提交本地密码、Webhook、API Key 等敏感信息。 - 配置里的敏感值优先改成环境变量占位。 ## 验证习惯 - 每次只做与当前改动最相关的最小验证。 - 改 jsh-ai-service:mvn -f jsh-ai-service/pom.xml test - 改 jshERP-web:npm --prefix jshERP-web run build - 改 jshERP-boot 的 service/controller/mapper/SQL:检查相关接口和映射链路是否闭合。 - 没有运行验证时,必须明确说明。模块级规则拆到.cursor/rules/下,比如jsh-ai-service.mdc:
--- description: jsh-ai-service 模块规则 globs: jsh-ai-service/**/*.java --- - 新增接口必须补 DTO 校验注解。 - 调用老 ERP 的 HTTP 客户端统一走 ErpClient,不要新建 RestTemplate。 - 异常统一抛 BizException,由全局 handler 转换。接下来是 TaoToken 接入。TaoToken 的作用是统一 Key 和 API 通道,让你在 Cursor 里切换模型时不用改一堆配置。官网入口在 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api 。
Cursor 的模型配置走 OpenAI 兼容协议,在设置里填三件套:
{ "openai_api_key": "sk-你的TaoTokenKey", "openai_base_url": "https://taotoken.net/api/v1", "model": "claude-sonnet-4-20250514" }如果你用 Cline 或 Claude Code 这类工具,配置项名称不同但三件套一致:Base URL 填https://taotoken.net/api,Key 填控制台生成的令牌,Model ID 填你要用的模型标识。Key 在控制台的 API Keys 页面生成,地址是 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
注意:Base URL 末尾带不带
/v1取决于客户端实现。Cursor 走 OpenAI 兼容模式时需要/v1,Claude Code 走 Anthropic 协议时用https://taotoken.net/api即可。
4. 验证规则生效:从一次真实请求看结果
规则写完不验证,等于没写。我用的验证方法是:故意给一个模糊需求,看 AI 是否按规则约束行为。
测试用例选的是"给订单列表加一个按状态筛选的功能"。这个需求横跨jshERP-boot的 controller、service、mapper 和jshERP-web的列表页,正好能测出规则有没有拦住"无关扩散"。
第一次请求,AI 的响应里出现了jshERP-web的改动建议。说明"单次改动不超过两个文件"这条约束没生效——检查后发现是我把规则写在了.cursor/rules/里但 glob 没匹配到.vue文件。修正 glob 后重新测试:
globs: jshERP-web/**/*.{vue,js}第二次请求,AI 只动了jshERP-boot的 controller 和 service,并在回复末尾主动说明"mapper XML 未改动,因为筛选逻辑可复用现有查询条件"。这就是规则生效的信号——它不仅约束了行为,还触发了验证习惯里的"说明影响面"。
再验证 TaoToken 通道。在 Cursor 里发一条请求,观察返回:
curl https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的TaoTokenKey" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "回复 OK 两个字母"}] }'正常返回里会有choices[0].message.content字段,值为OK。如果返回 401,说明 Key 无效或没带Bearer前缀;如果返回model not found,说明 Model ID 拼错了。这一步通了,说明 TaoToken 通道和模型映射都正常。
验证模型本身是否可用,可以直接在模型对话页面测:https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。长期做编码和 Agent 任务的话,Coding Plan 更划算,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
5. 常见报错排查:401、local proxy failed、reading choices
配规则和通道的过程中,我遇到过几类典型报错,逐个说清楚。
401 Unauthorized。最常见的原因是 Key 没带Bearer前缀,或者 Key 复制时带了空格。检查Authorization头的格式,正确写法是Bearer sk-xxx,中间一个空格。另一个原因是 Key 被禁用或额度耗尽,去控制台确认状态。
local proxy failed / connection refused。这类报错通常出现在本地客户端(比如 Cline、Continue)配置了错误的 Base URL。检查两点:一是 URL 是否写成了https://taotoken.net/api而不是带/v1的完整路径(取决于客户端);二是本地网络是否能正常访问该域名。如果客户端有"代理"设置项,确认没有开启本地转发。
reading 'choices' of undefined。这个报错说明客户端拿到了响应,但响应结构里没有choices字段。原因通常是:请求发到了错误的端点(比如把 chat 请求发到了 models 端点),或者模型返回了错误对象但客户端没处理。先看原始响应体,如果里面有error字段,按错误信息排查;如果没有,检查请求路径是否为/v1/chat/completions。
OAuth 相关报错。Claude Code 走 Anthropic 协议时,如果配置里混入了 OpenAI 的 OAuth 流程会报错。Claude Code 的正确配置是设置ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY两个环境变量,Base URL 填https://taotoken.net/api,不要走 OAuth 登录流程。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 。
规则不生效。如果 AI 没按.cursorrules约束行为,先确认文件位置对不对——.cursorrules必须在项目根目录,.cursor/rules/*.mdc必须在.cursor/rules/下。其次确认 glob 是否匹配到了目标文件。最后,Cursor 有时需要重启窗口才会重新加载规则文件。
排查顺序建议:先看 HTTP 状态码,再看响应体结构,最后看客户端配置。大部分问题出在配置层,不在模型层。
6. 把规则和通道固定下来,后续只做增量
这套流程跑通之后,我的日常操作变成了:新需求进来,先看.cursorrules里的改动边界,确认属于哪个模块;如果涉及模块细节,Cursor 会自动加载对应的.mdc规则;模型调用统一走 TaoToken 通道,切换模型只改一个 Model ID。
规则文件不是写完就锁死的。每次发现 AI 犯了新错误,就往对应层级补一条约束;每次发现某条规则从没触发过,就考虑删掉或降级。保持.cursorrules精简,比一次性写全更重要。
如果你也在给老项目配 Cursor 规则,建议从最小可用版本开始:先写仓库地图和改动边界,跑一周,观察 AI 在哪些地方越界,再针对性补规则。TaoToken 的 Key 和通道配置一次,后续所有模型调用都复用,省去反复改配置的麻烦。