Preflight Checklist
What's Wrong?
When ExitPlanMode triggers hooks, it executes them with current working directory set to user home (~) rather than the project directory where the plan was created. This causes plugins using relative paths from settings to resolve paths incorrectly.
Impact: Plugins using ExitPlanMode hooks with relative paths fail silently. Multi-project workflows break when each project has its own .claude/plans/ directory.
Evidence:
- Hook
cwd is ~ (user home) instead of project directory
- Relative path
./.claude/plans resolves to ~/.claude/plans/ instead of project's .claude/plans/
- Hook opens wrong plan file from global directory
Affected: plan-review plugin and likely any plugin hooking ExitPlanMode that uses relative paths from settings
What Should Happen?
ExitPlanMode should preserve project context when executing hooks:
- Hook
cwd should be project directory (e.g., /Users/storm/PhpstormProjects/CodexMonitor)
- Relative path
./.claude/plans should resolve to project's .claude/plans/ directory
- Hook should operate on correct project-specific plan file
- Similar to how other hooks (PreToolUse, PostToolUse) work with
$CLAUDE_PROJECT_DIR
Error Messages/Logs
No explicit error messages - hook executes successfully but with wrong working directory.
**Evidence from hook execution**:
cwd = Path.cwd() # Returns ~ instead of /Users/storm/PhpstormProjects/CodexMonitor
settings_plans_dir = settings.get("plansDirectory", "./.claude/plans")
plans_dir = cwd / settings_plans_dir[2:] # Wrong resolution due to incorrect cwd
**File locations**:
- Correct plan: `/Users/storm/PhpstormProjects/CodexMonitor/.claude/plans/streamed-gliding-sonnet.md`
- Hook found: `~/.claude/plans/elegant-hopping-book.md` (stale plan from different project)
Steps to Reproduce
- Set up multi-project workflow with per-project
.claude/plans/ directories
- Configure
~/.claude/settings.json with relative path:
{
"plansDirectory": "./.claude/plans"
}
- Open project in subdirectory (e.g.,
/Users/storm/PhpstormProjects/CodexMonitor)
- Create and work on a plan in the project
- Exit plan mode → triggers hook (e.g.,
plan-review plugin)
- Hook resolves relative path using
Path.cwd() and gets ~ instead of project directory
- Observe that hook opens plan from
~/.claude/plans/ instead of project's .claude/plans/
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
No response
Claude Code Version
2.1.29 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Related Issues
This appears distinct from existing cwd-related hook issues:
This issue is specifically about ExitPlanMode hook subprocess executing with incorrect working directory context.
Proposed Solutions
Option 1 (Preferred): Preserve project directory context
- Execute ExitPlanMode hooks with
cwd set to project directory
- Or: Pass project directory as environment variable (
$CLAUDE_PROJECT_DIR) to hook subprocess
- Similar to how other hooks work with
$CLAUDE_PROJECT_DIR
Option 2: Document workaround and best practices
- Update hook documentation to warn against relying on
cwd for ExitPlanMode hooks
- Provide API or environment variable for hooks to reliably get project directory
- Recommend using absolute paths in settings for multi-project workflows
Context
Discovered during plan-review plugin testing across multiple projects. The plugin correctly reads settings with relative paths but fails because ExitPlanMode hook execution context doesn't match the project where planning occurred.
Settings file: ~/.claude/settings.json line 193
"plansDirectory": "./.claude/plans"
Affected plugin: plan-review from storm-plugins marketplace
Preflight Checklist
What's Wrong?
When ExitPlanMode triggers hooks, it executes them with current working directory set to user home (
~) rather than the project directory where the plan was created. This causes plugins using relative paths from settings to resolve paths incorrectly.Impact: Plugins using ExitPlanMode hooks with relative paths fail silently. Multi-project workflows break when each project has its own
.claude/plans/directory.Evidence:
cwdis~(user home) instead of project directory./.claude/plansresolves to~/.claude/plans/instead of project's.claude/plans/Affected: plan-review plugin and likely any plugin hooking ExitPlanMode that uses relative paths from settings
What Should Happen?
ExitPlanMode should preserve project context when executing hooks:
cwdshould be project directory (e.g.,/Users/storm/PhpstormProjects/CodexMonitor)./.claude/plansshould resolve to project's.claude/plans/directory$CLAUDE_PROJECT_DIRError Messages/Logs
Steps to Reproduce
.claude/plans/directories~/.claude/settings.jsonwith relative path:{ "plansDirectory": "./.claude/plans" }/Users/storm/PhpstormProjects/CodexMonitor)plan-reviewplugin)Path.cwd()and gets~instead of project directory~/.claude/plans/instead of project's.claude/plans/Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
No response
Claude Code Version
2.1.29 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Related Issues
This appears distinct from existing cwd-related hook issues:
This issue is specifically about ExitPlanMode hook subprocess executing with incorrect working directory context.
Proposed Solutions
Option 1 (Preferred): Preserve project directory context
cwdset to project directory$CLAUDE_PROJECT_DIR) to hook subprocess$CLAUDE_PROJECT_DIROption 2: Document workaround and best practices
cwdfor ExitPlanMode hooksContext
Discovered during plan-review plugin testing across multiple projects. The plugin correctly reads settings with relative paths but fails because ExitPlanMode hook execution context doesn't match the project where planning occurred.
Settings file:
~/.claude/settings.jsonline 193Affected plugin: plan-review from storm-plugins marketplace