Cursor 没读到整个项目:3 个原因 + 修复路径

Cursor 只能改"看得见"的——调整索引范围 + 显式 @File 引用。

你让 Cursor “把全项目的 useAuth 都改成 useSession”,结果它只改了 3 个文件,但 grep -r useAuth src/ 显示还剩 17 处。这不是模型偷懒,是它根本没”看见”剩下那 17 个文件——索引漏了、workspace 打开位置不对,或者你的 prompt 没把它指向正确目录。Cursor(以及 Windsurf、Cline 这类 IDE 集成 agent)只能修改”在 codebase index 里 + 在 chat context window 里”的文件,缺一个都漏。这篇给出诊断步骤和把项目重新”拉进 Cursor 视野”的具体命令。

常见原因

按命中率从高到低排序。

1. 索引排除了关键目录

Cursor 的 codebase index 受三层规则影响:.gitignore.cursorignore,以及 Cursor 自己的”过大文件/隐藏目录”启发式跳过。最常见的踩坑是把整个 src/packages/apps/web/ 写进 .gitignore(比如旧的 monorepo 习惯),结果 Cursor 顺带也不索引了。

如何判断:在 Cursor 里按 Cmd+Shift+P → “Cursor Settings” → Features → Codebase Indexing,看显示的”Files Indexed”数。和 git ls-files | wc -l 对比,若差距超过 30%,说明大量文件被排除。

2. Workspace 打开的层级不对

你在 ~/projects/myapp/frontend/ 打开 Cursor,但后端代码、共享 types 在 ~/projects/myapp/backend/~/projects/myapp/shared/。Cursor 只索引当前 workspace 根,看不到兄弟目录的内容,agent 自然无法跨包重构。

如何判断:在 Cursor 左下角看 workspace 名。若显示的是子目录而不是 monorepo 根,就是这种情况。

3. Prompt 没显式钉文件

即使索引完整,Cursor 在长 chat 里也会按”相关性 + token 预算”挑文件塞进 context window。如果你的 prompt 写得太抽象(“refactor the auth flow”),它会用 embedding 检索去找,但漏掉那些命名不直观或者注释不全的文件。

如何判断:执行后看 Cursor 给出的 “Context used” 折叠面板(在回复底部),列出它实际读过哪些文件。和你预期改动的文件清单对比。

4. .gitignore 中包含了运行时生成但仍要被 AI 看到的文件

比如 src/generated/prisma/client/ 这种由 build 产生但语义上很重要的类型定义,常被一并 ignore,然后 agent 改 query 时不知道字段名。

如何判断:搜 grep -r "from.*generated" src/,若代码大量从 generated 目录 import,但 .gitignore 把它排掉了,Cursor 就读不到。

5. 大文件被自动跳过

Cursor 对 > 500KB 或 > 5000 行的单文件默认不索引(避免拖慢检索)。如果你的 schema、迁移脚本或 i18n 字典是巨型单文件,agent 经常表现为”完全不知道这个文件存在”。

如何判断find src -type f -size +500k,把列出来的文件名贴回 chat 问 Cursor “do you see this file in your index?”

最短修复路径

按收益从高到低,前 3 步通常足够。

Step 1:核对 Codebase Index 范围

打开 Cursor → Cmd+Shift+P → “Cursor Settings” → Features → Codebase Indexing。看:

  • Files Indexed:和 git ls-files | wc -l 比较
  • Status:必须是 Synced,不是 Indexing 也不是 Stale
  • Ignore Rules:会显示生效的 .gitignore + .cursorignore

如果 Files Indexed 明显偏少,临时把可疑的 ignore 行注释掉,再点 “Resync Index”。命令行也可以一键重建:

# 关掉 Cursor 后清掉索引缓存
rm -rf ~/Library/Application\ Support/Cursor/User/workspaceStorage/*/cursorIndex
# 重启 Cursor,让它从零重建

Step 2:从 monorepo 根目录重开 workspace

如果你在子目录里打开,直接 File → Open Folder 重选根目录。或在终端:

cd ~/projects/myapp           # monorepo 根
cursor .                       # 用根目录重启 Cursor

打开后,在 chat 里输入 @Folder frontend@Folder backend 各自验证一次,确认两边都能被引用到。

Step 3:Prompt 里显式钉住文件 / 目录

不要写”修改 auth 相关逻辑”,改写成:

@File src/lib/auth.ts @File src/hooks/useAuth.ts @Folder src/components/auth

把 useAuth 替换为 useSession。只动我 @ 出来的文件 + 这些文件
的直接调用方。改完后列出所有被改的文件路径。

@File / @Folder / @Symbol 是硬钉子,比依赖 embedding 检索可靠得多。Claude Code 用户对应的是在 CLAUDE.md 里写死”always read these files first”。

Step 4:维护一个干净的 .cursorignore

.cursorignore 语法和 .gitignore 一样,但只影响 Cursor。典型模板:

# 构建产物
dist/
build/
.next/
.astro/
out/

# 依赖
node_modules/
vendor/

# 缓存与日志
.cache/
.turbo/
*.log
coverage/

# 大型生成数据(按需)
**/*.snap
public/locales/*.json

不要把 src/generated/ 一类语义上必要的目录写进去——它们是 agent 推理类型时的关键依据。

Step 5:把大文件拆成可索引的规模

如果某文件超过 5000 行,agent 几乎一定漏。把 i18n、schema、route 表按模块拆开:

# 例:把 4 万行的 src/i18n/zh.json 按 namespace 拆
node scripts/split-i18n.mjs src/i18n/zh.json src/i18n/zh/

拆完更新 import,再 Resync Index。

预防建议

  • 在仓库根加一份最小.cursorignore,只屏蔽构建产物和依赖,绝不屏蔽 src/generated/、schema、迁移脚本
  • 大改动前先写一行 “files I expect to be touched: a.ts, b.ts, c.ts” 让 agent 反过来确认它能不能 @ 到全部
  • monorepo 始终从仓库根打开 Cursor,子包用 @Folder packages/foo 限定,而不是单独打开子目录
  • 单文件超过 3000 行时主动拆分;不可拆的(如自动生成的 schema)在 CLAUDE.md / .cursorrules 里点名说明
  • 每次重大依赖升级或目录结构调整后,手动点一次 “Resync Codebase Index”,别等 Cursor 自己发现

相关阅读

标签: #AI 编程 #排查 #排查 #Cursor