Files
claude-foundations/memory/script-require-plan-file.md
Paul O'Reilly e94417b896 Add best practices, hooks, memory files, and scripts from recent sessions
Includes: spec-driven and test-driven development best practices,
reproduce-before-fixing debugging workflow, require-plan-file hook,
find-project-root script, session logs, memory files for decisions/
gotchas/process-lessons, and updates to existing best practice topics.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 09:47:47 +13:00

1.6 KiB

name, description, type
name description type
require-plan-file PreToolUse hook that blocks ExitPlanMode unless a *-PLAN.md file exists in the current project root reference

script: require-plan-file

Location: hooks/require-plan-file.sh Symlinked to: ~/.claude/hooks/require-plan-file.sh

Purpose

Enforces the plan-file convention: Claude cannot exit plan mode until it has written a [MILESTONE]-[PURPOSE]-PLAN.md file in the project root.

How it works

Fires as a PreToolUse hook on ExitPlanMode. Reads cwd from the JSON input on stdin, checks for any *-PLAN.md file in that directory:

  • File found → exits 0 (allows ExitPlanMode to proceed)
  • No file found → exits 2 (blocks ExitPlanMode, stderr message injected into Claude's context)

The exit 2 message tells Claude exactly what to do, so it self-corrects and writes the file before retrying.

Settings.json config

"PreToolUse": [
  {
    "matcher": "ExitPlanMode",
    "hooks": [{ "type": "command", "command": "~/.claude/hooks/require-plan-file.sh" }]
  }
]

Naming convention

[MILESTONE]-[PURPOSE]-PLAN.md — e.g. M2-auth-PLAN.md, M3-monitoring-PLAN.md, initial-setup-PLAN.md

Plan files are committed to the project repo as a persistent record of planning decisions.

Gotchas

  • cwd in the hook input is the Claude session's working directory, not necessarily the repo root — works correctly as long as Claude is cd'd into the project root (the standard pattern).
  • If cwd cannot be parsed from stdin, the hook exits 0 (fails open) to avoid blocking legitimate use.