Cursor 上下文面板没带上你要的文件

Cursor 的 context 面板漏掉了你明知相关的文件。先用 @ 五秒救场,再断根:查 .cursorignore、resync 索引、给通用文件改名。

Cursor 的 Agent(或 Composer)给了你答案,你点开对话顶上的 context 面板,结果 utils/parseInvoice.ts——你明知该参考的文件——根本不在列表里。这个面板就是它真正交给模型的文件清单:不在面板里,就等于模型压根没看到。

这几乎从来不是 bug,而是检索的几个经典失败模式之一:语义检索打分太低、被 .cursorignore 挡住、文件刚改过还没重新索引,或者上下文窗口被无关文件挤满了。

最快的修法(5 秒): 在对话输入框里输 @,再打文件名(例如 @parseInvoice),让自动补全把它带进来,重新发送。手动挂上去的文件一定会交给模型。唯一例外:如果这个文件被写进了 .cursorignore,那 @ 也带不进去——见下面的原因 2。

然后把根因修掉,省得每次都得手动盯着。

先判断你属于哪一类

面板里的现象最可能的原因跳转
文件从来不出现,连 @ 都带不进.cursorignore 挡住原因 2
@ 能带进,但自动检索就是不带它语义分太低 / 文件名太通用原因 1 / 原因 5
刚新建 / 刚改名的文件不在还没重新索引原因 3
出现的是同名但路径不对的文件通用文件名撞车原因 5
面板被一堆无关 tab / 近期文件塞满上下文被挤掉原因 4
.parquet / .bin / 超大文件不在不可索引原因 6

常见原因

1. 语义检索打分太低

Cursor 把每个文件切成块、嵌入成向量、存进向量索引做语义检索(@codebase 和 Agent 的自动找文件都走这套)。一个 500 行混着各种工具函数的 utils.ts,对 “parse invoice” 这个 query 的相似度会被稀释;同样的代码放进叫 parseInvoice.ts 的文件,文件名信号一下被点亮,直接排到结果最前面。

如何确认: 执行 git mv utils.ts parseInvoiceHelpers.ts,跑一次 resync(见 Step 3),再回头看面板。

2. 被 .cursorignore 挡住

这是最常被误判的原因。截至 2026 年 6 月,.cursorignore 是硬屏蔽:被它命中的文件会被排除在语义检索、Tab、Agent 和 Inline Edit 之外,而且连 @-mention 引用也用不了。所以如果你”最快修法”里输 @filename 却毫无反应,那这个文件几乎肯定在 .cursorignore 里。

还有一个更”软”的文件:.cursorindexingignore。被它命中的文件只是不进检索索引(所以自动检索带不出来),但仍然可以用 @-mention 和 Agent 取到。对于那些偶尔要引用一下的大型生成目录,通常你真正想要的是这个。

.cursorignore 里最常见的误伤:dist/build/generated/——里面往往就有模型该参考的 schema 和类型定义。

如何确认:

cat .cursorignore
git check-ignore -v src/utils/parseInvoice.ts

git check-ignore 会告诉你是哪条 .gitignore 规则排除了文件(Cursor 也尊重 .gitignore)。如果是 .cursorignore 特有的规则,它不会打印出来,得直接肉眼看 .cursorignore。优先级顺序是:先 .gitignore,再 .cursorignore(支持 ! 反向规则),最后 .cursorindexingignore 再叠加一层仅针对索引的排除。

3. 文件刚新建或刚改名

索引是增量的:Cursor 用 Merkle-tree 变更检测,按一个轮询周期(几分钟一次,截至 2026 年 6 月大约 5-10 分钟,且不可由用户调整)只对改动过的文件做自动 resync。全新文件需要一次保存事件才会登记,改名后旧路径可能在索引里滞留几秒。在这个窗口里,检索用的是旧索引。

如何确认: 打开 Cursor Settings → Indexing,把已索引文件数和 git ls-files | wc -l 对比。如果数字偏少,说明索引还没跟上——手动逼一下(Step 3)。

4. 被噪声挤出上下文

模型的 context window 是有限的。Agent/Composer 会自动拉进”近期编辑过的文件""打开的 tab”和被 import 的文件;这些一多,就把预算吃光、把你的目标文件挤出去了。

如何确认: 面板里有十几二十个不相关的 tab 或最近编辑文件,就是这种。

5. 文件名太通用,信号被分摊

index.tshelpers.tstypes.tsutils.ts——monorepo 里每种都有几十个,语义检索选了别处的同名兄弟。

如何确认: 面板里出现了同名、但路径不对的文件。

6. 二进制、超大或不支持的文件

二进制大块(.parquet.bin.gz)没法嵌入,超大的纯文本文件在切块时会被跳过。一个普通的 .ts/.json 一旦膨胀到几 MB,也会悄悄掉出索引。

如何确认: ls -lh path/to/file。如果是二进制类型,或是大得反常的文本文件,它就不在语义索引里——直接用 @ 挂上去,或者把它拆小。

动手前先确认

  • 确认问题出在哪个入口:Agent / Composer / Cmd+K / chat。Cmd+K(inline edit)只针对当前文件和选区,不走全仓检索,所以那里”缺”一个全仓文件是正常的。
  • 改名或动 ignore 规则之前先 commit 一次,免得把团队共享配置弄乱。
  • 记下 Cursor 版本和当前模型(例如 Sonnet 4.6、GPT-5.5、Composer)。不同版本检索 ranking 会变。

需要收集的信息

  • Cursor 版本、操作系统、仓库总文件数。
  • .cursorignore.cursorindexingignore 全文、.gitignore 关键条目。
  • Cursor Settings → Indexing 截图(索引状态、上次同步时间、已索引文件数)。
  • 对话 context 面板截图(你看到的实际加载文件列表)。
  • 目标缺失文件的路径、大小、扩展名。

最短修复路径

按”立刻可救 → 系统改善”排序。

Step 1:用 @ 手动挂文件

最快。在对话输入框输 @parseInvoice,让自动补全把文件挂上去,再发送。手动挂的文件一定会交给模型——大约 5 秒。(如果 @ 挂不上去,直接跳 Step 2:它被 .cursorignore 了。)

Step 2:审计 .cursorignore

cat .cursorignore
git check-ignore -v src/utils/parseInvoice.ts

如果文件确实被挡:

  • 临时: 注释掉那条规则,重载 Cursor(Cmd+Shift+P → “Reload Window”),再试。
  • 更好: 如果你只是想让它不进检索(而不是彻底对模型隐藏),把规则从 .cursorignore 挪到 .cursorindexingignore。这样文件仍然可以 @-mention。
  • 更精确的 glob:dist/**/*.js 代替 dist/,至少把生成的 .d.ts 类型留下。

Step 3:Resync 索引

Cmd+Shift+P → “Cursor: Resync Index”(旧版本里叫 “Cursor: Rebuild Index” / “Rebuild Codebase Index”)。这会强制立即重新索引,不用等自动周期。大仓全量重建可能要几分钟;索引还没完全建完,语义检索通常就已经重新可用了。大改名或大量新增后必跑这一步。

如果 resync 卡住,或跑完后 CPU 一直占满,就删掉本地索引缓存让它重建。macOS 上路径是 ~/Library/Application Support/Cursor/Index/;退出 Cursor,删掉那个文件夹,重新打开。

Step 4:给重要文件起有语义的名字

utils.ts 拆成 parseInvoice.ts / formatCurrency.ts / validateEmail.ts。检索打分 = 文件名信号 + 内容信号,名字一描述清楚就直接窜到前面。

Step 5:用 project rule 固定指认 canonical 文件

加一条 project rule(.cursor/rules/*.mdc,现行格式;放在仓库根的旧式 .cursorrules 也仍然有效),告诉 Agent 哪些文件永远要读:

When working on invoice logic, always read:
- src/utils/parseInvoice.ts
- src/types/invoice.ts
- src/api/invoices.ts
These define the canonical model and parser.

Cursor 会把命中的 rule 直接喂给模型——相当于给这个工作流一份手搓的索引。

Step 6:清掉面板里的噪声

context 面板里每一项旁边都有个 × 可以删掉。把无关的 tab 和历史项删掉,给目标文件腾出窗口空间。在 Agent/Composer 设置里也可以把 “Auto-include open tabs” 关掉。

怎么确认已经修好

  • 重新跑一次同样的 prompt,确认目标文件现在出现在 context 面板里。
  • 答完后追问 “List every file you read for this answer”,看目标文件被点到名。
  • 在第二台机器上拉取同一仓库复现——确认你修的是共享配置(ignore 规则、文件名、project rule),而不只是你本地的索引。

如果还是没修好

  • 把 prompt 缩到只剩一个关键词加一个显式 @File,把检索问题和 prompt 歧义分开。
  • 回滚最近一次 .cursorignore 改动或 Cursor 升级。
  • 抓索引日志:View → Output → 在下拉里选 “Cursor” / indexing 通道。
  • forum.cursor.com 搜 “context panel missing”;要发帖就附上版本、仓库结构和缺失文件的路径。

预防建议

  • 重要文件用有语义的文件名,别用 utils.ts / helpers.ts 这种万能名。
  • .cursorignore 只放真正不该碰的文件(密钥、外来垃圾)。“别检索但我可能会 @” 的,用 .cursorindexingignore
  • 核心工作流的 canonical files 列进 .cursor/rules 文件或 CONTEXT.md
  • 大改名或大量新增后立即 Cmd+Shift+P → “Cursor: Resync Index”,别等轮询周期。
  • 重要 prompt 永远手动 @ 挂上关键参考,别赌自动检索。

常见问题

为什么偏偏某一个文件 @filename 没反应? 那个文件被 .cursorignore 命中了,而它连 @-mention 也一并屏蔽(截至 2026 年 6 月)。删掉或收窄那条规则;如果你只是想让它不进检索,就改用 .cursorindexingignore

新文件多久会自动出现? Cursor 用 Merkle-tree 差分,按几分钟一次(大约 5-10 分钟)的轮询周期自动 resync 改动过的文件。先保存文件,不想等就跑 “Cursor: Resync Index”。

现在去哪里看索引状态? Cursor Settings → Indexing 显示同步状态和已索引文件数;Indexing & Docs → “View included files” 能列出到底哪些路径进了索引。(旧版本把这块嵌在 Settings → Features → Codebase Indexing 下。)

Cmd+K 到底用不用索引? 不用。Cmd+K(inline edit)只对当前文件和你的选区生效。全仓检索只在 chat、Composer 和 Agent 里跑。Cmd+K 编辑里”缺”一个全仓文件是正常的——用 @ 挂上,或者改用 Agent。

.cursorignore.cursorindexingignore 我该用哪个? .cursorignore = 全屏蔽(不检索、不 Tab、不 Agent、不 @)。.cursorindexingignore = 只把它移出检索索引;仍可被 @ 和 Agent 取到。偶尔要引用的大型生成目录用后者。

相关阅读

标签: #排查 #Cursor #排查 #上下文面板