5.4 OpenSpec + Cursor 工作流
概述
Cursor 是一款基于 VS Code 的 AI 编程 IDE,以其强大的代码补全和智能编辑能力著称。本章将详细介绍如何在 Cursor 中使用 OpenSpec 进行规格驱动开发。
Cursor 与 OpenSpec 的集成
集成架构
┌───────────────────────────────────────────────────────────┐
│ Cursor IDE │
├───────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ .cursor/prompts/openspec/ │ │
│ │ ├── openspec-proposal.md → 创建变更提案 │ │
│ │ ├── openspec-apply.md → 实现变更 │ │
│ │ └── openspec-archive.md → 归档变更 │ │
│ └─────────────────────────────────────────────────────┘ │
│ + │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ .cursorrules │ │
│ │ 全局 AI 行为配置,包含 OpenSpec 工作流指令 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↓ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Cursor AI (Claude/GPT) 执行 OpenSpec 工作流 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────┘命令格式
| 命令 | 功能 | 触发方式 |
|---|---|---|
/openspec-proposal | 创建变更提案 | Cmd+K 或 Chat |
/openspec-apply | 实现变更 | Cmd+K 或 Chat |
/openspec-archive | 归档变更 | Cmd+K 或 Chat |
配置 Cursor 集成
方式 1:通过 OpenSpec 初始化
bash
cd my-project
openspec init
# 选择 Cursor 作为 AI 工具这会自动创建以下文件结构:
.cursor/
└── prompts/
└── openspec/
├── openspec-proposal.md
├── openspec-apply.md
└── openspec-archive.md方式 2:手动配置
bash
# 创建目录
mkdir -p .cursor/prompts/openspec
# 运行更新以生成 Cursor 配置
openspec update配置 .cursorrules
创建 .cursorrules 文件以增强 AI 行为:
markdown
# Cursor Rules for OpenSpec Project
## OpenSpec Workflow
This project uses OpenSpec for spec-driven development.
### Before Any Feature Work
1. Check existing specs: `openspec list --specs`
2. Check active changes: `openspec list`
3. Review project conventions: `openspec/project.md`
### Creating Changes
Use `/openspec-proposal` command or natural language.
### Implementing Changes
Use `/openspec-apply [change-id]` command.
### Spec Format Requirements
- Requirements: `### Requirement:` (3 hashtags)
- Scenarios: `#### Scenario:` (4 hashtags)
- Keywords: **WHEN/THEN/AND/GIVEN** in bold
### Code Conventions
- Follow TypeScript strict mode
- Use async/await for async operations
- Add error handling for all API callsCursor 特有功能
1. Composer 模式 (Cmd+I)
Composer 模式适合创建和实现 OpenSpec 变更:
[Cmd+I 打开 Composer]
输入: 创建 OpenSpec 提案,添加用户通知功能
Cursor 响应:
正在分析项目...
发现现有规格: user, product, order
创建变更提案 add-notifications:
┌─ proposal.md ─────────────────────┐
│ ## Why │
│ 用户需要实时了解订单状态变化... │
└───────────────────────────────────┘
┌─ tasks.md ────────────────────────┐
│ ## 1. Backend │
│ - [ ] 1.1 创建 Notification 模型 │
│ ... │
└───────────────────────────────────┘
[Apply] [Edit] [Cancel]2. 内联编辑 (Cmd+K)
选中规格后快速生成代码或测试:
[选中 spec.md 中的 Requirement]
[Cmd+K] 输入: 根据这个需求生成测试代码
Cursor 生成测试:
describe('User Login', () => {
it('should return JWT on valid credentials', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({ email: 'test@example.com', password: 'valid' });
expect(response.status).toBe(200);
expect(response.body).toHaveProperty('token');
});
});3. 上下文引用 (@符号)
Chat: @openspec/specs/auth/spec.md 需要添加 OAuth 登录
Cursor: 我已阅读 auth 规格。建议创建变更提案:
openspec/changes/add-oauth/
├── proposal.md
├── tasks.md
└── specs/auth/spec.md # Delta
需要我创建吗?4. 多文件编辑
Chat: 根据 add-2fa 提案实现所有代码
Cursor 响应:
我将修改以下文件:
1. src/models/User.ts
+ otpSecret: string
+ otpEnabled: boolean
2. src/routes/auth.ts
+ POST /auth/2fa/enable
+ POST /auth/2fa/verify
3. src/services/OtpService.ts
[新文件]
[显示 diff 预览]
[Apply All] [Review Each]完整工作流演示
场景:为博客系统添加评论功能
Step 1: 创建提案
[Cmd+I 打开 Composer]
输入: /openspec-proposal 为博客文章添加评论功能
Cursor:
正在创建变更提案 add-comments...
已创建:
openspec/changes/add-comments/
├── proposal.md
├── tasks.md
└── specs/
└── comments/
└── spec.md生成的 proposal.md:
markdown
## Why
博客文章需要评论功能以促进读者互动和讨论。
## What Changes
- 添加评论数据模型
- 实现评论 CRUD API
- 添加评论 UI 组件
- 支持嵌套回复
## Impact
- **New spec**: comments
- **Related specs**: post, user
- **Breaking changes**: None生成的 spec.md:
markdown
# Comments Specification
## Purpose
Enable readers to comment on blog posts.
## Requirements
### Requirement: Add Comment
The system SHALL allow authenticated users to add comments.
#### Scenario: Add top-level comment
- **GIVEN** user is logged in
- **WHEN** user submits comment on a post
- **THEN** comment is saved
- **AND** displayed under the post
- **AND** author is notified
#### Scenario: Reply to comment
- **GIVEN** user is logged in
- **WHEN** user replies to existing comment
- **THEN** reply is nested under parent
- **AND** parent author is notified
### Requirement: Edit Comment
The system SHALL allow users to edit their own comments.
#### Scenario: Edit within time limit
- **GIVEN** comment was posted within 15 minutes
- **WHEN** author edits comment
- **THEN** content is updated
- **AND** "edited" label is shown
#### Scenario: Edit after time limit
- **GIVEN** comment was posted over 15 minutes ago
- **WHEN** author tries to edit
- **THEN** edit is rejected
- **AND** error message is shown
### Requirement: Delete Comment
The system SHALL allow comment deletion.
#### Scenario: Author deletes comment
- **WHEN** author deletes their comment
- **THEN** comment content shows "[deleted]"
- **AND** replies are preserved
#### Scenario: Admin deletes comment
- **GIVEN** user is admin
- **WHEN** admin deletes any comment
- **THEN** comment is removed
- **AND** action is loggedStep 2: 审核和完善
Chat: @openspec/changes/add-comments/specs/comments/spec.md
需要添加评论审核功能
Cursor: 我将添加审核需求到规格中:
### Requirement: Comment Moderation
The system SHALL support comment moderation.
#### Scenario: Flag inappropriate comment
- **WHEN** user flags a comment
- **THEN** comment is queued for review
- **AND** admin is notified
#### Scenario: Approve flagged comment
- **GIVEN** comment is flagged
- **WHEN** admin approves it
- **THEN** flag is removed
- **AND** comment remains visible
#### Scenario: Remove flagged comment
- **GIVEN** comment is flagged
- **WHEN** admin removes it
- **THEN** comment is deleted
- **AND** author receives warning
[Apply changes?]Step 3: 验证规格
bash
# 在终端运行
openspec validate add-comments --strict或在 Cursor 中:
Chat: 验证 add-comments 变更规格
Cursor: [执行 openspec validate add-comments --strict]
✓ 验证通过
- 4 个需求
- 10 个场景
- 格式正确Step 4: 实现变更
[Cmd+I 打开 Composer]
输入: /openspec-apply add-comments
Cursor:
读取变更提案...
任务列表:
1. [ ] 创建 Comment 模型
2. [ ] 创建评论 API
3. [ ] 添加评论组件
4. [ ] 实现嵌套回复
5. [ ] 添加审核功能
6. [ ] 编写测试
开始实现任务 1: 创建 Comment 模型生成的代码示例:
typescript
// src/models/Comment.ts
import { prisma } from '../lib/prisma';
export interface Comment {
id: string;
postId: string;
authorId: string;
parentId: string | null;
content: string;
createdAt: Date;
updatedAt: Date;
isEdited: boolean;
isDeleted: boolean;
}
export async function createComment(
postId: string,
authorId: string,
content: string,
parentId?: string
): Promise<Comment> {
return prisma.comment.create({
data: {
postId,
authorId,
content,
parentId: parentId || null,
},
});
}
export async function getCommentsByPost(
postId: string
): Promise<Comment[]> {
return prisma.comment.findMany({
where: { postId, isDeleted: false },
include: {
author: { select: { id: true, name: true, avatar: true } },
replies: {
where: { isDeleted: false },
include: { author: { select: { id: true, name: true, avatar: true } } },
},
},
orderBy: { createdAt: 'desc' },
});
}
export async function updateComment(
commentId: string,
authorId: string,
content: string
): Promise<Comment | null> {
const comment = await prisma.comment.findUnique({
where: { id: commentId },
});
if (!comment || comment.authorId !== authorId) {
return null;
}
// Check 15-minute edit window
const fifteenMinutesAgo = new Date(Date.now() - 15 * 60 * 1000);
if (comment.createdAt < fifteenMinutesAgo) {
throw new Error('EDIT_WINDOW_EXPIRED');
}
return prisma.comment.update({
where: { id: commentId },
data: { content, isEdited: true, updatedAt: new Date() },
});
}
export async function deleteComment(
commentId: string,
userId: string,
isAdmin: boolean
): Promise<void> {
const comment = await prisma.comment.findUnique({
where: { id: commentId },
});
if (!comment) {
throw new Error('COMMENT_NOT_FOUND');
}
if (comment.authorId !== userId && !isAdmin) {
throw new Error('UNAUTHORIZED');
}
if (isAdmin) {
// Admin: hard delete
await prisma.comment.delete({ where: { id: commentId } });
} else {
// Author: soft delete
await prisma.comment.update({
where: { id: commentId },
data: { isDeleted: true, content: '[deleted]' },
});
}
}Step 5: 归档变更
Chat: 评论功能已完成并部署,归档变更
Cursor: [执行 openspec archive add-comments --yes]
✓ 归档完成
- 规格已合并到 openspec/specs/comments/
- 变更已移至 archive/2024-12-05-add-comments/Cursor 高级技巧
1. 使用 Tab 补全
在编写规格时,Cursor 会根据上下文提供补全建议:
markdown
### Requirement: Password Re[Tab]
→ ### Requirement: Password Reset
#### Scenario: [Tab]
→ #### Scenario: Successful reset2. 规格到代码的快速转换
[选中整个 spec.md]
[Cmd+K] 输入: 根据这些规格生成完整的 API 路由代码
Cursor: 生成 routes/comments.ts...3. 批量更新任务状态
Chat: 标记 add-comments 的任务 1-3 为完成
Cursor: 更新 tasks.md:
- [x] 1.1 创建 Comment 模型
- [x] 1.2 创建 CommentReply 关联
- [x] 2.1 GET /api/posts/:id/comments
- [x] 2.2 POST /api/posts/:id/comments
- [x] 2.3 PUT /api/comments/:id
- [x] 2.4 DELETE /api/comments/:id
- [ ] 3.1 CommentList 组件
...4. 与 Git 集成
Chat: 为 add-comments 变更创建功能分支并提交提案
Cursor: 执行:
1. git checkout -b feature/add-comments
2. git add openspec/changes/add-comments/
3. git commit -m "spec: add comments feature proposal"
完成!当前在 feature/add-comments 分支。常见问题
问题 1: 命令不识别
解决: 确保 .cursor/prompts/openspec/ 目录存在,重启 Cursor。
问题 2: 规格格式错误
解决: 使用 Cursor 的 lint 功能或运行 openspec validate --strict。
问题 3: 多人协作冲突
解决: 使用 Git 分支,每个变更对应一个分支:
bash
git checkout -b feature/add-comments
# 工作...
git merge main本章小结
Cursor 与 OpenSpec 的集成提供了流畅的开发体验:
- Composer 模式:适合创建完整的变更提案
- 内联编辑:快速生成代码和测试
- 多文件编辑:一次性修改多个相关文件
- 上下文引用:@ 符号引用规格文件
完整示例代码
以下是 Cursor + OpenSpec 的完整配置和工作流脚本:
bash
#!/bin/bash
# Cursor + OpenSpec 配置和演示脚本
set -e
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'
log() { echo -e "${BLUE}[Cursor+OpenSpec]${NC} $1"; }
success() { echo -e "${GREEN}[✓]${NC} $1"; }
# 项目设置
PROJECT_DIR="cursor-openspec-demo"
log "创建演示项目: $PROJECT_DIR"
rm -rf "$PROJECT_DIR"
mkdir -p "$PROJECT_DIR"
cd "$PROJECT_DIR"
# 初始化
git init -q
# ============================================
# 1. OpenSpec 初始化
# ============================================
log "初始化 OpenSpec..."
mkdir -p openspec/{specs,changes/archive}
mkdir -p .cursor/prompts/openspec
# 项目配置
cat > openspec/project.md << 'EOF'
# Project Context
## Overview
Blog platform with comments system.
## Tech Stack
- TypeScript + Node.js
- Express + Prisma
- React + TailwindCSS
## Conventions
- RESTful API design
- Async/await for all async code
- Comprehensive error handling
EOF
# AGENTS.md
cat > openspec/AGENTS.md << 'EOF'
# OpenSpec Instructions
## Workflow
1. Create proposal with `/openspec-proposal`
2. Implement with `/openspec-apply`
3. Archive with `/openspec-archive`
## Spec Format
- `### Requirement:` for requirements
- `#### Scenario:` for scenarios
- **WHEN/THEN/AND** keywords
EOF
cat > AGENTS.md << 'EOF'
<!-- OPENSPEC:START -->
This project uses OpenSpec. See `openspec/AGENTS.md`.
<!-- OPENSPEC:END -->
EOF
success "OpenSpec 已初始化"
# ============================================
# 2. Cursor 命令配置
# ============================================
log "配置 Cursor 命令..."
# proposal 命令
cat > .cursor/prompts/openspec/openspec-proposal.md << 'EOF'
# OpenSpec Proposal
Create a new OpenSpec change proposal based on the user's request.
## Instructions
1. Run `openspec list --specs` to see existing specs
2. Create change directory: `openspec/changes/<change-id>/`
3. Generate:
- proposal.md (Why, What Changes, Impact)
- tasks.md (Implementation checklist)
- specs/<capability>/spec.md (Delta specs)
## Format
- Change ID: kebab-case, verb-led
- Requirements: `### Requirement:` (3 #)
- Scenarios: `#### Scenario:` (4 #)
- Keywords: **WHEN/THEN/AND/GIVEN**
User request: {input}
EOF
# apply 命令
cat > .cursor/prompts/openspec/openspec-apply.md << 'EOF'
# OpenSpec Apply
Implement an OpenSpec change.
## Instructions
1. Read proposal.md and tasks.md
2. Execute tasks in order
3. Mark completed: `- [x]`
4. Follow project conventions
Change ID: {input}
EOF
# archive 命令
cat > .cursor/prompts/openspec/openspec-archive.md << 'EOF'
# OpenSpec Archive
Archive a completed change.
## Instructions
1. Verify all tasks are complete
2. Run: `openspec archive {input} --yes`
3. Commit changes
Change ID: {input}
EOF
success "Cursor 命令已配置"
# ============================================
# 3. .cursorrules 配置
# ============================================
log "创建 .cursorrules..."
cat > .cursorrules << 'EOF'
# Cursor Rules for OpenSpec Project
## OpenSpec Integration
This project uses OpenSpec for spec-driven development.
### Available Commands
- `/openspec-proposal` - Create change proposal
- `/openspec-apply` - Implement change
- `/openspec-archive` - Archive completed change
### Before Starting Work
1. Check `openspec list` for active changes
2. Check `openspec list --specs` for existing specs
3. Read `openspec/project.md` for conventions
### Spec Format (CRITICAL)
- Requirements: `### Requirement: Name` (exactly 3 hashtags)
- Scenarios: `#### Scenario: Name` (exactly 4 hashtags)
- Keywords in bold: **WHEN**, **THEN**, **AND**, **GIVEN**
### Code Conventions
- TypeScript strict mode
- Async/await (no .then chains)
- Comprehensive error handling
- JSDoc for public APIs
### File Locations
- Specs: openspec/specs/
- Changes: openspec/changes/
- Project context: openspec/project.md
EOF
success ".cursorrules 已创建"
# ============================================
# 4. 创建示例规格
# ============================================
log "创建示例规格..."
mkdir -p openspec/specs/{post,user}
cat > openspec/specs/post/spec.md << 'EOF'
# Post Specification
## Purpose
Manage blog posts.
## Requirements
### Requirement: Create Post
The system SHALL allow authors to create posts.
#### Scenario: Create draft
- **GIVEN** user is logged in
- **WHEN** user creates a post
- **THEN** post is saved as draft
- **AND** preview is available
### Requirement: Publish Post
The system SHALL allow publishing posts.
#### Scenario: Publish draft
- **GIVEN** post is in draft status
- **WHEN** author publishes post
- **THEN** post becomes public
- **AND** RSS feed is updated
EOF
cat > openspec/specs/user/spec.md << 'EOF'
# User Specification
## Purpose
Handle user accounts.
## Requirements
### Requirement: User Registration
The system SHALL allow registration.
#### Scenario: Register with email
- **WHEN** user submits valid email and password
- **THEN** account is created
- **AND** verification email is sent
EOF
success "示例规格已创建"
# ============================================
# 5. 创建评论变更提案
# ============================================
log "创建评论变更提案..."
CHANGE_ID="add-comments"
mkdir -p "openspec/changes/$CHANGE_ID/specs/comments"
cat > "openspec/changes/$CHANGE_ID/proposal.md" << 'EOF'
## Why
博客需要评论功能以促进读者互动。
## What Changes
- 新增评论数据模型
- 实现评论 CRUD API
- 支持嵌套回复
## Impact
- **New spec**: comments
- **Related**: post, user
- **Breaking**: None
EOF
cat > "openspec/changes/$CHANGE_ID/tasks.md" << 'EOF'
# Tasks: Add Comments
## 1. Database
- [ ] 1.1 Create Comment model (Prisma)
- [ ] 1.2 Run migration
## 2. API
- [ ] 2.1 GET /api/posts/:id/comments
- [ ] 2.2 POST /api/posts/:id/comments
- [ ] 2.3 PUT /api/comments/:id
- [ ] 2.4 DELETE /api/comments/:id
## 3. Frontend
- [ ] 3.1 CommentList component
- [ ] 3.2 CommentForm component
- [ ] 3.3 ReplyThread component
## 4. Testing
- [ ] 4.1 API unit tests
- [ ] 4.2 Integration tests
EOF
cat > "openspec/changes/$CHANGE_ID/specs/comments/spec.md" << 'EOF'
# Comments Specification
## Purpose
Enable readers to comment on blog posts.
## Requirements
### Requirement: Add Comment
The system SHALL allow authenticated users to add comments.
#### Scenario: Add top-level comment
- **GIVEN** user is logged in
- **WHEN** user submits comment on post
- **THEN** comment is saved and displayed
#### Scenario: Reply to comment
- **GIVEN** user is logged in
- **WHEN** user replies to existing comment
- **THEN** reply is nested under parent
### Requirement: Edit Comment
The system SHALL allow users to edit own comments within 15 minutes.
#### Scenario: Edit within time limit
- **GIVEN** comment was posted within 15 minutes
- **WHEN** author edits comment
- **THEN** content is updated with "edited" label
#### Scenario: Edit after time limit
- **GIVEN** comment was posted over 15 minutes ago
- **WHEN** author tries to edit
- **THEN** edit is rejected with error
### Requirement: Delete Comment
The system SHALL allow comment deletion.
#### Scenario: Author soft-deletes
- **WHEN** author deletes their comment
- **THEN** content shows "[deleted]"
- **AND** replies are preserved
#### Scenario: Admin hard-deletes
- **GIVEN** user is admin
- **WHEN** admin deletes comment
- **THEN** comment is removed completely
EOF
success "评论变更提案已创建"
# ============================================
# 6. 验证
# ============================================
log "验证变更..."
if command -v openspec &> /dev/null; then
openspec validate "$CHANGE_ID" --strict 2>/dev/null || echo "验证完成"
else
echo "(openspec 未安装,跳过验证)"
fi
# ============================================
# 7. 显示结构
# ============================================
echo ""
echo "========================================"
echo " Cursor + OpenSpec 配置完成!"
echo "========================================"
echo ""
echo "项目结构:"
find . -type f \( -name "*.md" -o -name ".cursorrules" \) | sort
echo ""
echo "使用方法:"
echo "1. 用 Cursor 打开项目: cursor $PROJECT_DIR"
echo "2. 创建提案: Cmd+I 输入 /openspec-proposal 你的功能描述"
echo "3. 实现变更: Cmd+I 输入 /openspec-apply add-comments"
echo "4. 归档: Cmd+I 输入 /openspec-archive add-comments"
echo ""
echo "快捷键:"
echo "- Cmd+I: 打开 Composer(多文件编辑)"
echo "- Cmd+K: 内联编辑"
echo "- @文件名: 引用文件上下文"将此脚本保存为 cursor-openspec-setup.sh,然后执行:
bash
chmod +x cursor-openspec-setup.sh
./cursor-openspec-setup.sh这个脚本会创建一个完整配置的 Cursor + OpenSpec 项目,包括:
- OpenSpec 目录结构和配置
- Cursor 斜杠命令模板
- .cursorrules 全局规则
- 示例规格和变更提案
用 Cursor 打开生成的项目目录即可开始使用 OpenSpec 工作流。