Skip to content

文件读取门

它是什么

文件读取门是一个 PreToolUse 钩子,用于拦截 Claude 的 Read 工具调用。当 Claude 尝试读取数据库中已有先前观察记录的文件时,该门会阻止读取,而是显示该文件过去工作的简明时间线。然后 Claude 决定获取所需上下文的最廉价路径。

这是 progressive disclosure 的具体实现——先展示已有内容,让代理决定获取什么。


运作方式

Claude calls Read("src/services/worker-service.ts")

   PreToolUse hook fires

   File size < 1,500 bytes? ──→ Allow read (timeline costs more than file)
         ↓ No
   Project excluded? ──→ Allow read
         ↓ No
   Query worker: GET /api/observations/by-file

   No observations found? ──→ Allow read
         ↓ Has observations
   Deduplicate (1 per session)
   Rank by specificity
   Limit to 15

   DENY read with timeline

当传送门启动时,Claude会看到这样的消息:

Current: 2026-04-07 3:25pm PDT
Read blocked: This file has prior observations. Choose the cheapest path:
- Already know enough? The timeline below may be all you need (semantic priming).
- Need details? get_observations([IDs]) -- ~300 tokens each.
- Need current code? smart_outline("path") for structure (~1-2k tokens),
  smart_unfold("path", "<symbol>") for a specific function (~400-2k tokens).
- Need to edit? Use smart tools for line numbers, then sed via Bash.

### Apr 5, 2026
42301 2:15pm  Fixed database connection pooling
42298 1:50pm  Refactored worker startup sequence

### Mar 28, 2026
41890 4:30pm  Added health check endpoint

决策树

Claude在看到时间表后有四个选项,从最便宜到最贵排序:

选项token消耗何时使用
语义启动0 额外时间轴标题提供给 Claude 足够的信息以继续
get_observations([IDs])每次约300需要来自过去工作的具体细节
smart_outline / smart_unfold~1-2k需要当前的代码结构或特定函数
完整文件读取5k-50k自观察以来文件已发生重大变化

在实际操作中,大多数文件读取都是在语义启动或 get_observations 级别解决的,从而每次交互节省数千个 token。


用于时间推理的当前日期/时间

时间轴的第一行包括当前日期和时间:

Current: 2026-04-07 3:25pm PDT

这使 Claude 能够推理观察结果相对于现在的新旧程度。例如:

  • 今天的观察 -- 可能仍然准确,语义启动是安全的
  • 上周的观察 -- 可能准确,详情请查看 get_observations
  • 几个月前的观察 -- 文件可能已更改,请考虑使用 smart_outline 或完整读取

时间戳格式与会话开始上下文头 (YYYY-MM-DD time timezone) 匹配,因此 Claude 在整个会话中看到一致的时间标记。


token经济学

一个典型的源文件完整读取的成本为 5,000-50,000 个 token。文件读取门将其替换为:

组件token
时间轴标题 说明~120
15 条观察记录约 250
总时间表~370

如果 Claude 需要更多细节,它会获取每条约 300 个标记的单独观察记录。即使获取 3 条观察记录,总计约 1,270 个标记——相比读取整个文件,仍然节省 75-97%

现实世界的例子

没有门(阅读 worker-service.ts):

Read: 18,000 个 token

与大门一起:

Timeline:       370 个 token
+ 2 observations: 600 个 token
Total:          970 个 token (95% savings)

特异性排名

并非关于文件的所有观察都是同等相关的。门会根据每个观察与目标文件的具体相关性对其进行评分:

信号分数奖励
文件被修改(不仅仅是读取)2
观察覆盖 3 个或更少 的总文件2
观察覆盖 4-8 个文件1
观察涵盖 9 个文件(类似调查)0

得分较高的观察会优先出现在时间线上。一个文件是主要修改目标的观察,其排名高于一个文件仅偶然被读取并伴随其他20个文件的观察。


配置

小文件绕过

小于 1,500 字节 的文件总是可以直接通过网关而不会被拦截。在这个大小下,时间线(约 370 个标记)的成本将超过直接读取文件的成本。这个阈值在 src/cli/handlers/file-context.ts 中是硬编码的。

项目排除

CLAUDE_MEM_EXCLUDED_PROJECTS 中的模式匹配的项目将完全跳过此门。请在 ~/.claude-mem/settings.json 中配置此项:

json
{
  "CLAUDE_MEM_EXCLUDED_PROJECTS": "/tmp/*,/scratch/*"
}

如何关闭门

文件读取门作为 Read 工具匹配器上的 PreToolUse 钩子实现。要禁用它,请从钩子配置中删除 Read 匹配器条目:

  1. 打开你的 Claude Code 设置:

    ~/.claude/settings.json
  2. hooks.PreToolUse 下找到 claude-mem hooks 部分,并移除带有 Read 匹配器的条目。

或者,如果你想保留门控但在特定读取时绕过它,Claude 可以请求你允许该读取——门控的拒绝决定会呈现给用户,用户可以覆盖它。

禁用门控意味着 Claude 每次都会读取完整文件,这会增加 token 使用量,但确保它始终看到最新的代码。这对于小型项目或观察数据稀少的情况是一个合理的选择。


它是如何组合在一起的

文件读取门是claude-mem分层上下文策略的一部分:

  1. 会话开始:注入最近观察的时间轴(第1层——元数据)
  2. 文件读取门:通过观察历史截获读取(第1层——元数据)
  3. get_observations:按需获取特定观察详情(第2层——详细信息)
  4. smart_outline / smart_unfold:高效阅读当前代码结构(第3层 -- 源码)
  5. 完整文件读取:当其他方法都不足时的最后手段

每一层的费用逐渐增加。这个门确保Claude从最便宜的层开始,并且只有在需要时才升级。