Claude Code 与 Cursor 的 Skills 对照:同一个名字,两边装的不是同一种东西
你在 .claude/skills/ 下攒了几个 SKILL.md,同事在 Cursor 里也建了 .cursor/skills/,两边文档都写着自己遵循 Agent Skills 开放标准,于是很自然会以为:把文件夹拷过去就行了。
把两边文档摊开逐字对,会发现共享的主要是最外层那层壳——目录里放一个 SKILL.md、顶部一段 YAML frontmatter、模型自己判断什么时候用它。壳之下的三件事——能写哪些字段、文件从哪儿被找到、什么时刻算”可以被调用”——两边划的边界并不一样。这篇只对照两边都白纸黑字写明的部分,有一方查不到的维度直接说不比。
一、定义格式:字段表的交集比你以为的窄
Cursor 官方文档《Agent Skills》页给出的 frontmatter 字段表一共五个字段:name、description、paths、disable-model-invocation、metadata。其中 name 与 description 标注为必填,另外三个可选。该页还写明,旧的 globs 字段仍作为兼容回退被接受,但新技能应该用 paths。
Claude Code 官方文档 code.claude.com/docs/en/skills 的字段表长得多,而且开头就写着一句相反的话:所有字段都是可选的,只有 description 是”推荐”;如果省略 description,Claude Code 会拿 markdown 正文的第一段来顶。
把两张表叠在一起,能同时出现的正好就是 Cursor 那五个。你在 Claude Code 侧用到的 when_to_use、arguments、user-invocable、allowed-tools、disallowed-tools、model、effort、context、agent、background、hooks、shell 等,在 Cursor 的这张表里都查不到对应项。
更容易翻车的是同名字段语义不同这一处:
- Cursor 文档写明,
name是技能标识符,只允许小写字母、数字和连字符,且必须与父文件夹名一致。 - Claude Code 文档写明,在个人技能和项目技能里,
name只决定技能列表中显示的名字,你输入的命令名仍然来自目录名;只有在 plugin 技能里,name才会替换命令的最后一段(插件前缀保留)。
同一个 name,一边是”必须和文件夹对齐的硬标识”,一边是”只影响显示的软标签”。文件搬过去语法上都能过,行为不一定是你想的那个。
还有第二重收窄:分发路径
Claude Code 文档单列了一节说明,本地的 Claude Code 接受上表的每一个字段,但走 claude.ai 技能上传、Skills API、以及 anthropics/skills 仓库里 package_skill.py 打包这三条路时,只能用 Agent Skills 规范的六个字段:name、description、license、compatibility、metadata、allowed-tools。多写一个字段不是被忽略,而是硬报错,文档给出的报错原文是:
Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, name
这六个字段和 Cursor 那五个也不是同一组——paths 与 disable-model-invocation 在 Cursor 表里有、在打包白名单里没有,license、compatibility、allowed-tools 反过来。所以”哪个字段安全”没有单一答案,得先说清你要走哪条路。真正三边都稳的交集只剩 name、description、metadata,想让一份技能同时喂给 Claude Code 本地、Cursor 和 claude.ai 上传,就把流程写进正文,frontmatter 写薄:
---
name: deploy-staging
description: Deploy the application to staging. Use when the user mentions deployment, releases, or environments.
---
以上为按官方文档中的参数语义组合的示例,未经实测,以官方文档与 --help 的实际输出为准。
二、发现机制:一边给的是目录清单,一边给的是覆盖顺序
Cursor 文档列出四个自动加载位置:.agents/skills/、.cursor/skills/(项目级),~/.agents/skills/、~/.cursor/skills/(用户级);此外为了兼容,还会加载 .claude/skills/、.codex/skills/ 以及它们的 ~/ 版本。Claude Code 文档列的是四类来源:企业级(走 managed settings)、个人级 ~/.claude/skills/<skill-name>/SKILL.md、项目级 .claude/skills/<skill-name>/SKILL.md、插件级 <plugin>/skills/<skill-name>/SKILL.md。
两边都收 .claude/skills/(这是 Cursor 侧写明的兼容行为),所以”两边共用一个项目目录”是文档支持的。但重名之后的行为,两边文档详略差得很远。
Claude Code 明确写了一整套同名解析规则:跨层级是企业覆盖个人、个人覆盖项目;任一层级的技能会覆盖同名的 bundled 技能,但不覆盖 bundled 技能的别名(文档的例子是:项目里的 code-review 技能会替换内置的 /code-review,但敲别名 /review 永远不会跑到你那个);plugin 技能走 plugin-name:skill-name 命名空间,不会和别的层级撞;.claude/commands/ 下的文件和技能同名时技能优先。
Cursor 的这两页文档里,我们没有找到同名技能如何解析优先级的说明。这一点没有依据,不比。
顺带说清一件容易混的事:两边都在把 slash 命令往技能上收,收法不同。Claude Code 文档写明自定义命令已并入技能——.claude/commands/deploy.md 和 .claude/skills/deploy/SKILL.md 都产生 /deploy,老的 commands/ 文件继续可用。Cursor 文档写明 2.4 起提供内置的 /migrate-to-skills,把符合条件的动态规则和 slash 命令主动转成技能,slash 命令转出来会带 disable-model-invocation: true 以保留”只手动触发”的行为。
嵌套目录:都有,但”什么时候能用”不一样
Monorepo 里把技能放在子包旁边,两边都支持。
Cursor 文档写明,仓库里任何位置的 .cursor/skills/(或 .agents/skills/)都会被拾取,且嵌套项目目录里的技能自动限定到该目录下的文件——例如 apps/web/.cursor/skills/ 下的 deploy-web 只在 agent 处理 apps/web/ 下的文件时才被呈现,不需要额外设 paths。
Claude Code 这边分两种情况,文档写得很具体:
- 父目录方向:项目技能从你启动 Claude Code 的目录以及它每一级父目录(直到仓库根)的
.claude/skills/加载。在子目录里启动,仍然能拿到根上定义的技能。 - 子目录方向:启动目录之下的嵌套
.claude/skills/启动时不加载。它们在 Claude 第一次读或改该子目录内的文件时才载入,之后本次会话一直可用;在那之前,这些技能不出现在自动补全里,也无法按名调用。
这是本篇最值得记住的一处差异。如果你在 Claude Code 里刚开会话就想敲某个嵌套技能的名字,很可能什么都补不出来——不是配错了,是文档写明的加载时机就是这样。撞名时嵌套技能会用目录限定名,例如 apps/web/.claude/skills/deploy/SKILL.md 对应 /apps/web:deploy,而裸的 /deploy 跑的是项目根那个。
Cursor 的文档里,我们没有找到嵌套技能在会话的哪个时刻进入可调用列表的说明。这一点不比。
三、调用时机:把”谁能调”拆成两个开关
两边的默认行为一致:模型根据 description 自己判断是否相关,你也可以在对话里敲 / 加技能名手动触发。paths 字段两边语义也一致,都是用 glob 限定这个技能只在处理匹配文件时才被呈现。
差别从”要限制”开始。
disable-model-invocation: true 是两边都有的:设了之后模型不再自动应用,只能你显式敲 /skill-name。Claude Code 文档给的用途是有副作用的流程,比如 /commit、/deploy、/send-slack-message——不希望 Claude 因为”代码看着能发了”就自己去部署。
反方向的开关只有 Claude Code 侧有:user-invocable: false 表示只有 Claude 能调,Claude Code 会把它从 / 菜单里藏起来,你敲名字也不跑。文档给的场景是纯背景知识,比如一个讲清楚老系统怎么运作的 legacy-system-context,Claude 该知道,但用户敲 /legacy-system-context 没有意义。Cursor 的这两页文档里没有对应字段,不比。
Claude Code 还多两层不在 SKILL.md 里的控制,遇到”仓库里的技能我不想改文件”时会用到:
skillOverrides设置,给单个技能指定四种状态之一——on、name-only、user-invocable-only、off,分别控制它以什么形式列给 Claude、以及是否出现在/菜单。从 v2.1.199 起,off同时也会把它从 Remote Control 客户端和 Agent SDK 调用方看到的命令列表里隐藏。文档写明插件技能不受skillOverrides影响。- 权限规则层面:
Skill(name)精确匹配、Skill(name *)前缀匹配,也可以直接把Skill放进 deny 规则关掉全部技能。
Cursor 文档里,我们没有找到从设置侧覆盖技能可见性、或用权限规则限制技能调用的对应说明,不比。
反过来 Cursor 有一处 Claude Code 文档里没写的:帮助中心的 Skills 页写明,除了敲 / 运行,还可以敲 @ 选中技能作为上下文附加。Claude Code 文档里没有找到 @ 附加技能的对应说明,不比。
四、三处 Claude Code 写明、Cursor 文档里查不到的机制
这三处不是”谁更强”,而是你如果依赖它们,技能就不再是可搬运的了,心里要有数。
动态上下文注入。 Claude Code 支持在技能正文里写 !`<command>`,命令在技能内容送给 Claude 之前执行,输出替换掉占位符。文档给的例子是用 !`git diff HEAD` 把当前工作区的 diff 直接内联进提示词。几条边界值得记:行内形式只在 ! 位于行首或紧跟空白时才被识别,写成 KEY=!`cmd` 会当字面文本;一条命令失败会中止整次技能调用(不只是它自己那个占位符),Claude 根本看不到这次的技能内容;多行命令要用 ```! 开头的围栏代码块。管理员可以用 disableSkillShellExecution 关掉这一整套。
在 subagent 里跑。 context: fork 让技能在一个隔离上下文里执行,技能正文变成驱动这个 subagent 的提示词,它拿不到你的对话历史;agent 字段决定用哪种 subagent 类型;background 只在 context: fork 下生效,设 false 表示在发起那一轮里等结果,该字段需要 Claude Code v2.1.218 或更高版本。文档还专门警告:context: fork 只对含明确任务的技能有意义,纯规范类内容 fork 出去只会拿到一堆约定却没有可执行的任务。
shell 选择与 Windows。 Claude Code 的 shell 字段决定上面那些注入命令用什么跑,接受 bash(文档写明是默认值,随版本可能变动)或 powershell。这里 Windows 用户要单独看一段:文档写明 PowerShell 工具在 Windows 上没有 Git Bash 时默认开启,其它环境要用 CLAUDE_CODE_USE_POWERSHELL_TOOL=1 打开;而如果技能里写了 shell: bash 但 bash 不可用(文档明说这正是 Windows 上没有 Git Bash 的情形),整次调用在任何命令执行前就直接失败,报错是:
Skill <name> requires bash (`shell: bash` in frontmatter) but Git Bash was not found
Linux 与 macOS 上默认走 Bash 工具,不会撞到这条。所以在 Windows 为主的团队里,往共享仓库提交带注入命令的技能之前,最好先确认组里是不是人人都装了 Git Bash。
Cursor 的这两页文档里,我们没有找到技能正文内联执行 shell、技能在 subagent 里 fork 执行、以及技能内 shell 选择的对应说明,这三项都不比。
五、决策路径
把上面的东西倒过来,从处境出发:
“我只想让一份技能两边都能用。” 只写 name + description,步骤写进正文,别碰 Claude Code 扩展字段;name 与文件夹名保持一致(Cursor 的硬要求,Claude Code 侧不冲突),放在 .claude/skills/ 下——这是两边都写明会加载的位置。
“我在 monorepo 里,技能要跟着子包走。” 两边都支持嵌套目录并自动按目录限定作用范围。要留意 Claude Code 的加载时机:会话刚开时嵌套技能不在补全列表里。希望它一开始就能按名调用,就把它提到项目根的 .claude/skills/,改用 paths 限定作用文件。
“这个技能会部署、会发消息,绝不能让模型自己触发。” 两边都用 disable-model-invocation: true。如果这个 SKILL.md 来自别人的仓库、你不想改文件,Claude Code 侧还能用 skillOverrides 或 Skill(...) 权限规则从外面按住;Cursor 侧我们没有找到对应机制。
“技能跑之前得先抓一份实时状态”或”这是个大流程、不想污染主会话”。 前者对应 !`command`,后者对应 context: fork,都只有 Claude Code 文档写明。用了任意一个,这个技能就基本绑在 Claude Code 上了,Windows 上还得再过 Git Bash 那一关。
最后一句本该提醒的:这两个产品迭代都频繁,字段表、目录清单、版本门槛随时会变,以各自官方文档最新内容为准。真要跨工具共用技能,验证方式是在两边各起一个干净会话确认技能出现在可用列表里,而不是靠”文件放对了”来推断。
本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。
该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现;
我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。
该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。
本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。
本文涉及的另一方内容依据其官方文档整理(Cursor:cursor.com/docs 与 cursor.com/help)。
双方均为闭源商业产品,本文只对照各方公开写明的机制,不推断实现,也不对产品做优劣排名。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。