Cursor Agent 端到端开发实战
Cursor 是大多数开发者接触 AI 编程的第一个工具。前面章节讲了 Rules 和 Prompt 的理论,本章进入实战——用 Cursor 的 Agent 模式完成 AI 视频平台的真实开发任务:从简单的组件生成到跨文件重构,从 Bug 修复到完整功能实现。每个案例都展示完整的操作流程、Prompt 写法、Agent 的执行过程,以及需要人工介入的环节。
1. Cursor Agent 工作模式
1.1 三种交互模式
| 模式 | 快捷键 | 适合场景 | 自主程度 |
|---|---|---|---|
| Tab 补全 | Tab | 写代码时的实时补全 | 最低,逐行确认 |
| Cmd+K 内联 | Cmd+K | 局部修改一个函数/块 | 中等,选区内替换 |
| Agent | Cmd+L → Agent | 多步骤、多文件任务 | 最高,自主规划执行 |
Agent 模式是 Cursor 最强大的能力——你描述目标,Agent 自主决定读哪些文件、改哪些代码、执行什么命令。
1.2 Agent 的执行流程
用户输入 Prompt
↓
Agent 分析任务 → 制定计划
↓
循环执行:
├── 读取文件(理解现有代码)
├── 搜索代码库(找到相关文件)
├── 编辑文件(生成 diff)
├── 执行命令(运行测试/构建)
├── 调用 MCP 工具(查数据库等)
└── 检查结果 → 决定下一步
↓
展示所有修改(diff 视图)
↓
用户逐个审查 → Accept / Reject
关键点:Agent 的每次文件修改都以 diff 形式展示,你可以逐个接受或拒绝。这是 Cursor 与 Claude Code 最大的区别——Cursor 始终保持人在回路。
2. 实战:创建 API + 前端功能
2.1 场景:添加视频收藏功能
这是一个典型的全栈任务——需要数据库 schema、API 路由、前端 composable 和 UI 组件。
Prompt:
给 AI 视频平台添加视频收藏功能:
数据库:
- 创建 favorites schema(packages/database/schema/favorites.ts)
- 字段:id, userId, videoId, createdAt
- userId + videoId 唯一约束
API(server/api/favorites/):
- toggle.post.ts:切换收藏状态(收藏/取消)
- index.get.ts:获取当前用户的收藏列表(分页)
- check.get.ts:检查某视频是否已收藏
Composable:
- composables/useFavorite.ts:封装收藏逻辑,Optimistic UI
组件:
- components/FavoriteButton.vue:收藏按钮(心形图标,已收藏显示实心)
参考 @server/api/videos/[id]/like.post.ts 的风格
参考 @composables/useLike.ts 的 Optimistic UI 模式
2.2 Agent 的执行过程
Agent 接收到这个 Prompt 后,典型的执行过程:
Step 1:读取参考文件
Agent 读取:
- server/api/videos/[id]/like.post.ts(理解 API 风格)
- composables/useLike.ts(理解 Optimistic UI 模式)
- packages/database/schema/likes.ts(理解 schema 风格)
Step 2:创建 schema
// packages/database/schema/favorites.ts
export const favorites = pgTable('favorites', {
id: text('id').primaryKey().$defaultFn(() => createId()),
userId: text('user_id').notNull().references(() => users.id),
videoId: text('video_id').notNull().references(() => videos.id),
createdAt: timestamp('created_at').defaultNow().notNull(),
}, (table) => ({
uniqueUserVideo: unique().on(table.userId, table.videoId),
}))Step 3:创建 API 路由(3 个文件)
Step 4:创建 composable
Step 5:创建 UI 组件
Step 6:运行 typecheck 验证
整个过程 Agent 自动完成,你在最后审查所有 diff。
2.3 审查要点
Agent 生成的代码通常 80-90% 正确,需要关注:
- 导入是否正确:Nuxt 自动导入的不应该手动 import
- SSR 安全性:收藏状态初始值来自
useFetch,不是localStorage - 错误处理:toggle API 是否处理了并发场景
- 类型完整性:返回类型是否与前端 composable 匹配
3. 实战:Cmd+K 局部修改
3.1 场景:给现有组件添加功能
已有 VideoCard.vue 组件,想添加视频时长显示和悬停预览。
操作流程:
- 打开
VideoCard.vue - 选中整个
<template>块 - 按 Cmd+K
- 输入:
在缩略图右下角添加视频时长显示(格式 mm:ss),
缩略图 hover 时显示前 3 秒的 GIF 预览(从 video.previewUrl 获取)
3.2 Cmd+K 的优势
Cmd+K 适合精确的局部修改:
- 已经知道要改哪个文件、哪个位置
- 修改范围明确(一个函数、一段模板)
- 不需要跨文件操作
相比 Agent,Cmd+K 更快(不需要搜索代码库),更可控(只改选中的部分)。
3.3 进阶技巧
链式 Cmd+K:先改 template,再改 script。
第 1 次 Cmd+K(选中 template):
"添加一个搜索框,绑定 searchQuery ref,支持回车搜索和清空"
第 2 次 Cmd+K(选中 script):
"添加 searchQuery ref,watch 它做 300ms 防抖搜索,
调用 /api/search 接口"
4. 实战:代码重构
4.1 场景:拆分过大的组件
VideoPlayer.vue 已经 500 行了,需要拆分。
Prompt:
重构 @components/VideoPlayer.vue:
这个组件太大了(500+ 行),请拆分为:
1. components/VideoPlayer.vue(主组件,负责组合)
2. components/player/VideoControls.vue(播放控制栏)
3. components/player/QualitySelector.vue(画质选择)
4. components/player/DanmakuLayer.client.vue(弹幕层)
5. composables/useVideoPlayer.ts(播放器核心逻辑)
6. composables/useVideoHotkeys.ts(快捷键逻辑)
要求:
- 保持 VideoPlayer.vue 的 props/emits 不变(不影响外部调用)
- 子组件通过 provide/inject 或 props 通信
- 弹幕层标记为 .client.vue(只在客户端渲染)
4.2 Agent 重构的执行
Agent 会:
- 先读取
VideoPlayer.vue完整代码 - 分析 代码结构,识别可拆分的逻辑块
- 逐个创建 新文件,移动对应代码
- 修改
VideoPlayer.vue,引入拆分后的子组件 - 运行 typecheck 验证类型一致
4.3 审查重点
重构的审查比新功能更需要仔细:
- 功能完整:拆分后所有原有功能是否保留
- 状态通信:父子组件之间的数据流是否正确
- 事件传播:子组件的事件是否正确向上传递
- SSR 兼容:弹幕层是否正确使用了
.client.vue
5. 上下文引用技巧
5.1 @ 引用体系
Cursor 的 @ 引用是提升 Prompt 质量的关键武器:
| 引用方式 | 语法 | 用途 |
|---|---|---|
| 文件 | @filename.ts | 让 AI 读取特定文件 |
| 文件夹 | @server/api/ | 让 AI 了解目录结构 |
| 代码库 | @codebase | 语义搜索整个项目 |
| 文档 | @docs | 引用 Cursor 索引的文档 |
| Git | @git | 引用 Git 历史 |
| Web | @web | 搜索互联网 |
5.2 最佳实践
引用参考文件:
创建 server/api/comments/index.post.ts
参考 @server/api/videos/[id]/like.post.ts 的认证和校验模式
引用类型定义:
@packages/shared/types/video.ts 基于这个类型,
创建一个 VideoCard 组件,展示视频的所有信息
引用代码库搜索:
@codebase 项目中所有使用 useFetch 的地方都是怎么处理错误的?
帮我统一错误处理模式
引用 Git 变更:
@git 上次提交改了什么?帮我检查是否有 SSR 安全问题
5.3 上下文窗口管理
Cursor 的上下文窗口有限。引用太多文件会稀释注意力。原则:
- 精确引用:只引用直接相关的 2-3 个文件,不要引用整个目录
- 先搜后引:不确定哪个文件相关时,先让 Agent 用
@codebase搜索 - 新会话:长对话后上下文会被历史消息占满,开新会话更高效
6. Bug 修复实战
6.1 场景:SSR Hydration Mismatch
Bug:视频列表页在 SSR 渲染后,客户端 hydration 报错:
"Hydration text content mismatch"
错误出现在 VideoCard 的时间显示上:
- 服务端渲染 "3 分钟前"
- 客户端 hydration 时变成 "4 分钟前"
相关文件:
@components/VideoCard.vue
@composables/useTimeAgo.ts
请分析原因并修复。
6.2 Agent 的调试过程
1. 读取 VideoCard.vue → 找到时间显示逻辑
2. 读取 useTimeAgo.ts → 发现用了 new Date()
3. 分析:SSR 和 CSR 的时间差导致文本不一致
4. 修复方案:
- 使用 <ClientOnly> 包裹时间显示
- 或使用 useNuxtApp().ssrContext 统一时间源
6.3 修复后验证
Agent 修复后,你应该:
- 检查 diff:确认修复方案合理
- 本地测试:刷新页面确认 hydration 错误消失
- 边缘情况:检查 SEO 是否受影响(
<ClientOnly>内的内容不会被搜索引擎抓取)
7. 高效使用 Cursor 的习惯
7.1 模式选择决策树
任务类型判断:
├── 写新代码,知道大概怎么写 → Tab 补全
├── 修改一个函数/块 → Cmd+K
├── 探索性问题,想了解代码 → Chat(Cmd+L)
├── 多文件创建/修改 → Agent
└── 复杂重构/全栈功能 → Agent 或 Claude Code
7.2 会话管理
- 一任务一会话:不要在一个会话里做多个不相关的事
- 及时开新会话:超过 10 轮对话,上下文已经很拥挤
- 保存好的 Prompt:把常用的 Prompt 模板存到项目的
.ai/prompts/目录
7.3 审查纪律
Agent 的输出不是最终代码——它是初稿:
- 必审:每个 diff 都要看,理解 Agent 做了什么
- 必测:Agent 不一定运行了测试,手动验证关键功能
- 必改:Agent 的变量命名、注释质量可能不理想,顺手调整
7.4 与 Claude Code 的协作
不同任务选不同工具:
日常开发流程:
1. Cursor Agent 快速生成代码骨架
2. Cursor Tab/Cmd+K 做细节调整
3. 遇到复杂问题 → 切换到 Claude Code
4. Claude Code 完成后 → 回到 Cursor 审查和微调
本章小结
- 三种模式:Tab(逐行)→ Cmd+K(局部)→ Agent(多步多文件),按任务复杂度选择
- 全栈功能:Agent 可以一次生成 schema + API + composable + 组件,审查 diff 后接受
- 局部修改:Cmd+K 适合精确的单文件修改,链式 Cmd+K 可以分步改 template 和 script
- 代码重构:明确拆分目标和约束,Agent 自动移动代码并保持类型一致
- 上下文引用:@ 文件/代码库/Git/Web 是提升 Prompt 质量的关键,精确引用 > 大量引用
- 审查纪律:Agent 输出是初稿,必审 diff、必测功能、必改细节