Cursor 配置分 Rules、Hooks、Skills、Agents、MCP 五层,各层环环相扣;跳过底层会导致上层泄漏,实战验证有效。
大约有六个月时间,我的 Cursor 配置方式跟大多数人一样。打开设置,粘贴几条规则,然后就开始工作。结果每次会话开始时,还是得重新解释一遍项目情况。
我以为是规则不够好,不断重写它们。问题不在这里。
真正的问题是:规则只是五层配置中的一层,其他四层都在闲置。
上周我在一个生产级 Go 代码库上把五层配置都搭好了——这个项目叫 PortfolioPulse,是一项服务,会在开盘和收盘时拉取 Trading212 的持仓数据,在 Upstash Redis 中保留滚动快照,并把历史数据持久化到 Airtable。真实的基础设施、真实的凭证、权限配错会有真实的后果。
关于这五层的顺序及其原因,我有了新的理解,这个顺序不是随意排列的菜单。
Rules → hooks → skills → agents → MCP。
每一层都依赖前一层的存在:
规则约束写入的内容。Hook 在提交时强制执行规则在写入时所要求的内容。Skill 是你主动调用的工作流。Agent 负责一项任务并携带自己的权限。MCP 则是它们访问编辑器外部任何事物的通道。
跳过某一层,它上面那一层就会泄漏。没有规则的 Agent 生成的代码违反代码约定的速度比你审查的速度还快。有规则没有 hook,规则就只是建议。Skill 没有作用域控制就会变成规则,频繁触发,最终被忽略。
我犯了好几个月的错误是把规则写成了一份愿望清单。"写出整洁代码。""妥善处理错误。"都是不可执行、人人可以忽略的东西。
有效的是那些狭窄且可检查的规则。在这个代码库中,规则这样写道:依赖方向必须保持稳定——domain 层绝不导入 infrastructure 层。错误需要携带操作上下文进行包装。不允许静默丢弃错误。HTTP 客户端必须声明显式超时。瞬态的 5xx 错误在浮现之前恰好重试一次。
规则的形式部分跟内容一样重要。规则文件位于 .cursor/rules/ 目录下,以 .mdc 为扩展名,YAML frontmatter 决定它们何时加载:
---
description: "Go API design and error handling"
globs: infrastructure/**/*.go, domain/**/*.go
alwaysApply: false
---
带有 glob 的规则仅在匹配的文件进入上下文时才加载。没有 glob 的规则会应用到每一次会话中。
最后这个细节值得真正理解,它直接来自 Cursor 官方文档:没有 glob 模式的规则会无差别地应用到所有会话中。十条没有作用域的规则,就是十条规则的信息在一次讨论 CSS 的对话中被白白消耗。
Cursor 的文档在"规则里不应该放什么"这一点上也非常直接。不要把样式指南复制进去——用 linter,模型本身已经知道这些约定。引用文件而不是粘贴其内容,这样规则文件才能保持简短,而且不会在代码迁移后变得过时。
关于视频的一处纠正:我在几处提到了 .cursorrules,这是旧路径,已经废弃。请使用 .cursor/rules/*.mdc。该目录下的 .md 文件会因扩展名错误而被完全忽略,这会让人白白浪费二十分钟。
模型可以口头忽略一条规则,但它无法忽视一个失败的 pre-commit hook。
规则是上下文。好的上下文,模型通常会遵循。但"通常"这个词在句中承担了太多重量,而且失败是静默的——你只有在 review 时,甚至更晚,才会发现某条规则被跳过了。
所以规则之上是确定性的强制执行层。在这个代码库中,那就是在提交之前运行 commit-message 格式检查、go vet、golangci-lint 和 gofmt,任何东西在落地之前都必须通过这些检查。规则描述标准,hook 让标准不可商量。
值得注意的是 Cursor 也有自己的 hook 系统,与 git hooks 独立——这是 1.7 版本引入的 agent 生命周期 hook,配置在 .cursor/hooks.json 中,在 beforeShellExecution、afterFileEdit、beforeMCPExecution 和 stop 等事件上触发。机制不同,原则一致,而且可以很好地组合。
Semgrep 用更好的方式阐述了这个观点,谈及他们自己的 hooks 集成:像 MCP 这样的协议让安全工具对 AI 可用,但无法确保它们真的被使用。基础检查不能依赖一个随机的系统去记住要运行它们。这一句话就是这个层面的全部论点。
他们的模式也值得借鉴——afterFileEdit 记录哪些文件发生了变化,stop hook 对它们进行扫描,agent 会重新生成直到问题清零。这是一个自我修正的循环,而不是一道关卡。
Skill 是你主动调用的工作流。我的 skill 包括:一段代码巡检,解释一个 Go 文件在做什么而不是它写了什么;一个 domain-model 一致性检查;还有一个 Airtable schema 引用。
它们与规则分开的理由正是重点所在。规则是环境式的——始终被考虑。Skill 是被调用的。把一个可选的工作流放进规则,它就会在每次会话中触发,增加噪音,最终训练你忽略规则文件。我之前就是这么做的,后来才拆分开。
我现在用的测试方法是:我想让这条规则在每个 prompt 中都被考虑吗?如果不是,那就是 skill。

Airtable 那个是最清晰的例子。列名、字段类型、schema 约定、应该使用哪些 MCP 工具。在操作那个集成时极其有用,其他百分之九十的时间就是纯粹的噪音。
一个能做所有事情的 Agent 不过是换了皮的助手。价值完全在作用域里。
这里有两个 agent。ai-broker 回答关于 Trading212 实时状态的问题——当前持仓、数量、盈亏——它是只读的。它有 Bash、Read、Grep 和 Glob 权限,明确拒绝订单和持仓变更类接口。data-agent 处理 Airtable 和 Redis,同样只读,负责所有历史和缓存数据,让 broker agent 专注于当下。
只读约束不是为了谨慎而谨慎。这个 agent 持有真实券商账户的凭证。一条被误读 prompt 的爆炸半径是真实的金钱。限定作用域就是安全模型。
把实时数据和历史数据分开也消除了一种真实的失败场景:一个 agent 试图用实时持仓接口回答"上周我持有什么?"——而那个接口根本不知道上周是什么。
MCP 是各层访问编辑器外部事物的通道。四个服务器:Upstash Redis 用于快照、一个文件系统服务器、一个用于文档的 llms-txt 服务器,还有 Hugging Face 用于模型访问。
{
"mcpServers": {
"upstash-redis": {
"command": "npx",
"args": ["@upstash/mcp-server"],
"env": {
"UPSTASH_REDIS_REST_URL": "...",
"UPSTASH_REDIS_REST_TOKEN": "..."
}
}
}
}
连接 Hugging Face 需要一个正常的 OAuth 流程,之后我就可以在编辑器内浏览模型,挑选适合这个应用的那个——用 ProsusAI/finbert 对金融新闻情绪进行分类后再存储评论,用 Qwen2.5-3B-Instruct 来总结持仓情况。
你也可以用同样的方式连接很多其他市场服务器的模型——Figma、Google Drive、Airtable 等等。
不要一次性把五层都搭完。先把规则做好,用真正的 glob 让它们只在相关时加载。然后加上 hook,让规则不再是建议。这能以一小部分工作换来大部分价值,而且把这两层搭好之后,其他三层的样子就显而易见了。
完整讲解视频,大约十八分钟:https://youtu.be/TPXbwLNi9jA
代码:https://github.com/Mozes721/PortfolioPulse
如果你有运行时间比我更长的分层配置,我想知道哪一层先出问题。