1. 为什么我把 Skills 清单当成 Cursor 里的“第二大脑”
在 Cursor 里写 React + Next.js + shadcn 项目,最耗神的往往不是写组件本身,而是每次都要重复交代同一套上下文:这个项目用 App Router 还是 Pages Router、组件放components/ui还是components/shared、样式走 Tailwind 还是 CSS Modules、表单用 react-hook-form 还是受控组件。你每次开新对话,模型都像失忆一样从头问起,或者更糟——它不问,直接按自己的默认习惯生成一堆和你项目风格冲突的代码。
Skills 解决的正是这个问题。你可以把它理解成给 Cursor 挂载的“技能包”:每个 Skill 是一段被结构化描述的能力说明,包含触发条件、执行步骤和约束。当你在对话里提到 shadcn、components.json、React 性能优化这些关键词时,Cursor 会自动匹配到对应 Skill,按里面写好的流程来干活,而不是自由发挥。它和 Rules 的区别在于,Rules 更像全局静态约束,Skills 更偏向“按需调用的操作手册”。
这套东西适合谁?如果你满足下面任意一条,就值得花半小时整理:一是同时维护两三个 Next.js 项目,每个项目组件规范还不一样;二是团队里有人写 shadcn 有人手写组件,风格飘忽;三是你经常让 Cursor 生成组件,但生成完还要手动改半天命名和目录。我试过把常用技能沉淀成一份清单后,最直观的变化是:同一个“生成一个带校验的登录表单”的指令,以前要来回三轮,现在基本一次到位。
这篇会按“清单结构 → 安装配置 → 在 Cursor 里触发一次组件生成与校验 → 排错”的顺序走,中间会给出可直接复制的目录结构和配置片段。核心检索词就三个:Skills 清单怎么整理、Cursor 里怎么调用、React/Next.js/shadcn 组件开发怎么串成一条工作流。你不需要先懂 Skills 的底层实现,跟着配一遍就能用起来。
2. Skills 目录结构与 Cursor 识别机制:清单怎么放才不白装
很多人装完 Skill 发现 Cursor 没反应,九成是目录放错或者没加全局参数。先把结构讲清楚,后面配置才不会踩坑。
Skills 在本地一般落在用户目录下的.cursor/skills或者通过npx skills管理的全局目录里。全局安装的意义在于,Cursor 启动时会扫描这个固定路径,把每个 Skill 的SKILL.md读进上下文索引。如果你只装在项目里,换个项目就失效,所以清单类技能一律走全局。
一个可维护的清单,我建议按“领域 + 触发词”两层来组织,而不是按安装顺序堆在一起。下面是我自己用的目录结构,你可以直接照抄:
~/.cursor/skills/ ├── frontend/ │ ├── react-best-practices/ │ │ └── SKILL.md │ ├── composition-patterns/ │ │ └── SKILL.md │ └── shadcn/ │ └── SKILL.md ├── quality/ │ ├── requesting-code-review/ │ │ └── SKILL.md │ ├── systematic-debugging/ │ │ └── SKILL.md │ └── webapp-testing/ │ └── SKILL.md ├── planning/ │ ├── brainstorming/ │ │ └── SKILL.md │ └── writing-plans/ │ └── SKILL.md └── registry.jsonregistry.json是我自己加的一层索引,用来记录每个 Skill 的触发词和适用项目,方便快速查。它不是 Cursor 必需的,但对“清单管理”很有用,内容大概长这样:
{ "skills": [ { "name": "shadcn", "path": "frontend/shadcn", "triggers": ["shadcn", "components.json", "ui 组件", "样式组合"], "scope": "nextjs-app-router" }, { "name": "react-best-practices", "path": "frontend/react-best-practices", "triggers": ["React 性能", "重渲染", "useMemo", "组件重构"], "scope": "react-nextjs" }, { "name": "requesting-code-review", "path": "quality/requesting-code-review", "triggers": ["review", "合并前检查", "回归风险"], "scope": "all" } ] }安装命令这块必须强调参数。社区技能用npx skills管理,安装时-g不能省,否则 Cursor 扫不到;装完必须重启 Cursor,热加载不生效。以 shadcn 和 React 最佳实践为例:
# 搜索社区技能 npx skills find shadcn # 全局安装,-y 跳过确认,-g 全局 npx --registry=https://registry.npmjs.org -y skills add vercel-labs/agent-skills@shadcn -g -y npx --registry=https://registry.npmjs.org -y skills add vercel-labs/agent-skills@react-best-practices -g -y # 查看已安装 npx skills list -g # 检查并更新 npx skills check npx skills update清单整理的一个实用技巧:给每个 Skill 在SKILL.md顶部补一行“本项目适用条件”。比如 shadcn 这个 Skill,我会写“仅当项目根目录存在 components.json 时启用”。这样当你在一个没用 shadcn 的老项目里提到“组件”,它不会误触发。Cursor 读取时会把这行当作前置判断,减少误匹配。
还有一点,清单不要贪多。我一开始装了二十多个,结果触发词互相打架,生成组件时同时命中三四个 Skill,输出反而混乱。后来砍到十个以内,按“前端开发、质量保障、计划拆解”三组保留,命中率明显提升。低频的比如 React Native 相关、站点审计类,可以留着但不放进主清单,需要时再手动提。
3. 可复制配置:把 React、Next.js、shadcn 串成一条工作流
这一节给可直接落地的配置片段。目标很明确:在 Cursor 里说一句“帮我生成一个用户资料卡片组件”,它能自动走 shadcn 的组件规范、React 的性能约束、Next.js 的目录约定,生成后还能触发一次校验。
先配 Cursor 的项目级规则,放在项目根目录.cursor/rules下。这个文件负责告诉 Cursor 当前项目的技术栈基线,和 Skills 配合使用:
{ "rules": { "framework": "nextjs", "router": "app", "styling": "tailwind", "uiLibrary": "shadcn", "componentDir": "components", "uiDir": "components/ui", "sharedDir": "components/shared", "typescript": true, "importAlias": "@/*" } }然后是 shadcn 的components.json,这个文件决定了 shadcn Skill 能不能正确识别你的组件路径和别名。路径和字段名要和项目实际一致,否则 Skill 会按默认值生成到错误目录:
{ "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": true, "tsx": true, "tailwind": { "config": "tailwind.config.ts", "css": "app/globals.css", "baseColor": "zinc", "cssVariables": true }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "hooks": "@/hooks" } }如果你用 TaoToken 作为模型接入层,Cursor 的模型配置可以指向它的 API 地址,这样 Skills 触发的请求走统一入口,方便排查。配置片段如下,Base URL 用https://taotoken.net/api,Key 在控制台生成:
{ "models": [ { "name": "claude-sonnet", "provider": "openai-compatible", "baseUrl": "https://taotoken.net/api", "apiKey": "sk-你的Key", "modelId": "claude-sonnet-4-5" } ] }这里三件套要写全:Base URL、Key、Model ID。少任何一个都会在请求时报 401 或者 model not found。Key 的生成入口在控制台的 API Keys 页面,接入细节可以对照官方文档,地址是https://taotoken.net/api-keys和https://taotoken.net/doc。
配置完成后,工作流的触发逻辑是这样的:你在 Cursor 对话里输入“用 shadcn 生成一个 UserProfileCard,放在 components/shared,带 loading 和 error 状态”。Cursor 先读项目规则确认技术栈,再匹配 shadcn Skill 拿到组件生成规范,同时命中 react-best-practices 拿到性能约束(比如避免在渲染中创建新对象、memo 的使用边界),最后按 Next.js App Router 的约定决定是否加"use client"。
为了让校验也能自动串进来,我在清单里把requesting-code-review的触发词设成“生成后检查、review、合并前”。这样生成完组件,我补一句“按 review 流程检查一下”,它就会走代码评审 Skill,输出风险点和测试缺口。整条链路不需要手动切换工具,全在对话里完成。
4. 验证请求:在 Cursor 里跑一次组件生成与校验
配置对不对,跑一次就知道。下面是我实际用的验证步骤,你可以照着走一遍。
第一步,确认 Skills 被识别。重启 Cursor 后,在对话里输入“列出当前可用的 skills”。如果配置正确,它会返回你安装的清单,包含 shadcn、react-best-practices 等。如果返回空,先回去检查-g参数和重启这两步。
第二步,发一条完整的组件生成指令。我用的原文是:
用 shadcn 生成一个 UserProfileCard 组件,放在 components/shared 下。 要求:接收 name、avatarUrl、bio 三个 props;有 loading 和 error 两种状态; 用 Card、Avatar、Skeleton 这些 shadcn 组件组合;TypeScript 严格类型; 按 Next.js App Router 约定处理客户端边界。第三步,观察输出。正常情况下它会生成类似下面的文件,路径和命名都符合components.json里的别名:
"use client"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Skeleton } from "@/components/ui/skeleton"; type UserProfileCardProps = { name?: string; avatarUrl?: string; bio?: string; loading?: boolean; error?: string | null; }; export function UserProfileCard({ name, avatarUrl, bio, loading = false, error = null, }: UserProfileCardProps) { if (loading) { return ( <Card> <CardHeader> <Skeleton className="h-12 w-12 rounded-full" /> </CardHeader> <CardContent className="space-y-2"> <Skeleton className="h-4 w-32" /> <Skeleton className="h-4 w-48" /> </CardContent> </Card> ); } if (error) { return ( <Card> <CardContent className="py-6 text-sm text-destructive"> {error} </CardContent> </Card> ); } return ( <Card> <CardHeader className="flex flex-row items-center gap-4"> <Avatar> <AvatarImage src={avatarUrl} alt={name ?? "user"} /> <AvatarFallback>{name?.slice(0, 1) ?? "U"}</AvatarFallback> </Avatar> <div> <p className="font-medium">{name}</p> <p className="text-sm text-muted-foreground">{bio}</p> </div> </CardHeader> </Card> ); }第四步,触发校验。紧接着输入“按 review 流程检查这个组件”。它会走requesting-code-reviewSkill,输出类似:缺少 error 状态的类型收窄、loading 时未保留布局高度可能导致抖动、建议给 AvatarImage 加 fallback 超时。这些就是 Skill 带来的结构化检查,比你自己想更全。
第五步,验证请求链路。如果你接了 TaoToken,可以在控制台的请求日志里看到这次对话的调用记录,确认 Base URL 和 Model ID 生效。这一步能帮你区分“是 Skill 没触发”还是“是模型请求失败”。
整个验证过程大概五分钟。跑通一次后,你就有了一个可复用的模板:以后新项目只要复制.cursor/rules和components.json,Skills 清单不用动,直接就能用。
5. 常见报错排查:401、local proxy failed、reading choices 怎么解
这一节按真实报错来。下面这几个是我和身边人踩过的,对照着查基本能定位。
401 Unauthorized。这个最常见,出现在模型请求层。原因通常是 Key 没填、填错、或者 Base URL 和 Key 不匹配。排查顺序:先确认apiKey字段是不是完整的sk-开头字符串,没有多余空格;再确认baseUrl是https://taotoken.net/api,不要多加/v1或者结尾斜杠;最后去控制台看这个 Key 是否被禁用或额度耗尽。如果三件套里 Model ID 写错,有时也会返回 401 而不是 404,所以顺手核对一下模型名。
local proxy failed。这个报错一般和 Cursor 的网络配置有关,不是 Skill 本身的问题。先检查 Cursor 设置里有没有开自定义代理,如果有,关掉再试。然后确认本机能不能正常访问https://taotoken.net/api,用 curl 测一下:
curl -X POST https://taotoken.net/api/v1/chat/completions \ -H "Authorization: Bearer sk-你的Key" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-5","messages":[{"role":"user","content":"ping"}]}'如果 curl 通但 Cursor 不通,多半是 Cursor 的配置缓存没刷新,重启一次。如果 curl 也不通,检查系统时间是否准确,时间偏差过大会导致 TLS 握手失败。
reading 'choices' of undefined。这个报错说明请求发出去了,但返回结构不是预期的 OpenAI 兼容格式。常见原因是 Base URL 指向了错误的端点,比如指向了网页地址而不是 API 地址。确认baseUrl是https://taotoken.net/api,请求路径由客户端自动补/v1/chat/completions。另一个原因是 Model ID 写成了不存在的模型,返回了错误对象,客户端却按成功结构去读choices。去模型对话页面确认可用模型名,再回填。
OAuth 相关报错。如果你用的是 Claude Code 或者带 OAuth 的客户端,报错里出现 token expired、invalid grant 这类词,说明授权过期。重新走一次授权流程即可。注意 OAuth 和 API Key 是两套体系,不要混用。Claude Code 的接入配置里,Base URL 同样填https://taotoken.net/api,Key 用 API Keys 页面生成的,Model ID 按文档填。
Skill 装了但没触发。这个不算报错,但很常见。排查三步:一是npx skills list -g确认装上了;二是重启 Cursor;三是检查触发词是否被其他 Skill 抢占。如果两个 Skill 触发词重叠,Cursor 可能只选一个。解决办法是在SKILL.md里把触发条件写得更具体,比如把“组件”改成“shadcn 组件生成”。
生成到错误目录。这是components.json的 aliases 和项目实际路径不一致导致的。检查ui、components、utils三个别名是否指向真实存在的目录。如果项目用的是src/components,别名就要写成@/src/components或者对应的 tsconfig paths。
6. 把清单用起来:从模型对话到长期编码的接入路径
清单整理完,接下来是让它真正进入日常。我的做法是分三层:临时验证走模型对话,日常组件开发走 Cursor + Skills,长期项目沉淀走 Coding Plan。
临时想验证某个 Skill 的效果,或者只是想快速问一句“这个组件该怎么拆”,用模型对话最轻。地址是https://taotoken.net/chat,不用配本地环境,直接开聊。适合在没打开 Cursor 的时候快速确认思路。
日常开发就是这篇讲的主线:Cursor 里挂 Skills 清单,配好.cursor/rules和components.json,用触发词调用。组件生成、代码评审、调试定位都在对话里完成。如果你还没配 Key,先去 API Keys 页面生成一个,地址是https://taotoken.net/api-keys,然后按文档里的接入说明填到 Cursor 配置里,文档在https://taotoken.net/doc。
长期项目、Agent 类任务、需要持续跑多轮编码的场景,用 Coding Plan 更合适。它的计费和额度模型偏向长会话,地址是https://taotoken.net/coding-plan。我一般把需要连续改多个文件、跑测试、迭代组件的任务放这边,避免按次计费带来的心理负担。
如果你用 Claude Code,接入配置单独走一份,地址是https://taotoken.net/claude-code。配置里同样是 Base URL + Key + Model ID 三件套,Base URL 填https://taotoken.net/api。
最后说一个实用技巧:清单不是一次整理完就锁死的。我每个月会看一次npx skills check的输出,把更新了的 Skill 过一遍变更说明,触发词有变化的同步改registry.json。低频的 Skill 不删,但从主清单挪到归档目录,需要时再挂回来。这样清单始终保持在十个以内的高命中状态,Cursor 的响应也更稳。