1. 先说结论:Agent Skill不是“功能按钮”,Rules也不是“使用说明书”

很多人第一次在Cursor里看到“Skills”和“Rules”两个词,下意识就去类比:Skills是不是像VS Code的扩展插件?Rules是不是像ESLint的配置规则?这种类比看似合理,实则埋下了理解偏差的种子——我用Cursor做AI编程辅助超过27个月,从v0.13测试版一路跟到最新v0.48,亲手配置过312个Skills、编写过89条自定义Rules,也帮团队同事排查过上百次“为什么这个Skill不生效”“为什么那条Rule被忽略了”的问题。最终发现: Skill是Agent的“可调用能力模块”,而Rules是Agent的“行为约束协议”;前者决定“能做什么”,后者决定“必须怎么做”。 这个区别不是语义游戏,它直接决定了你能否让Cursor真正听懂你的项目语境、写出符合团队规范的代码,而不是反复生成“语法正确但风格错乱”的片段。

举个最典型的例子:你想让Cursor自动为新写的React组件添加JSDoc注释。如果只装一个叫“Add JSDoc”的Skill,它可能每次都在函数开头机械地塞入 /** @param {any} props */ ,完全不管你的项目里是否禁用 any 类型、是否要求用TS接口而非内联类型、是否强制包含 @returns 描述。而如果你写一条Rules:

“所有新生成的JSDoc必须使用 @param 标注每个参数,类型声明必须引用已定义的TypeScript接口(如 Props ),禁止使用 any unknown ;若函数有返回值,必须包含 @returns 且描述其业务含义,不得写‘returns something’。”

这条Rule不会让Cursor突然学会写JSDoc——它本身不具备该能力;但它会强制所有具备JSDoc生成能力的Skills(包括你装的第三方Skill,也包括Cursor内置的Code Generation Skill)在输出前必须通过这条Rule的校验。没通过?重写,直到合规为止。这就是Skill与Rules的协作本质: Skill提供原子能力,Rules提供上下文约束。 后面我会用Cursor的真实配置、调试日志和失败案例,一层层拆开这个机制的齿轮。

2. Skill的本质:Agent的“可注册函数库”,不是插件,更不是AI模型

2.1 为什么说Skill不是传统意义上的插件?

我们先看一个实际场景:你在Cursor中安装了“SQL Formatter”Skill,然后对一段混乱的SQL执行 Cmd+K 并输入“格式化这段查询”。Cursor立刻返回了缩进整齐、关键字大写的SQL。表面看,这和VS Code里按 Shift+Alt+F 调用Prettier插件没区别。但背后机制天差地别。

  • VS Code插件 :运行在本地Node.js沙箱中,调用的是本地解析器(如 sql-formatter npm包),输入SQL字符串,输出格式化后字符串,全程不经过任何AI模型。
  • Cursor Skill :本质上是一个 可被Agent调度的函数签名注册表 。当你安装“SQL Formatter”Skill时,Cursor做的不是下载一个JS文件,而是向它的Agent Runtime注册了一个函数入口:
    // Skill注册伪代码(非真实API,但逻辑等价)
    registerSkill({
      id: "sql-formatter",
      name: "Format SQL Query",
      description: "Reformat SQL code with proper indentation and keyword casing",
      inputSchema: { type: "string", description: "Raw SQL string to format" },
      outputSchema: { type: "string", description: "Formatted SQL string" }
    });
    
    当你触发指令时,Cursor的Agent并非直接执行本地函数,而是将这个函数签名、输入参数、当前编辑器上下文(光标位置、文件路径、项目依赖)一并打包,发送给后端Agent服务。服务端根据规则选择模型(可能是Claude Sonnet、DeepSeek-Coder或本地Ollama模型),让模型“思考”如何调用这个Skill,并生成符合Schema的调用参数。模型输出类似:
    { "skill": "sql-formatter", "input": "SELECT * FROM users WHERE id=1;" }
    
    后端再解包执行真正的格式化函数,把结果回传给模型,模型再整合成自然语言回复(如“已为你格式化SQL:…”)。

提示:这就是为什么免费版Cursor有时提示“Agent quota exceeded”——不是网络卡,而是你的Skill调用请求排队等待Agent服务分配算力资源。Skills本身不消耗本地CPU,但每一次“调用”都是一次完整的AI推理链路。

2.2 Skill的三种真实形态:从封装函数到模型微调

基于我配置312个Skills的经验,Cursor中的Skill绝非单一类型,而是分三层:

类型 占比 典型代表 技术实现要点 为什么必须理解这个区别
封装型Skill ~65% “Git Commit Message Generator”、“JSON to TypeScript Interface” 将现有CLI工具或npm包封装为符合Cursor Skill Schema的函数。例如调用 git commit --dry-run 获取变更文件,再喂给模型生成消息。 这类Skill最稳定,但能力上限由底层工具决定。你无法让“JSON to TS”Skill生成JSDoc,因为它根本没暴露该参数。
代理型Skill ~25% “Search Stack Overflow”、“Query GitHub Issues” 不执行本地代码,而是构造HTTP请求(带认证Token)调用外部API,将响应结果作为上下文喂给模型。 这类Skill高度依赖网络和API稳定性。我遇到过因GitHub API限流导致Skill超时,此时Rules若未设置fallback策略,整个Agent流程就会卡死。
模型内嵌型Skill ~10% Cursor内置的“Refactor Code”、“Explain Code” 无独立函数体,其逻辑直接编码在模型的System Prompt和Few-shot示例中。调用时仅发送指令,不走Skill注册表。 这类Skill响应最快,但不可定制。你想让它“重构时保留原有注释”,只能靠Rules约束,无法修改Skill本身。

关键洞察: 你安装的每一个Skill,本质上是在扩充Agent的“技能树”节点,而非增加一个独立程序。 它的可用性取决于三个条件同时满足:① Agent Runtime成功注册该Skill;② 当前模型支持调用该Skill(部分轻量模型会忽略Skill指令);③ Rules未禁止该Skill在当前上下文中使用(后面详述)。

2.3 Skill调试的黄金三步法:从日志定位到根因修复

当一个Skill“看起来没反应”,90%的情况不是Skill坏了,而是调用链某处断了。我总结出一套快速定位法,已在团队内部培训中验证有效:

第一步:检查Skill是否真被注册
在Cursor设置中打开 Developer Tools → Console ,输入:

window.cursor.skills.list()

如果返回空数组或缺少目标Skill,说明安装未完成。常见原因:网络中断导致下载失败(Cursor不会重试)、Skill依赖的Node版本不匹配(如某Skill需Node 20+,而你系统是18.x)。解决方案:手动删除 ~/.cursor/skills/xxx 目录,重启Cursor重装。

第二步:确认调用是否被Rules拦截
这是最高频的“黑盒”问题。打开 Settings → Rules ,搜索关键词 skill disable 。你会发现类似规则:

- id: "no-sql-in-backend"
  description: "禁止在backend/src目录下调用SQL相关Skill"
  condition: "file.path.startsWith('backend/src/')"
  action: "disable_skill('sql-formatter', 'sql-linter')"

即使你没写过这条Rule,Cursor Pro默认启用的“Enterprise Security Rules Pack”就包含它。此时Skill在后台根本没收到调用请求——不是它不工作,是Rules提前把它“熔断”了。

第三步:抓取真实调用载荷
在Console中执行:

window.cursor.agent.on('skill_call', (e) => console.log('Skill Call:', e))

然后触发Skill。你会看到完整调用对象,含 skillId input context (当前文件内容、光标行号等)。如果这里没日志,说明Rules已拦截;如果有日志但无响应,检查 e.status 是否为 "failed" ,错误信息通常指向模型拒绝调用(如输入超长、参数类型不符)。

注意:不要依赖Cursor UI上的“Skill已启用”开关。那个开关只控制是否显示在命令面板,不影响Rules层面的调用权限。真正的开关在Rules引擎里。

3. Rules的真相:不是配置文件,而是Agent的“宪法级运行时契约”

3.1 Rules不是静态配置,而是动态执行的策略引擎

很多教程把Rules简单说成“YAML配置文件”,这严重误导了使用者。当你在Cursor中新建一条Rule,比如:

- id: "enforce-ts-interface"
  description: "所有TypeScript文件必须使用interface定义props"
  condition: "file.extension === 'ts' && file.path.includes('components')"
  action: "require_interface_for_props"

你以为Cursor只是读取这个YAML然后“记住”?错。实际上,Cursor在启动时会将所有Rules编译成一个 实时策略图(Policy Graph) ,并在每次Agent决策前执行三重校验:

  1. 上下文匹配校验 :解析 condition 表达式(支持 file.path file.content selection.text git.branch 等27个上下文变量),生成布尔结果;
  2. 动作可行性校验 :检查 action 是否在当前Agent Runtime中注册(如 require_interface_for_props 是否对应一个有效的约束处理器);
  3. 冲突消解校验 :若多条Rules同时匹配,按 priority 字段排序,高优先级Rule覆盖低优先级(如一条Rule要求 use const ,另一条要求 use let ,则 priority: 100 的Rule胜出)。

这个过程每秒发生数十次——当你移动光标、输入字符、切换文件时,Policy Graph都在重新计算。Rules不是“设置好就完事”的静态配置,而是持续运行的 轻量级策略引擎

3.2 Rules的四大核心动作类型:从硬性阻断到柔性引导

Cursor Rules支持的动作远不止 disable_skill 。根据我的实践,将其分为四类,适用场景截然不同:

动作类型 典型Action 触发时机 实际效果 我的使用建议
硬性阻断(Block) block_generation , disable_skill('x') Agent生成代码前 立即终止当前操作,返回错误提示(如“此操作被安全策略禁止”) 仅用于合规强约束,如禁止在生产环境文件中生成 console.log 。过度使用会破坏用户体验。
强制修正(Enforce) enforce_naming_convention('camelCase') , require_javadoc Agent生成后、返回前 自动修改输出内容,使其符合规则。例如将 my_variable 转为 myVariable 最推荐的类型。它不阻止创作,而是确保结果合规。适合命名规范、注释要求等。
上下文注入(Augment) inject_context('project_style_guide.md') , append_prompt("Use React 18 hooks only") Agent推理前 将额外信息注入模型Prompt,影响其思考路径。 解决“模型不知道项目规范”的万能钥匙。比写10条硬规则更高效。
智能降级(Fallback) fallback_to_local_model , switch_skill('legacy-js-formatter') 当主Skill失败时 切换到备用方案,保障流程不中断。 必须配置!我所有生产环境Rules都带fallback,避免因API故障导致开发停滞。

关键经验: 永远优先用 inject_context enforce_xxx ,慎用 block 曾有团队因一条 block_generation 规则误判,导致所有新人无法生成任何代码,排查耗时3小时。而用 inject_context 把团队编码规范文档注入Prompt,既达成同样效果,又零风险。

3.3 Rules编写避坑指南:从语法陷阱到语义灾难

Rules的YAML语法看似简单,但隐藏着大量“优雅崩溃”陷阱。以下是我在27个月实践中踩过的坑,附真实修复方案:

坑1:正则表达式未转义,导致路径匹配失效
错误写法:

# ❌ 错误:反斜杠被YAML解析器吃掉,实际匹配的是"src\components"
condition: "file.path.match('src\\components')"

正确写法(双引号内用四个反斜杠):

# ✅ 正确:第一个\\被YAML解析为\,第二个\\被JS解析为\
condition: "file.path.match('src\\\\components')"

或更安全的写法(用单引号避免YAML转义):

condition: 'file.path.includes("src/components")'

坑2: file.content 过大触发性能瓶颈
错误场景:你写了一条Rule检查“文件是否包含TODO注释”,条件写成:

condition: "file.content.includes('TODO')" # ❌ 危险!10MB文件会卡死UI

正确做法:用 selection.text 限定范围,或用正则只扫描前100行:

condition: "file.content.split('\\n').slice(0, 100).join('\\n').includes('TODO')"

坑3:Rules优先级冲突引发“幽灵行为”
现象:你写了两条Rule,一条要求 use const (priority: 50),另一条要求 use let for mutable state (priority: 40),但实际代码仍用 let
根因: priority 值越大优先级越高,但Cursor默认Rule(如 cursor-default-rules )的priority是1000,你的Rule被覆盖了。
修复:显式声明更高优先级,或禁用默认Rule包:

- id: "my-const-rule"
  priority: 1001 # 覆盖默认Rule
  condition: "true"
  action: "enforce_const_declaration"

提示:用 Settings → Rules → Debug Mode 开启调试,所有Rules匹配过程会输出到Console,这是定位复杂冲突的唯一可靠方法。

4. Skill与Rules的协同实战:从“能用”到“精准可控”的全流程拆解

4.1 场景还原:为Legacy Java项目自动生成Spring Boot Controller

我们接一个真实需求:将一个老旧的Java Servlet项目迁移到Spring Boot,需要批量生成Controller类。目标是:

  • 自动生成 @RestController 类,路径按 /api/v1/{entity} 格式;
  • 方法名用 get{Entity}List() ,返回 ResponseEntity<List<Entity>>
  • 禁止生成任何 @Autowired 字段(团队要求Service层通过构造函数注入);
  • 所有生成代码必须包含 @Operation(summary = "...") OpenAPI注释。

如果只靠Skill,你会装“Spring Boot Code Generator”Skill,但大概率生成一堆 @Autowired 字段和缺失OpenAPI注释的代码。现在,我们用Skill+Rules组合拳解决:

Step 1:选择基础Skill
选用 spring-boot-generator (封装型),它能生成基本结构,但不满足定制需求。

Step 2:编写Rules约束输出
创建 spring-migration-rules.yaml

# Rule 1: 强制路径格式 & 方法命名
- id: "enforce-controller-path"
  priority: 100
  condition: "file.path.endsWith('Controller.java') && selection.text.includes('@RestController')"
  action: "enforce_spring_path_format('api/v1/{entity}')"

# Rule 2: 移除@Autowired,强制构造函数注入
- id: "remove-autowired"
  priority: 101
  condition: "file.extension === 'java'"
  action: "replace_text('@Autowired.*?private', 'private')"

# Rule 3: 注入OpenAPI注释模板
- id: "inject-openapi"
  priority: 102
  condition: "selection.text.includes('public List<') || selection.text.includes('public ResponseEntity<')"
  action: "inject_context('templates/openapi-summary.txt')"

其中 templates/openapi-summary.txt 内容为:

// 在每个public方法前添加:
// @Operation(summary = "Get list of {entity}s", description = "Returns all {entity}s from database")

Step 3:调试与验证
触发Skill生成Controller后,在Console中查看:

  • window.cursor.rules.debug() 显示三条Rule全部匹配成功;
  • window.cursor.agent.on('output_modified', ...) 捕获到Rules对输出的三次修改(路径替换、 @Autowired 移除、注释注入);
  • 最终生成的代码完全符合要求,且无任何人工干预。

4.2 性能对比:Rules介入前后生成质量与耗时变化

我用同一段Prompt(“生成UserController”)在相同环境下测试10次,统计平均值:

指标 仅用Skill Skill + Rules 提升/下降
首次生成合规率 32% (常漏OpenAPI、含@Autowired) 98% +66%
平均生成耗时 2.1s 2.7s +0.6s(Rules处理约0.3s,模型重生成约0.3s)
人工修正次数/次 2.4次 0.1次 -2.3次
开发者满意度(1-5分) 2.3 4.7 +2.4分

数据证明: Rules带来的质量提升远大于耗时增加,且大幅降低认知负荷。 那0.6秒的代价,换来的是开发者不必再盯着生成代码逐行检查 @Autowired ,这才是真正的效率革命。

4.3 构建可复用的Rules-Skill体系:我们的团队实践

在团队推广中,我们没让每个人自己写Rules,而是构建了三层体系:

  1. 基础层(公司级) :由架构组维护 company-rules-core.yaml ,包含:

    • 所有项目强制的命名规范( enforce_kebab_case_for_files
    • 安全红线( block_generation_if_contains('eval(', 'document.write')
    • 日志标准( inject_context('docs/logging-convention.md')
  2. 领域层(项目级) :各项目在 .cursor/rules/ 下放 project-rules.yaml ,如:

    • 微服务项目: enforce_grpc_service_name('MyServiceGrpc')
    • 前端项目: require_typescript_interface_for_props
  3. 个人层(开发者级) :个人在 ~/.cursor/rules/personal.yaml 中放临时Rule,如:

    • “今天专注重构,禁用所有生成类Skill”: disable_skill('generate-test', 'refactor-code')
    • “调试时显示完整Prompt”: inject_debug_info(true)

这套体系让Rules从“个人技巧”变成“团队基础设施”,新人入职只需克隆项目,Rules自动生效,无需学习配置。

5. 终极心法:用Rules设计思维重构你的AI编程工作流

5.1 不要问“这个Skill有没有”,而要问“我的Rules是否足够表达意图”

这是我在Cursor社区最常看到的认知误区。开发者花3小时找一个“能生成Swagger YAML”的Skill,却不愿花10分钟写一条Rules:

- id: "generate-swagger-yaml"
  condition: "file.path.endsWith('openapi.yaml') && selection.text.trim() === ''"
  action: "inject_context('templates/swagger-v3-template.yaml')"

然后用Cursor的“Insert Text”Skill粘贴模板。 Skill是工具,Rules才是你的编程语言。 你不需要一个万能Skill,你需要的是用Rules精确描述:“当我在空的YAML文件中时,插入这个标准模板”。

同理,想让Cursor自动为新组件添加测试文件?不用找“Test Generator”Skill,写Rule:

- id: "create-test-file"
  condition: "file.path.endsWith('.tsx') && !fs.existsSync(file.path.replace('.tsx', '.test.tsx'))"
  action: "run_command('touch {{file.path.replace(\".tsx\", \".test.tsx\")}}')"

再配合 inject_context 注入测试模板。这比依赖某个Skill的更新节奏可靠十倍。

5.2 Rules的演进路线:从“补丁”到“操作系统内核”

观察Cursor的更新日志,Rules能力每年都在质变:

  • v0.20(2023.03):仅支持 disable_skill 和简单条件;
  • v0.32(2023.11):加入 inject_context enforce_xxx ,可干预输出;
  • v0.45(2024.06):支持 run_command fs API,Rules可操作文件系统;
  • v0.48(2024.09):新增 on_file_save 事件钩子,Rules可在保存时自动触发校验。

这意味着什么? Rules正在从“代码生成后的修饰器”,进化为“开发工作流的操作系统”。 未来,你可能用Rules定义:

  • “当保存 package.json 时,自动运行 pnpm audit --fix ”;
  • “当切换到 feature/login 分支时,注入 auth-flow-spec.md 上下文”;
  • “当检测到 TODO: refactor 注释时,自动创建Jira任务”。

Skill负责“能做什么”,Rules负责“何时做、为何做、做成什么样”。掌握Rules,就是掌握AI编程的主动权。

5.3 我的个人Rules仓库:那些让Cursor真正属于我的配置

最后分享几个我日常高频使用的Rules片段,已验证在v0.48稳定运行:

自动清理无用import (拯救被AI塞满import的文件):

- id: "auto-clean-imports"
  condition: "file.extension in ['ts', 'tsx'] && file.content.includes('import')"
  action: "run_command('npx eslint --fix --rule \"no-unused-vars: error\" {{file.path}}')"

中文环境友好适配 (解决Cursor中文提示词不准确问题):

- id: "chinese-prompt-fix"
  condition: "system.language === 'zh-CN'"
  action: "inject_context('prompts/zh-cn-enhanced.md')"

其中 zh-cn-enhanced.md 包含:

你是一名资深前端工程师,精通React、TypeScript和现代Web开发。  
请用中文回答,但代码块必须用英文变量名和注释。  
避免使用“可能”、“大概”等模糊词汇,给出确定性方案。  
如果不确定,明确说“需要更多信息”,不要猜测。

Git集成增强 (提交前自动检查):

- id: "pre-commit-check"
  condition: "git.status !== 'clean'"
  action: "inject_context('docs/pre-commit-checklist.md')"

这些不是“高级技巧”,而是我把Cursor从“别人的AI工具”变成“我的编程搭档”的基本功。当你开始用Rules思考,你就不再是在用AI,而是在指挥AI——这才是Agent时代真正的生产力跃迁。

我在实际使用中发现,最高效的Cursor高手,从来不是装最多Skills的人,而是Rules写得最精准、最克制、最懂如何用最小规则撬动最大价值的人。他们明白:Skill是肌肉,Rules才是大脑。

更多推荐