[Bug] Plugin-registered CwdChanged and FileChanged hooks don't fire (settings.json works) — v2.1.153
[Bug] CwdChanged and FileChanged hooks never fire in v2.1.153
Summary
Neither CwdChanged nor FileChanged hooks fire under the conditions described in the hooks docs. SessionStart from the same plugin works fine, so plugin loading itself is not the issue.
This appears to be a continuation of the unresolved #44925 (closed stale, same use case: re-applying mise env on cwd/file changes).
Environment
- Claude Code
2.1.153 - macOS (Darwin 25.5.0)
- Plain terminal — no cmux, no IDE extension, no managed-settings policy
- Plugin installed via local marketplace, enabled in
~/.claude/settings.json
Plugin hooks/hooks.json
{
"hooks": {
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/apply-mise-env.sh\"" }] }
],
"CwdChanged": [
{ "hooks": [{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/apply-mise-env.sh\"" }] }
],
"FileChanged": [
{
"matcher": "mise.toml",
"hooks": [{ "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/apply-mise-env.sh\"" }]
}
]
}
}
The hook script logs every invocation (stdin + timestamp + pid) to a tmp file before doing anything else, so we can see every fire unconditionally.
Reproduction
- Start Claude in a project directory containing
mise.toml. SessionStartfires — log entry appears. ✅- Ask Claude to
cd ./subdir(a directory inside the project). The Bash tool reports the new cwd and it persists across subsequent Bash calls — this matches the exact example in theCwdChangeddocs (/Users/my-project→/Users/my-project/subdir). NoCwdChangedlog entry appears. ❌ - Externally edit
mise.toml(mtime updates). NoFileChangedlog entry appears. ❌
Repeated across multiple fresh claude startups and /resumes. The hook script is never invoked for either event.
What I checked
- Hook JSON shape matches docs (matcher-wrapped form for SessionStart works; same shape for CwdChanged;
matcher: "mise.toml"per the docs' literal-filename syntax for FileChanged). - Plugin is loaded (SessionStart proves this).
$CLAUDE_ENV_FILEmachinery in the hook script is irrelevant — the script writes the log entry before anything else, so even a no-op hook would show up.- No managed settings restricting hooks.
- Version 2.1.153 is well past 2.1.83 which added these events; no CHANGELOG entries since suggest any bug fix to them.
- #44925 reports the same symptom with the same use case (mise env reload) and was closed stale without developer comment.
Expected
Per docs, CwdChanged should fire when Claude executes cd (the docs' own example matches the test), and FileChanged should fire when a file matched by the matcher is modified on disk.
Actual
Neither fires. Only SessionStart from the same plugin definition produces hook invocations.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗