【planning-with-files】核心架构与设计原理深度解析:让 AI Agent 拥有 Manus 级别的持久化规划能力
【planning-with-files】核心架构与设计原理深度解析:让 AI Agent 拥有 Manus 级别的持久化规划能力
一、引子:当 Claude Code 写完第 50 个工具调用后,它还记得最初的目标吗?
2025 年底,AI Agent 的「上下文失忆」问题被推到风口浪尖。Claude Code、Cursor、Codex 这些主流编码 Agent 在完成 50+ 工具调用后,几乎都会出现三类症状:
- 目标漂移(Goal drift)—— 「帮我做一个支持用户登录的 Todo 应用」,写到第 7 个文件时,agent 突然开始实现 OAuth 第三方登录
- 重复错误(Repeated error)—— 同一个
TypeError在 3 个文件里出现 3 次,每次 agent 都重新「第一次遇到」一次 - /clear 灾难(Context wipeout)—— 用户按
/clear清理上下文,agent 失去全部上下文,30 分钟的工作清零
这三个问题,本质上是同一个根因:LLM 的上下文窗口(context window)是 RAM,而任务规划是「工作记忆」——RAM 一断电,工作记忆就消失。
2026 年 2 月,一个叫 planning-with-files 的开源项目在 GitHub 横空出世。它把 Meta 以 20 亿美元收购的 Manus AI 的核心方法论(”Filesystem as memory”)封装成了一套可复用的 SKILL,3 个月内冲上 ⭐24,700。它的答案极其简洁却极其有效:
把任何”重要的工作记忆”写进磁盘文件。3 个文件 = 你的 Agent 整个工作日的状态。
到 2026 年 7 月 v3.2.0 发布时,它已经支持 60+ AI 编码 Agent(Claude Code/Codex/Cursor/Continue/Gemini/Kiro/OpenCode/Hermes/Pi/Mastra/FoxCode/Codebuddy/Autohand 等),并被 SkillCheck 验证、96.7% benchmark 通过率、3/3 盲评 A/B 测试胜出。本文将深度拆解它是如何做到的。
二、项目定位与核心价值
2.1 一句话定义
planning-with-files 是一个持久化文件规划 Skill(不是框架、不是库),通过在 AI Agent 的工作目录维护 task_plan.md / findings.md / progress.md 三个文件,配合 5 个原生 Hook 时机(UserPromptSubmit / PreToolUse / PostToolUse / Stop / PreCompact),让 Agent 在 上下文清除(/clear)、崩溃、跨会话、跨 IDE 等任何异常场景下都能精确恢复工作记忆。
2.2 能力矩阵
| 能力维度 | 解决的问题 | 技术手段 |
|---|---|---|
| 抗 /clear 灾难 | 用户清理上下文后状态归零 | 3-File 模式 + progress.md 增量日志 |
| 抗 Goal drift | 50+ 工具调用后跑偏 | PreToolUse 钩子重新读 plan 头 30 行 |
| 抗 Repeated error | 同一错误反复出现 | task_plan.md 的 ## Errors Encountered 表 |
| 抗 Context rot | 长会话性能下降 | findings.md 卸载研究发现到磁盘 |
| 抗 Crash 闪退 | Agent 异常退出 | task_plan.md 状态机 + 阶段标记 |
| 抗 并行会话冲突 | 多 Agent 同时改 plan | .planning/<date>-<slug>/ slug 模式 |
| 抗 计划篡改 | 攻击者改 plan 注入 prompt | SHA-256 哈希见证(attest-plan.sh) |
| 抗 Agent 提早停止 | 任务没完成 agent 自己结束 | v3 --gated 模式 + 5 条件门控决策表 |
2.3 仓库关键统计(截至 2026-07-06)
| 指标 | 数值 |
|---|---|
| Stars | 24,711 |
| Forks | 2,106 |
| License | MIT |
| Languages | Python (session-catchup.py) + Shell (POSIX) + PowerShell (Windows) + Markdown |
| Size | 11,070 KB |
| Pushed | 2026-07-03 |
| Created | 2026-01-03 |
| 当前版本 | v3.2.0 |
| Benchmark | 96.7% pass rate (v2.21.0, claude-sonnet-4-6) |
| 支持 Agent 数 | 60+ (Claude Code/Codex/Cursor/Continue/Gemini/Kiro/OpenCode/Hermes/Pi/Mastra/FoxCode/Codebuddy/Autohand/OpenClaw/BoxLite/Copilot/ADAL/Antigravity/Factory/KiloCode/Mastra 等) |
| 测试套件 | 186 passed, 5 skipped, 0 failed (v3.2.0) |
三、整体架构:3-File 模式 + 5-Hook 调度 + 双轨执行环境
3.1 顶层架构图
flowchart TB
subgraph A[用户层]
U[用户在 Claude Code/Codex/Cursor 等 60+ Agent 中输入 prompt]
end
subgraph B[Hook 调度层 / 5 个原生时机]
H1[UserPromptSubmit<br/>注入完整 plan 头 + 进度]
H2[PreToolUse<br/>Write/Edit/Bash/Read 前重读 plan 头 30 行]
H3[PostToolUse<br/>Write/Edit 后提醒更新 progress.md]
H4[Stop<br/>检查完成度,v3 模式下阻断提早停止]
H5[PreCompact<br/>/compact 前提醒刷新 progress.md]
end
subgraph C[3-File 持久化层]
F1[task_plan.md<br/>阶段 + 状态 + 决策 + 错误表]
F2[findings.md<br/>研究发现 + 文档摘要 + 备选方案]
F3[progress.md<br/>会话日志 + 测试结果 + 错误日志]
end
subgraph D[v3 元数据层 / .planning/slug/]
M1[.mode 文件<br/>autonomous / gated 标记]
M2[.nonce 文件<br/>会话随机数分隔符]
M3[.attestation 文件<br/>SHA-256 哈希值]
M4[.stop_blocks<br/>Stop 阻断计数器]
end
subgraph E[执行环境层 / 双轨]
E1[POSIX Shell<br/>init-session.sh / inject-plan.sh<br/>check-complete.sh / attest-plan.sh<br/>gate-stop.sh / ledger-append.sh]
E2[PowerShell<br/>同名 .ps1 镜像]
E3[Python 3<br/>session-catchup.py<br/>跨 IDE 历史恢复]
end
subgraph F[外部安全层]
S1[XDG_CACHE_HOME/pwf-sha<br/>哈希缓存目录]
S2[Containment guard<br/>路径必须在项目根内]
S3[SLUG_RE 白名单<br/>^[A-Za-z0-9_][A-Za-z0-9._-]*$]
end
U --> H1
H1 -->|读取| F1
H1 -->|读取| F3
H2 -->|读取| F1
H3 -->|写入提醒| F3
H4 -->|读取| F1
H4 -->|读取| M1
H4 -->|读取| M4
H5 -->|读取| F3
F1 -.状态机.-> D
F2 -.研究归档.-> D
F3 -.会话日志.-> D
E1 -->|执行| B
E2 -->|执行| B
E3 -->|恢复| F3
M3 -->|校验| S1
B -->|路径校验| S2
B -->|slug 校验| S33.2 3-File 模式 —— 整个 Skill 的灵魂
planning-with-files 的方法论浓缩成一句话就是 Manus 的核心 5 原则:
| Manus 原则 | planning-with-files 实现 |
|---|---|
| Filesystem as memory | 3 个 markdown 文件在磁盘 |
| Attention manipulation | PreToolUse 钩子每次工具调用前重读 plan |
| Error persistence | task_plan.md 中的 ## Errors Encountered 表 |
| Goal tracking | task_plan.md 中的 ### Phase N: [Title] + **Status:** |
| Completion verification | Stop 钩子 + v3 完成门控检查所有 phase 都是 complete |
具体到 3 个文件的职责分工(来自 templates/task_plan.md / progress.md / findings.md):
| 文件 | 角色 | 关键字段 | 写入时机 |
|---|---|---|---|
task_plan.md | 阶段路线图 | ## Goal / ## Current Phase / ### Phase N / ## Key Questions / ## Decisions Made / ## Errors Encountered | 任务开始 + 每个阶段切换时 |
findings.md | 研究归档 | 文档摘要 / API 测试结果 / 备选方案对比 | 每次发现新信息时 |
progress.md | 会话日志 | ## Session: [DATE] / ### Phase N: [Title] / ## Test Results / ## Error Log / ## 5-Question Reboot Check | 每次工具调用后(PostToolUse 提醒) |
这种 3-File 设计的精妙之处在于:它把 LLM 的「工作记忆」从上下文窗口卸载到磁盘,让 LLM 的 RAM(context window)只保留”当前阶段的决策”,而所有”历史状态”都在磁盘上可以按需加载。
四、5 个 Hook 时机的精确调度
planning-with-files 的工程精髓在于它完整利用了 Agent 平台的 5 个原生 Hook 时机,每个时机都对应一种特定的”提醒”或”拦截”。
4.1 5 个 Hook 时机总览
sequenceDiagram
participant U as 用户
participant LLM as LLM Agent
participant Hook as Claude Code Hook 系统
participant Script as scripts/*.sh
participant FS as 3-File 磁盘
U->>LLM: 输入 prompt
LLM->>Hook: UserPromptSubmit
Hook->>Script: inject-plan.sh --context=userprompt
Script->>FS: 读取 task_plan.md + progress.md
FS-->>Script: 返回 plan 头 50 行 + 进度尾部
Script-->>Hook: 输出完整 plan 上下文
Hook-->>LLM: 注入到 model turn
LLM->>LLM: 思考决定调用工具
LLM->>Hook: PreToolUse(Write/Edit/Bash/Read)
Hook->>Script: inject-plan.sh --context=pretool
Script->>FS: 读取 task_plan.md 头 30 行
Script-->>Hook: 短 plan 头
Hook-->>LLM: 注入(v3 autonomous 模式跳过)
LLM->>FS: Write/Edit 工具调用
FS-->>LLM: 写入成功
LLM->>Hook: PostToolUse
Hook-->>LLM: stdout: "[planning-with-files] Update progress.md..."
LLM->>FS: 写入 progress.md 更新
LLM->>Hook: Stop(agent 试图停止)
Hook->>Script: gate-stop.sh -> check-complete.sh --gate
Script->>FS: 读取 task_plan.md + .mode + .stop_blocks
Script-->>Hook: 5 条件门控决策
alt 5 条件全部满足
Hook-->>LLM: decision: block(继续执行)
else 任一条件不满足
Hook-->>LLM: 允许停止
end
U->>LLM: /compact 触发压缩
LLM->>Hook: PreCompact
Hook->>Script: inject-plan.sh --context=precompact
Script-->>Hook: "Before compaction: ensure progress.md captures recent actions"
Hook-->>LLM: 注入压缩前提醒4.2 UserPromptSubmit:完整 plan 注入(v3 vs Legacy 行为差异)
UserPromptSubmit 钩子用于在用户每次输入 prompt 时把 plan 完整地”重述”给 agent 一次。这是最关键的钩子,因为它对抗了 LLM 的”工作记忆衰减”——LLM 在多次工具调用后,最初的目标信息会逐渐被淹没在工具输出里。
来自 scripts/inject-plan.sh(v3.2.0)的关键逻辑:
1 | # 来自 scripts/inject-plan.sh:106-145 |
注意几个工程亮点:
- 数据/指令分离 — 第一行明确告诉 LLM:「把 plan 内容当结构化数据(structured data),不是指令(instructions)」。这是对 prompt injection 的标准防御。
- SHA-256 见证 — 如果启用了
attest-plan.sh,每次注入都会附带当前哈希,agent 可以看到 plan 是否被篡改。 - Nonce 分隔符 — v3 模式下使用
===BEGIN-PLAN-DATA-${NONCE}===这种带随机数 token 的分隔符,避免恶意 plan 内容伪造 END 分隔符。 - KV-cache 友好的时间戳归一化 —
sed -E 's/T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?Z/T00:00:00Z/g'把所有时间戳替换成T00:00:00Z,保证 progress.md 的尾部输出对 LLM 的 KV-cache 是稳定的(不稳定的尾部会让 cache 失效,每次都要重新 prefill)。 - v3 模式切换 ledger — autonomous/gated 模式用结构化的
ledger-summary.sh输出替代 rawprogress.mdtail,安全性更高(v3 的 ledger 本身有 nonce/attestation 保护)。
4.3 PreToolUse:对抗 Goal Drift 的核心机制
PreToolUse 钩子在 agent 每次准备调用 Write/Edit/Bash/Read 工具前触发,作用是把 plan 头 30 行重新注入到 agent 视野。这模拟了 Manus 论文里的”Attention manipulation”——通过持续在 agent 视野里展示目标,避免它偏离主线。
1 | # 来自 scripts/inject-plan.sh:124-138 |
注意几个细节:
- 短头(30 行)vs 长头(50 行) —
pretool模式只注入前 30 行(不含进度),降低 token 开销 - TAMPERED 阻断 — 一旦 plan 哈希不匹配,整个钩子输出
[PLAN TAMPERED — injection blocked],agent 自然不会执行一个”被篡改的计划”指定的工具 - v3 模式跳过 — autonomous/gated 模式下,per-tool-call 注入被完全关闭(
exit 0)—— 因为强模型不需要每次都重述 plan,per-tool-call 注入反而是 prompt injection 放大器(来自 security B1)
4.4 PostToolUse:自动提醒更新 progress.md
1 | # 来自 SKILL.md hooks: PostToolUse 段 |
这是 5 个钩子里最简洁的一个——只在 Write/Edit 工具后,stdout 一句提醒。它的设计哲学是:不强制 agent 更新 progress.md(那样会破坏 agent 的自主性),而是给一个软提示让 agent 自觉维护。
4.5 Stop:v3 完成门控(5 条件决策表)
Stop 钩子是 planning-with-files 在 v3.0 引入的完成门控机制。它通过一个薄分派器 gate-stop.sh 调到 check-complete.sh --gate:
1 | # 来自 scripts/gate-stop.sh(v3 完整代码) |
而 check-complete.sh 的 5 条件门控决策表是 v3 的灵魂(来自 scripts/check-complete.sh 注释):
1 | Gate mode (v3, --gate flag): |
5 条件必须全部满足才会真正阻断 agent 停止。这个设计极其精妙:
| 条件 | 防御的场景 | 设计意图 |
|---|---|---|
1. .mode 包含 gate | 用户没主动开启 gated 模式 | opt-in 原则——v3 默认不打断 |
| 2. 存在 in_progress 阶段 | 已经全部 complete | 没活干了自然停止 |
3. stop_hook_active=false | 正在被前一个 Stop 钩子重试 | 防无限循环 |
| 4. 阻断计数 < 20 | 一直阻断导致死循环 | 防御性熔断 |
| 5. ledger 自上次阻断后有推进 | ledger 没动 = 真卡住了 | 真卡住 → 放行(防止 hallucination 锁死) |
这种”5 条件全 AND + 软提示兜底”的设计是 2026 年最前沿的 Agent Termination Oracle 实现。
4.6 PreCompact:/compact 前的最后一道保险
1 | # 来自 scripts/inject-plan.sh:104-113 |
PreCompact 钩子专门为 /compact(用户手动压缩上下文)设计。Claude Code 在压缩前会触发这个钩子,planning-with-files 输出提醒让 agent 在压缩完成前把关键进度刷进 progress.md。压缩后,agent 失去大部分上下文,但 progress.md 还在磁盘上,下次 prompt 时 UserPromptSubmit 会把 plan + progress 重新加载。
这是对抗”长会话性能下降”(context rot)的关键机制。
五、核心引擎一:v3 Attestation 安全子系统
5.1 为什么需要哈希见证?
v3 之前,planning-with-files 的一个已知风险是 prompt injection amplification:
- 攻击者(恶意网页/外部 API 返回值)写入
task_plan.md一段看起来像”指令”的文本 - 每次
UserPromptSubmit钩子把 plan 注入到 model turn - LLM 看到的是”plan 内容”,但其实是被攻击者注入的恶意指令
v3 的解法是SHA-256 哈希见证——attest-plan.sh 锁定 plan 的哈希值,任何后续修改必须重新 attest,否则 inject-plan.sh 会输出 [PLAN TAMPERED — injection blocked]。
5.2 Attest 工作流
sequenceDiagram
participant U as 用户
participant LLM as LLM Agent
participant A as attest-plan.sh
participant H as inject-plan.sh
participant FS as 磁盘
Note over U,LLM: Step 1: 任务开始,用户首次确认 plan
U->>LLM: /plan-attest
LLM->>A: sh scripts/attest-plan.sh
A->>FS: 读取 task_plan.md
A->>FS: 计算 SHA-256
A->>FS: 写入 .attestation (或 .plan-attestation)
A-->>LLM: "Plan attested: abc123..."
Note over U,LLM: Step 2: 正常运行,每次钩子检查
LLM->>H: UserPromptSubmit
H->>FS: 读取 .attestation
H->>FS: 计算当前 plan SHA-256
alt 哈希匹配
H-->>LLM: 注入 plan + "Plan-SHA256: abc123..."
else 哈希不匹配
H-->>LLM: "[PLAN TAMPERED — injection blocked]"
H-->>LLM: "expected=abc123... actual=def456..."
H-->>LLM: "Run /plan-attest to re-approve, or restore from git"
end
Note over U,LLM: Step 3: 故意修改 plan(合法场景)
U->>LLM: 修 plan
LLM->>A: sh scripts/attest-plan.sh(重新见证)
A-->>LLM: 新的哈希,钩子重新通过5.3 关键源码:attest-plan.sh 的双层容错
1 | # 来自 scripts/attest-plan.sh:17-45 |
注意几个工程亮点:
- 双哈希工具容错 — 先试 Linux 的
sha256sum,再 fallback 到 macOS 的shasum -a 256(来自 v2.30+ 的多次跨平台 bug 修复) - mtime 缓存优化 —
inject-plan.sh用 mtime 作为缓存 key($KEY=$(printf "%s" "$PLAN_FILE" | sha256sum | cut -c1-16)),只对 mtime 变化的 plan 重新哈希,避免每次钩子都全文件哈希的开销 - gated 模式强制 re-hash —
case "$MODE" in gated) REHASH=1 ;;—— gated 模式下即使 mtime 缓存命中也强制重新计算(来自inject-plan.sh:91-95),因为终止决策 oracle 不能信任过期缓存
5.4 SHA 缓存目录与安全
1 | # 来自 scripts/inject-plan.sh:75-83 |
注意:SHA 缓存从原来的 /tmp/pwf-sha(v2 时代)搬到了 $XDG_CACHE_HOME/pwf-sha。这是 v2.40 的一次安全强化——/tmp 目录是多用户共享的(security A1.2:临时文件投毒),放用户私有目录后,攻击者无法通过 /tmp 注入伪造的 SHA 缓存条目来绕过见证。
六、核心引擎二:Containment Guard 路径安全子系统
6.1 攻击面:symlink 跨越项目根
v2 时代发现一个安全漏洞(标记为 security A1.3):slug 模式 .planning/<date>-<slug>/ 下的 task_plan.md 如果是软链接指向 /etc/passwd 或 /home/user/.ssh/id_rsa,那么 inject-plan.sh 会傻傻地把目标文件哈希、注入到 model turn。
6.2 解决方案:双层防御
inject-plan.sh 实现了4-级路径 canonicalizer + 1 个 containment guard(来自 inject-plan.sh:30-68):
1 | canonicalize() { |
注意几个工程亮点:
- 4 级 fallback —
realpath→readlink -f→python3→python,覆盖 Linux/macOS/WSL/Git Bash/Alpine 各种环境 - happy path 不 spawn python — Linux/WSL/Git Bash 现代 macOS 都有
realpath,python 只在 fallback 时才启动 - fail-open 策略 — 4 级都失败时返回 0(放行),保持 legacy 字节级兼容
- SLUG_RE 兜底 —
^[A-Za-z0-9_][A-Za-z0-9._-]*$限定 slug 只能含安全字符,攻击者无法用../路径穿越 - 从
"."解析根 — 不从$PWD字符串解析(Windows MSYS 8.3 短名//tmp别名会导致两个解析路径”看起来不同但实际相等”)
七、核心引擎三:双轨执行环境(POSIX Shell + PowerShell + Python 3)
planning-with-files 的另一个工程亮点是完整的 Windows 兼容。每个 .sh 脚本都有一个 .ps1 镜像:
1 | $ ls scripts/ | head -30 |
1 | # 来自 scripts/attest-plan.sh:62-80 (POSIX shell 模式) |
而对应的 PowerShell 版本(scripts/attest-plan.ps1)实现了完全相同的接口(--show / --clear / 默认 attest),但用 PowerShell 习惯的 param([string]$Mode = "attest") 语法。
为什么需要 Python 3 入口? —— session-catchup.py 跨 IDE 解析用户历史会话(Claude Code 的 .claude/projects/*.jsonl 和 OpenCode 的 ~/.local/share/opencode/storage/session/),需要 JSONL 解析 + 跨平台路径处理,shell 做这件事太痛苦。这种Shell + PowerShell + Python 3 的三件套是真正能”开箱即用”的开源工程范例。
八、核心引擎四:跨 60+ AI Agent 的 SKILL.md 自发现机制
8.1 为什么需要 60+ 适配器?
Claude Code / Codex / Cursor / Continue / Gemini 等 Agent 的 SKILL.md 格式几乎都遵循 Anthropic 2026 年推出的 skills 协议,但每个 Agent 的:
- Hook 字段名(
UserPromptSubmitvsuser_prompt_submit) - 环境变量(
${CLAUDE_SKILL_DIR}vs${CODEX_PLUGIN_ROOT}) - 路径约定(
~/.claude/skills/vs~/.codex/skills/) - Stop 钩子阻塞协议(
{"decision":"block"}vs{"continue": false})
都不一样。planning-with-files 的解法是自发现(self-discovery)模式:
1 | # 来自 SKILL.md hooks.UserPromptSubmit(Claude Code 适配) |
注意 || SH=$(ls ... | head -1) —— 先检查环境变量,再 fallback 到常见安装路径。这就是所谓的 “proven self-discovery pattern”。
8.2 SKILL.md 双语/多语支持
skills/ 目录下有 6 种 SKILL.md 变体:
1 | $ ls skills/ |
每个变体的结构 + 钩子配置完全一致,只是 SKILL.md 描述(description: 字段)翻译成本地语言。这让中文用户输入 “规划” 也能触发这个 skill。
8.3 关键发现:v3.1.3 修复了 SKILL.md frontmatter YAML 兼容性
v3.1.3 release notes 揭示了一个极其隐蔽的工程教训:
Hotfix: SKILL.md frontmatter was invalid YAML in v3.1.2. The v3.1.2 description refresh added a colon, and the English SKILL.md kept
descriptionunquoted, so YAML rejected the frontmatter (“mapping values are not allowed here”), which could break skill loading and the model-triggering description. v3.1.3 quotes the description (matching the already-quoted translated variants; the parsed value is identical) across the canonical file and the seven English IDE variants, and addstests/test_skill_frontmatter_valid.pyto validate every SKILL.md frontmatter as YAML.
这印证了我们之前写博客时遇到的 YAML 嵌套双引号陷阱 —— 即便是这种 ⭐24k 的明星项目,也会在 frontmatter 上踩雷,必须 tests/test_skill_frontmatter_valid.py 这种程序化校验来防住。
九、session-catchup.py:跨 IDE 历史恢复
9.1 用例
用户在 Claude Code 里跑了 30 分钟任务,然后切到 OpenCode(或者退出后第二天重新打开 Claude Code)。这时候 LLM 的上下文已经完全清空。session-catchup.py 做的事情是:
- 找到最新的
task_plan.md/findings.md/progress.md修改 - 找到那个时间点之后的所有 session(
.claude/projects/*.jsonl或~/.local/share/opencode/storage/session/) - 把这些 session 里的对话导出成 markdown,让新 agent 能”读历史”
9.2 关键源码(来自 scripts/session-catchup.py:1-130)
1 | PLANNING_FILES = ['task_plan.md', 'progress.md', 'findings.md'] |
注意几个工程亮点:
- 跨 IDE 抽象 —
detect_ide()通过OPENCODE_DATA_DIR环境变量和~/.claude/~/.local/share/opencode目录存在性,自动识别当前是哪个 IDE - 过滤 agent- 前缀* — Claude Code 的 sub-agent 会话以
agent-开头,脚本只关心主会话 - 按 mtime 排序 — 不依赖 session 文件名,直接按修改时间倒序,最新的在最前
- 跨平台路径处理 —
get_project_dir_claude()专门处理 Windows Git Bash 路径(/c/Users/...→C:/Users/...),这正是 v3.2.0 release notes 提到的修复点:
session-catchup.py, the mechanism behind “resume after/clear,” never sanitized Windows-style paths correctly and had no explicit encoding on three reads, so it silently did nothing on Windows with no error.
9.3 增量扫描算法
1 | # 来自 scripts/session-catchup.py 中的 scan_for_planning_update |
这个函数用了一个非常聪明的”快扫描”策略:只关心 Write/Edit 工具调用,扫描到最后一个 task_plan.md / progress.md / findings.md 写入就停。这样可以用 O(n) 一次扫描 + 一次 JSON 解析定位关键时间点,避免解析整个 session 文件。
十、Hook 链路的端到端数据流
下图展示了从用户输入 prompt 到 agent 完成工具调用的完整数据流(v3 模式):
sequenceDiagram
participant U as 用户
participant LLM as LLM Agent
participant UP as UserPromptSubmit<br/>(inject-plan.sh)
participant PT as PreToolUse<br/>(inject-plan.sh)
participant POT as PostToolUse<br/>(shell scalar)
participant ST as Stop<br/>(gate-stop.sh)
participant AT as attest-plan.sh
participant FS as 3-File 磁盘
U->>LLM: "实现 JWT 登录"
LLM->>UP: 触发
UP->>FS: 读取 .mode (autonomous)
UP->>FS: 读取 .attestation
UP->>FS: hash 校验 task_plan.md
UP->>FS: 读取 task_plan.md 头 50 行
UP->>FS: 读取 ledger-summary.sh 输出
UP-->>LLM: 注入 plan + ledger summary
LLM->>LLM: 思考:phase 1 = "实现 JWT 中间件"
LLM->>PT: 准备调用 Write("auth/jwt.py")
Note over PT: v3 autonomous 模式:per-tool-call 注入关闭
PT-->>LLM: exit 0 (无注入)
LLM->>FS: Write("auth/jwt.py")
FS-->>LLM: 写入成功
LLM->>POT: PostToolUse 触发
POT-->>LLM: "[planning-with-files] Update progress.md..."
LLM->>FS: Write("progress.md") 记录本次完成
LLM->>U: 报告完成
LLM->>ST: Stop 触发
ST->>FS: 读取 .mode (autonomous gate)
ST->>FS: 读取 .stop_blocks (0 < 20)
ST->>FS: 检查 in_progress phase
alt phase 1 仍是 in_progress
ST-->>LLM: decision=block (继续)
LLM->>LLM: 自动继续执行 phase 2
else 所有 phase complete
ST-->>LLM: 允许停止
end十一、与同类项目对比
planning-with-files 在 Coding Agent 生态里不是孤例。我们对比 3 个相邻项目:
11.1 对比矩阵
| 维度 | planning-with-files | Memori (Cognee 同类) | LangChain Memory | Cursor .cursorrules |
|---|---|---|---|---|
| 形态 | SKILL(Claude Code 插件) | Python 库 | Python 框架抽象 | Cursor 配置文件 |
| 持久化介质 | 3 个 .md 文件 | SQLite + 向量库 | 内存 + Redis/Postgres | 单一 .md 文件 |
| 触发方式 | 5 个原生 Hook 时机 | 显式 API 调用 | Python 装饰器 | Cursor 启动加载 |
| 上下文恢复 | session-catchup.py 跨 IDE | 显式 query | 显式 retrieve | 启动时读 .cursorrules |
| 抗篡改 | SHA-256 见证 | 数据库权限 | 应用层 | 无 |
| 跨 Agent 兼容 | 60+ Agent | 任何 Python Agent | 仅 LangChain | 仅 Cursor |
| 完成门控 | v3 5 条件决策表 | 无 | 无 | 无 |
| 学习成本 | 5 分钟(装 + 跑) | 1 小时+ | 1 天+ | 30 分钟 |
| 适配范围 | 任何 5+ 工具调用任务 | 长期 agent 记忆 | 对话 chatbot | 单一项目编码 |
11.2 设计差异深度分析
planning-with-files vs Memori/Cognee:
- Memori/Cognee 是”长期记忆基础设施“——它们在 LLM 调用之间维护一个结构化的、可查询的知识库(向量库 + 实体关系图)。典型用例是 chatbot 的”用户偏好持久化”。
- planning-with-files 是”任务规划工作流“——它关注的是单次任务的执行过程,用 3-File 模式给 agent 提供”工作记忆的纸质备份”。它不维护任何结构化知识库,只维护人类可读的 markdown。
- 核心差异:Memori 的”memory”是数据,planning-with-files 的”memory”是流程。
planning-with-files vs LangChain Memory:
- LangChain Memory 是应用层抽象,把 memory 抽象成
ConversationBufferMemory/ConversationSummaryMemory/VectorStoreMemory等接口,开发者需要主动调用。 - planning-with-files 是Agent 平台层抽象,通过 Hook 时机自动注入到 agent 的 prompt,开发者零调用。
- 这种”用户透明“的设计哲学是 planning-with-files 在 ⭐24k 时还能保持 96.7% benchmark 通过率的原因——它不要求用户改变编程模型。
planning-with-files vs Cursor .cursorrules:
.cursorrules是单文件静态规则(如”always use TypeScript”),Cursor 启动时全量加载一次。- planning-with-files 是3 文件动态状态(plan/findings/progress),每次 prompt 增量注入。
.cursorrules完全不支持完成门控、跨会话恢复、攻击防护。- 核心差异:
.cursorrules是”项目元数据“,planning-with-files 是”Agent 操作系统的进程状态“。
11.3 一句话总结对比
Memori 解决”agent 跨任务的记忆”问题;LangChain 解决”开发者集成 memory 的 API”问题;.cursorrules 解决”项目规范传递”问题;planning-with-files 解决”agent 在单次任务中不丢失目标”问题。
这四者完全正交不重叠,一个完整的 AI Agent 系统可以同时使用 4 个。
十二、优缺点分析
12.1 架构层面:简洁性 vs 扩展性
| 维度 | 优势 | 代价 |
|---|---|---|
| 架构简洁性 | ⭐⭐⭐⭐⭐ | ⭐⭐☆☆☆ |
| 可扩展性 | ⭐⭐☆☆☆ | ⭐⭐⭐⭐☆ |
| 学习曲线 | ⭐⭐⭐⭐⭐(5 分钟上手) | — |
| 跨平台支持 | ⭐⭐⭐⭐☆(Shell+PS1+Python) | 双倍维护成本 |
| Hook 时机利用 | ⭐⭐⭐⭐⭐(5/5 用上) | 依赖 Agent 平台能力 |
| 测试覆盖 | ⭐⭐⭐⭐⭐(186 tests passing) | 每个 PR 都要跑全套 |
架构简洁性极佳 —— 整个核心就是 6 个 shell 脚本 + 1 个 Python 脚本 + 6 个 SKILL.md 变体。没有数据库、没有消息队列、没有网络通信,全部基于”文件 + Hook”。
可扩展性受限 —— 因为依赖各 Agent 平台的 Hook 时机,未来 Agent 平台升级或新 Agent 出现时需要写新 SKILL.md 适配器。这就是为什么仓库里有 60+ 适配器。
12.2 性能层面:轻量 vs 功能深度
| 维度 | 优势 | 代价 |
|---|---|---|
| Token 开销 | ⭐⭐⭐⭐☆(pretool 只注入头 30 行) | userprompt 仍注入 50 行 |
| 磁盘 IO | ⭐⭐⭐⭐☆(mtime 缓存 + 分层注入) | 每次 tool call 仍读 FS |
| 延迟 | ⭐⭐⭐⭐☆(Hook 全是同步 <10ms) | gated 模式 + SHA 哈希增加 ~5ms |
| KV-cache 友好 | ⭐⭐⭐⭐⭐(时间戳归一化) | — |
极低延迟 —— Hook 全部同步执行,单次 pretool 注入在标准 SSD 上 < 10ms。和上下文窗口几秒的 prefill 延迟相比可忽略。
v3 模式增加少量开销 —— autonomous/gated 模式需要 SHA-256 哈希 + ledger summary,但 mtime 缓存把绝大多数钩子的哈希计算消除了。
12.3 维护性:测试 vs 双轨
| 维度 | 优势 | 代价 |
|---|---|---|
| 测试覆盖 | 186 passed, 5 skipped, 0 failed | 测试要跨 macOS/Linux/Windows |
| 变更可追溯 | release notes 详尽到 PR 号 | 维护 60+ SKILL.md 变体 |
| 社区贡献 | 多次感谢具体贡献者(@Stephen-abc / @igorcosta / @xwang118 等) | 社区 PR 偶尔需修 Windows 兼容性 |
| 安全补丁响应 | 24h 内 hotfix(如 v2.38.1 SKILL.md frontmatter) | — |
双轨维护(Shell + PowerShell)是工程债也是工程资产 —— 它是 planning-with-files 真正”开箱即用“的代价。任何想 fork 的项目都需要认真对待这个 trade-off。
十三、实践:手把手跑通 planning-with-files
13.1 30 秒快速安装(Claude Code)
1 | # 方式 1:插件市场安装(推荐) |
13.2 第一次使用:让 agent 创建一个真实任务
1 | # 在 Claude Code 中输入 |
agent 会自动:
- 创建
task_plan.md(5 个 phase 的状态机) - 创建
findings.md(空模板) - 创建
progress.md(空模板) - 在 Phase 1 完成时输出
**Status:** complete
13.3 v3 模式:开启自主 + 完成门控
1 | # 启动一个 6 阶段的长期任务 |
13.4 真实运行效果:5 条件门控决策示例
1 | # 假设 phase 2 还没完成,agent 试图停止 |
13.5 session-catchup.py:跨 IDE 历史恢复
1 | # 在新会话里恢复上下文 |
十四、趋势判断与工程启示
14.1 趋势一:AI Agent 的”持久化”成为标配
planning-with-files ⭐24k 的事实说明:2026 年的 AI Agent 行业,已经默认”持久化 = 基础能力”。任何不解决 /clear 灾难、context rot、Goal drift 的 Agent 框架/技能,在长任务场景下都会被淘汰。
未来 6-12 个月,我们可能看到:
- 平台级持久化抽象 —— Claude Code / Codex / Cursor 内置类似机制(而不是依赖第三方 SKILL)
- 持久化协议 —— 类似 MCP(Model Context Protocol)的”Memory Protocol”,让不同 Agent 共享持久化层
- 状态机驱动 —— planning-with-files 的 phase 状态机可能演化成更通用的 “Task State Machine” 协议
14.2 趋势二:Hook 时机成为 Agent 工程的”新原生 API”
planning-with-files 完整利用了 Claude Code 的 5 个 Hook 时机。这种”Hook-first“设计哲学预示:
- 未来的 Agent OS 会把 Hook 时机当成”系统调用”一样暴露出来
- Skills-as-Plugins 会成为 Agent 生态的标准打包格式(planning-with-files 已经验证了)
- 完成门控(Termination Oracle) 会从”可选优化”变成”默认配置”
14.3 趋势三:安全 = SHA-256 + 路径 containment + nonce
planning-with-files 的 v3 安全子系统(attest-plan.sh + containment guard + nonce delimiter)是 2026 年最前沿的 Agent 安全实践。三个机制组合起来防御了三类攻击:
| 攻击类型 | 防御机制 |
|---|---|
| Plan 篡改 → 注入恶意指令 | SHA-256 见证 + [PLAN TAMPERED] 阻断 |
| Symlink 跨项目根读敏感文件 | 4 级 canonicalize + is_within_root |
| End delimiter 伪造 → 注入非 plan 内容 | Nonce-based delimiter + data/instruction 分离 |
任何 2026 H2 发布的新 Skill 都会参考这种”三件套”安全设计。
14.4 工程启示 1:好工具 = 6 个 shell 脚本
planning-with-files 的整个核心是 6 个 shell 脚本 + 1 个 Python 脚本。这给我们一个重要启示:
2026 年最有效的 AI 工具,可能根本不是 Python 框架,而是 shell 脚本 + 几个 markdown 文件。
因为 shell 脚本是 AI Agent 最容易理解、修改、扩展的形态。Python 框架在 LLM 时代反而成了”抽象税“。
14.5 工程启示 2:测试要 100% 跨平台
planning-with-files 有 186 个测试,跨 macOS / Linux / Windows 跑。这对一个 shell 脚本项目来说是巨大的工程投入。但 v3.2.0 release notes 显示:
session-catchup.pynever sanitized Windows-style paths correctly and had no explicit encoding on three reads, so it silently did nothing on Windows with no error.
—— 没有这个测试套件,Windows 用户的”session 恢复”会静默失败。这就是为什么 186 tests 的投资是值得的。
14.6 工程启示 3:Release Notes 写得比代码还重要
planning-with-files 的 README 里有 几十个 release notes,每个都明确写出:
- 影响范围(v3.0.0 改了所有 SKILL.md 变体)
- 修复的具体 bug(YAML frontmatter 解析失败、8.3 短名解析不一致)
- 引用的 PR / issue 编号
- 测试套件结果(”Suite at 180 passed”)
这种”release notes as documentation“的风格,让任何 contributor 都能快速理解每个版本的关键变更,把”项目历史”变成了”项目知识”。
十五、总结
planning-with-files 用 6 个 shell 脚本 + 1 个 Python 脚本 + 6 个 SKILL.md 变体,重新定义了 AI Agent 的”持久化规划”标准。它在 ⭐24,711 stars 的背后,是 Meta 用 20 亿美元收购 Manus 所验证的核心理念:
Filesystem as memory. Attention manipulation. Error persistence. Goal tracking. Completion verification.
这 5 原则在 planning-with-files 里被精确地翻译成:
| Manus 原则 | planning-with-files 实现 |
|---|---|
| Filesystem as memory | 3 个 markdown 文件在磁盘 |
| Attention manipulation | PreToolUse 钩子每次工具调用前重读 plan |
| Error persistence | task_plan.md 中的错误表 + 5-Question Reboot Check |
| Goal tracking | ### Phase N: [Title] + **Status:** 状态机 |
| Completion verification | v3 Stop 钩子 5 条件门控决策表 |
它不是框架、不是库、不是平台,它是一个 Skill——一个装在 ~/.claude/skills/ 目录里、被所有现代 AI Agent 自动加载的”操作习惯”。这种”用户透明、平台原生、跨 Agent 兼容“的设计哲学,是它能在 5 个月内冲到 ⭐24k 的根本原因。
如果你是 AI Agent 的重度用户,强烈建议把 planning-with-files 装上——5 分钟的安装,节省未来 50 小时的”重新对齐目标”成本。
如果你是 AI Agent 工具的开发者,强烈建议学习 planning-with-files 的设计哲学——它展示了 2026 年最前沿的”Agent 操作系统”应该是怎样的。
附录:关键资源
| 资源 | 链接 |
|---|---|
| GitHub 仓库 | https://github.com/OthmanAdi/planning-with-files |
| 官方网站/文档 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/quickstart.md |
| Benchmark 报告 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/evals.md |
| 安装指南 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/installation.md |
| 工作流文档 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/workflow.md |
| 故障排除 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/troubleshooting.md |
| 性能优化笔记 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/perf-notes.md |
| 哈希见证文档 | https://github.com/OthmanAdi/planning-with-files/blob/master/docs/attestation-locking.md |
| License | MIT |
| 首次提交 | 2026-01-03 |
| 当前版本 | v3.2.0 (2026-07-03) |
| 衍生项目 | plan-cascade(多级任务编排), multi-manus-planning(多项目支持), agentfund-skill(Agent 众筹)等 |
| 上游灵感 | Anthropic skills 协议 + Manus AI(Meta $2B 收购) |
本文基于 OthmanAdi/planning-with-files v3.2.0 源码分析。所有引用脚本均可在仓库 scripts/ 目录找到对应文件并通过 sh scripts/<name>.sh 真实运行验证。