IDE 配置与 Rules 记忆体系

AI 编程工具的效果取决于两个因素:模型能力和上下文质量。模型能力你无法控制(由 Anthropic/OpenAI 决定),但上下文质量完全在你手里。Rules 文件(.cursorrulesCLAUDE.md、Windsurf 的 .windsurfrules)就是你向 AI 注入项目上下文的核心机制——告诉 AI 你的技术栈、代码规范、架构约定、常见陷阱。写好 Rules,AI 输出质量提升 3-5 倍不是夸张。

1. Rules 的本质

1.1 为什么需要 Rules

没有 Rules 的 AI 编码像是一个刚入职的高级工程师——能力强,但不了解你的项目:

没有 Rules有 Rules
useState 管理全局状态知道用 Pinia + useState 做 SSR 安全状态
生成 Options API 代码遵循 <script setup> + Composition API
axios 发请求$fetch / useFetch
随意的文件命名遵循 server/api/[resource]/[id].[method].ts 约定
不处理 SSR/CSR 差异import.meta.client 守卫浏览器 API

Rules 本质上是一份持久化的系统提示词——每次 AI 开始工作时都会自动加载,不需要你每次重复说明。

1.2 各工具的 Rules 机制

工具文件位置加载方式
Cursor.cursorrules项目根目录每次对话自动加载
Claude CodeCLAUDE.md项目根 / 子目录启动时自动读取,支持分层
Windsurf.windsurfrules项目根目录Flow 启动时加载
Copilot.github/copilot-instructions.md项目根目录Chat 时加载

2. Cursor Rules 编写

2.1 .cursorrules 结构

# Project: AI Video Platform
 
## Tech Stack
- Nuxt 4 (Vue 3.5+, Nitro, TypeScript)
- Drizzle ORM + PostgreSQL
- Tailwind CSS v4 + Nuxt UI
- pnpm monorepo (apps/web, apps/admin, packages/*)
 
## Code Style
- Always use `<script setup lang="ts">` for Vue components
- Use `defineProps` with TypeScript generics, not runtime declaration
- Use `useTemplateRef()` instead of template refs with string
- Use `$fetch` for client-side requests, `useFetch` for SSR-safe data fetching
- Use `import.meta.client` / `import.meta.server` guards, NEVER `process.client`
- All API handlers use Zod validation with `readValidatedBody`
 
## File Conventions
- API routes: `server/api/[resource]/[id].[method].ts`
- Composables: `composables/use[Name].ts` (auto-imported)
- Components: PascalCase, `.client.vue` suffix for client-only
- Types: `packages/shared/types/[domain].ts`
 
## Architecture Rules
- Server state: Drizzle queries in API handlers, NEVER direct DB access from client
- Auth: `requireAuth(event)` in all protected API routes
- Caching: `defineCachedEventHandler` for read-heavy, rarely-changing data
- Error handling: `createError({ statusCode, message })` for API errors
 
## Common Mistakes to Avoid
- Do NOT use `ref()` for props destructuring, use `defineProps` with reactive destructure
- Do NOT use `v-html` with user input
- Do NOT import from `vue` what Nuxt auto-imports (`ref`, `computed`, `watch`, etc.)
- Do NOT use `useAsyncData` when `useFetch` suffices (useFetch = useAsyncData + $fetch)
- Do NOT forget to handle SSR hydration mismatches for browser-only components

2.2 编写原则

具体胜过抽象:不要写"遵循最佳实践",要写具体的代码约定。

# 差:
Use best practices for error handling.
 
# 好:
All API handlers must:
1. Validate input with Zod: `readValidatedBody(event, schema.parse)`
2. Throw errors with: `createError({ statusCode: 400, message: 'xxx' })`
3. Wrap external API calls in try-catch with specific error messages

示例胜过描述:展示正确的代码比描述规则更有效。

# 差:
Use the Nuxt data fetching pattern.
 
# 好:
## Data Fetching Pattern
 
Server-rendered pages:
```vue
&lt;script setup&gt;
const &#123; data &#125; = await useFetch('/api/videos', &#123;
  query: &#123; page: 1 &#125;,
  transform: (res) => res.items,
&#125;)

Client-side actions:

const result = await $fetch('/api/videos', &#123;
  method: 'POST',
  body: &#123; title: 'xxx' &#125;,
&#125;)

**包含反模式**:告诉 AI 不要做什么,比告诉它要做什么更重要。

```markdown
## Anti-Patterns
- NEVER: `import { ref } from 'vue'` (auto-imported in Nuxt)
- NEVER: `process.client` (use `import.meta.client`)
- NEVER: `localStorage.getItem()` without `import.meta.client` guard
- NEVER: raw SQL strings (use Drizzle query builder)

2.3 Cursor 项目级 Rules

Cursor 还支持更细粒度的 Rules(.cursor/rules/ 目录),可以按文件类型或目录触发:

<!-- .cursor/rules/api-routes.md -->
---
globs: ["server/api/**/*.ts"]
---
 
# API Route Rules
- Every handler must start with auth check: `const session = await requireAuth(event)`
- Use `readValidatedBody(event, schema.parse)` for POST/PUT
- Use `getQuery(event)` for GET parameters
- Return typed objects, never raw database rows
- Always include pagination for list endpoints: `{ items, total }`
<!-- .cursor/rules/vue-components.md -->
---
globs: ["**/*.vue"]
---
 
# Vue Component Rules
- Use `<script setup lang="ts">` exclusively
- Props: `defineProps<{ ... }>()` with TypeScript generics
- Emits: `defineEmits<{ ... }>()` with TypeScript generics
- Template refs: `useTemplateRef<HTMLElement>('name')`
- Client-only logic: wrap in `onMounted` or use `.client.vue` suffix

3. CLAUDE.md 分层体系

3.1 分层架构

Claude Code 的 CLAUDE.md 支持目录级分层——不同目录可以有不同的 Rules:

project/
├── CLAUDE.md                    # 全局 Rules(技术栈、通用规范)
├── apps/
│   ├── web/
│   │   └── CLAUDE.md            # Web 应用特定规范
│   └── admin/
│       └── CLAUDE.md            # 管理后台特定规范
├── packages/
│   ├── database/
│   │   └── CLAUDE.md            # 数据库层规范
│   └── shared/
│       └── CLAUDE.md            # 共享包规范
└── tests/
    └── CLAUDE.md                # 测试规范

Claude Code 在进入某个目录时,会自动加载该目录及其所有父目录的 CLAUDE.md

3.2 全局 CLAUDE.md

# AI Video Platform
 
## Project Structure
pnpm monorepo with:
- `apps/web` - Nuxt 4 user-facing app (SSR)
- `apps/admin` - Nuxt 4 admin dashboard (SPA)
- `packages/database` - Drizzle ORM schema and migrations
- `packages/shared` - Shared types and utilities
- `packages/ui` - Shared UI components (Nuxt Layer)
 
## Commands
- `pnpm dev` - Start dev server (apps/web)
- `pnpm build` - Build for production
- `pnpm test` - Run all tests
- `pnpm typecheck` - TypeScript type check
- `pnpm lint` - ESLint check
- `pnpm db:migrate` - Run database migrations
- `pnpm db:generate` - Generate migration from schema changes
 
## Code Style
- TypeScript strict mode, no `any` unless unavoidable
- Vue: `<script setup lang="ts">`, Composition API only
- API: Zod validation, typed responses, proper error codes
- Database: Drizzle ORM, never raw SQL in application code
 
## Git Conventions
- Conventional Commits: `feat:`, `fix:`, `refactor:`, `docs:`, `test:`
- One logical change per commit
- Run `pnpm typecheck && pnpm test` before committing

3.3 子目录 CLAUDE.md

<!-- packages/database/CLAUDE.md -->
# Database Package
 
## Schema Location
All schemas in `schema/` directory, one file per domain entity.
 
## Schema Conventions
- Table names: snake_case plural (`videos`, `ai_tasks`)
- Column names: snake_case (`created_at`, `user_id`)
- Primary key: `text('id').$defaultFn(() => createId())`
- Timestamps: `created_at` and `updated_at` with defaults
- Foreign keys: always define `.references(() => table.column)`
- Indexes: define at table level with `pgTable` index option
 
## Migration
After schema changes, run: `pnpm db:generate`
Review generated SQL in `drizzle/` before applying.

3.4 Claude Code 专属命令

CLAUDE.md 中可以定义自定义 slash 命令:

<!-- .claude/commands/add-feature.md -->
---
description: "Add a new feature end-to-end"
---
 
When adding a new feature:
1. Create/update database schema in `packages/database/schema/`
2. Generate migration: run `pnpm db:generate`
3. Create API routes in `server/api/`
4. Create composable in `composables/`
5. Create page/component in `pages/` or `components/`
6. Run `pnpm typecheck` to verify types
7. Run `pnpm test` to verify tests pass
8. Commit with `feat: [description]`

4. Windsurf Rules 与记忆

4.1 .windsurfrules

<!-- .windsurfrules -->
# Nuxt 4 AI Video Platform
 
## Framework
Nuxt 4 with TypeScript, Nitro server, Drizzle ORM, Tailwind CSS v4.
 
## Key Patterns
- Data fetching: `useFetch` for SSR pages, `$fetch` for client actions
- State: Pinia stores for complex state, `useState` for simple shared state
- Auth: `nuxt-auth-utils`, session-based, `requireAuth()` server middleware
- Validation: Zod schemas for all API input
 
## File Structure
server/api/[resource]/index.get.ts   → List
server/api/[resource]/[id].get.ts    → Detail
server/api/[resource]/index.post.ts  → Create
server/api/[resource]/[id].put.ts    → Update
server/api/[resource]/[id].delete.ts → Delete

4.2 Windsurf Memory

Windsurf 有内置的持久化记忆系统(create_memory 工具),可以跨会话记住:

  • 项目偏好("总是用 Tailwind,不用内联样式")
  • 架构决策("视频处理用 BullMQ 队列")
  • 调试经验("PostgreSQL 连接超时通常是连接池耗尽")

记忆由 AI 自动管理,也可以主动要求"记住这个"。

5. Rules 同步策略

5.1 问题

同时使用 Cursor、Claude Code、Windsurf 时,三份 Rules 要保持同步——这很痛苦。

5.2 方案:共享核心 + 工具适配

.ai/
├── core-rules.md          # 核心规范(技术栈、代码风格、架构)
├── cursorrules.md          # Cursor 专属(IDE 相关的规则)
└── claude-commands/        # Claude Code 专属命令
    ├── add-feature.md
    └── fix-bug.md

.cursorrules               # 引用 .ai/core-rules.md + Cursor 专属
CLAUDE.md                  # 引用 .ai/core-rules.md + Claude 专属
.windsurfrules             # 引用 .ai/core-rules.md + Windsurf 专属

核心规范写一份,各工具的 Rules 文件引用核心 + 添加工具专属内容。虽然没有真正的"引用"机制(各工具都是纯文本读取),但可以通过脚本自动生成:

#!/bin/bash
# scripts/sync-rules.sh
CORE=$(cat .ai/core-rules.md)
 
# 生成 .cursorrules
echo "$CORE" > .cursorrules
cat .ai/cursorrules.md >> .cursorrules
 
# 生成 CLAUDE.md
echo "$CORE" > CLAUDE.md
echo "" >> CLAUDE.md
echo "## Claude Code Specific" >> CLAUDE.md
cat .ai/claude-specific.md >> CLAUDE.md

6. 实战:AI 视频平台 Rules 模板

6.1 完整的 .cursorrules

# AI Video Platform - Cursor Rules
 
## Tech Stack
- **Framework**: Nuxt 4 (Vue 3.5+, TypeScript strict)
- **Server**: Nitro with Node.js preset
- **Database**: PostgreSQL + Drizzle ORM
- **UI**: Tailwind CSS v4 + Nuxt UI
- **Auth**: nuxt-auth-utils (session-based)
- **Monorepo**: pnpm workspace
 
## Vue Components
- Always `<script setup lang="ts">`
- Props: `defineProps<{ prop: Type }>()` with TS generics
- Emits: `defineEmits<{ (e: 'update', value: string): void }>()` 
- Refs: `useTemplateRef<HTMLElement>('name')`
- Never import auto-imported composables: ref, computed, watch, onMounted, etc.
 
## Data Fetching
- SSR pages: `const { data } = await useFetch('/api/...')`
- Client actions: `await $fetch('/api/...', { method: 'POST', body: {} })`
- Never use axios or fetch directly
 
## API Routes
- Path: `server/api/[resource]/[id].[method].ts`
- Auth: `const session = await requireAuth(event)`
- Validation: `const body = await readValidatedBody(event, schema.parse)`
- Errors: `throw createError({ statusCode: 400, message: '...' })`
- Caching: `defineCachedEventHandler` for read-heavy endpoints
 
## Database
- Schema: `packages/database/schema/[entity].ts`
- Always use Drizzle query builder, never raw SQL in app code
- Relations: define in schema with `relations()`
- IDs: `text('id').$defaultFn(() => createId())`
 
## SSR Safety
- Browser APIs: guard with `import.meta.client` or use `.client.vue`
- Dynamic imports: `const Lib = await import('lib')` in onMounted
- No `window`, `document`, `localStorage` without client guard
 
## Don't
- Don't use Options API
- Don't use `process.client` (use `import.meta.client`)
- Don't use `v-html` with user content
- Don't put business logic in components (use composables)
- Don't access database from client-side code

本章小结

  • Rules 本质:持久化系统提示词,注入项目上下文,提升 AI 输出质量 3-5 倍
  • 编写原则:具体胜过抽象、示例胜过描述、反模式比正确模式更重要
  • Cursor.cursorrules(全局)+ .cursor/rules/(按文件类型),支持 glob 匹配
  • Claude CodeCLAUDE.md 分层(根目录 + 子目录),自动继承父级,支持自定义命令
  • Windsurf.windsurfrules + 内置 Memory 系统,跨会话记忆
  • 同步策略:核心规范写一份,脚本自动生成各工具的 Rules 文件