PreCompact 与 PostCompact Hook 触发环节拆解(context 压缩全流程与工程实践)

Claude Code 的 PreCompact 与 PostCompact 都属于会话生命周期里”context 压缩(compaction)”这一道工序,但一个在压缩动作启动前触发、一个在压缩完成、摘要已生成后触发。把这两个 hook 放在一起看,才能完整覆盖”会话在快要撑爆 context window 时,会按什么顺序发生什么、哪一步可以被业务脚本拦截或补充信息”。

一、context 压缩全流程中的两个触发位

Claude Code 在检测到上下文接近模型窗口上限、或用户手动调用 /compact 时,会把会话历史做摘要化压缩。整个压缩管线依次经过四步:

  1. 读取当前会话记录,估算上下文占用;
  2. 触发 PreCompact hook(matcher 为 auto 或 manual);
  3. 调用一个只读 agent 生成摘要,补回 plan、CLAUDE.md 等关键信息,并写入 compact_boundary;
  4. 触发 PostCompact hook。

PreCompact 落在”摘要 prompt 生成前”,这意味着脚本可以读取当前 transcript、注入自定义摘要要求,或在长事务进行中返回 exit code 2 阻断压缩。PostCompact 落在”summary 已经产生、隐藏的摘要 user message 也已经建好之后”,它的标准输出不会进入下一轮模型上下文,只能用于审计、落盘、刷新外部看板等只读动作。

Hook 触发环节 能否阻断压缩 输入关键字段 标准输出是否进入下一轮上下文
PreCompact 摘要 prompt 生成前 是(exit code 2 或返回 decision: block) trigger(auto/manual)、custom_instructions 否,仅做拦截或写盘
PostCompact summary 与 compact_boundary 建好之后 否 trigger、compact_summary 否,仅做审计与通知

需要特别区分的两种 auto 触发:主动型是 Claude Code 在 context 撑满前主动压缩,被动型是上一次请求已经返回 context 超限错误,压缩是为恢复会话而做的。阻断前者可直接跳过压缩,阻断后者会让原始错误透传到当前请求。

二、PreCompact 的三类工程实践

把 PreCompact 当作”压缩前的最后一个写入窗口”是它主要的价值。常见有三类落地。

  1. transcript 备份:在压缩吃掉旧消息前,把当前 .jsonl 会话记录复制到归档目录,便于回查被摘要丢掉的关键决策;
  2. 追加摘要要求:在 hook 中把”必须保留的字段清单”通过 custom_instructions 回写,让摘要 agent 不漏关键变量名、接口路径、未完成 TODO;
  3. 长事务保护:在涉及长跑事务(部署、迁移、批量回归)时阻断自动压缩,避免事务中间上下文被切走、模型丢失当前进度。

下面这段是 PreCompact 自动模式备份 transcript 的精简配置:

{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto",
        "hooks": [
          {
            "type": "command",
            "command": "cp \"$CLAUDE_TRANSCRIPT_PATH\" \"$HOME/.claude/backups/$(date +%Y%m%d-%H%M%S)-$CLAUDE_SESSION_ID.jsonl\""
          }
        ]
      }
    ]
  }
}

配置生效后,Claude Code 在每次自动压缩前都会把当前 transcript 拷贝到归档目录。备份完后再让摘要流程继续即可,不影响会话连贯性。

三、PostCompact 的三类工程实践

PostCompact 拿到的 compact_summary 字段是刚生成的完整摘要,但脚本无法再回头修改会话上下文。所以它的用法集中在”对外”。

  1. 落盘摘要:把摘要写入团队的会话归档系统或 Notion 周报,作为知识沉淀;
  2. 审计与告警:在审计敏感会话中,把摘要同步到 SIEM,配合 hookeventname 字段做事件分流;
  3. 刷新外部状态:把”会话刚被压缩过”这一事件通知到 IM 机器人或状态面板,方便团队了解当前会话经历了多少次压缩。

下面这段是 PostCompact 把摘要写入归档文件的示例:

#!/usr/bin/env bash
# PostCompact handler: archive the fresh summary
input=$(cat)
summary=$(echo "$input" | jq -r '.compact_summary // ""')
trigger=$(echo "$input" | jq -r '.trigger // "auto"')
sid=$(echo "$input"    | jq -r '.session_id')
ts=$(date -u +%Y%m%dT%H%M%SZ)
out="$HOME/.claude/summaries/${sid}-${trigger}-${ts}.md"
printf "# Session %s\n\n%s\n" "$sid" "$summary" > "$out"

把这段脚本挂到 PostCompact 的 command hook 上,每次压缩完成都能拿到一份独立的摘要快照,方便事后比对摘要质量与上下文丢失情况。

四、PreCompact 与 PostCompact 的协同模式

两者单独看都只是一段生命周期脚本,但串起来可以形成”压缩前加固 + 压缩后校核”的闭环。

协同模式 PreCompact 职责 PostCompact 职责 适用场景
审计闭环 备份 transcript 落盘摘要 长期项目的会话复盘
长会话续命 阻断自动压缩 / 注入摘要要求 通知 IM 群”刚压缩过” 跨天多轮调试
敏感信息治理 在压缩前脱敏 transcript 校验摘要里是否残留密钥 合规要求严格的行业

实操上更推荐把 PreCompact 的备份目录与 PostCompact 的摘要目录设为同一前缀(例如 ~/.claude/sessions/<sid>/),便于复盘时把”原始 transcript”与”压缩后摘要”配对查看。

五、落地时的两个易错点

第一,PostCompact 的 stdout 不会进入下一轮模型上下文,把它当作 SessionStart 用是常见误区——若希望压缩后向模型补充信息,应改在 SessionStart 的 compact matcher 里返回,否则信息只会被打印给用户。

第二,阻断 PreCompact 只能延缓主动压缩,对于已经触发 context 超限错误的被动压缩,阻断会让请求失败而不是恢复会话。判断方法很直接:PreCompact 输入里 trigger: auto 且紧邻一次 context_length_exceeded 错误时,阻断基本无效,应让它走完。

常见问题(FAQ)

Q1:PreCompact 可以阻止自动压缩吗?

可以。脚本返回 exit code 2 或输出 decision: block 即可阻止主动型自动压缩;被动型压缩会失败。

Q2:PostCompact 的输出会进入下一轮模型上下文吗?

不会。PostCompact 的 stdout 只用于审计与通知,无法影响后续会话。

Q3:两个 hook 的 matcher 怎么区分手动与自动?

matcher 接受 manual(/compact 触发)或 auto(context 撑满触发),需要分别处理时分别声明。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
套餐观察官的头像套餐观察官普通用户

相关推荐

返回顶部