[Bug] FileChanged hook doesn't detect file modifications from Bash tool execution
Bug Description
we use mise to manage our dev environment. i'm trying to make hooks to run mise env -s bash before each bash command in case the environment has changed. I'm trying to use the FileChanged hook to do this.
here is mise-update-env.sh which runs for SessionStart and FileChanged
# set common variables
read \
CLAUDE_CODE_SESSION_ID \
CLAUDE_CODE_TRANSCRIPT_PATH \
CLAUDE_CODE_CWD \
CLAUDE_CODE_HOOK_EVENT_NAME \
< <(jq -r '[.session_id, .transcript_path, .cwd, .hook_event_name] | @tsv' <&0)
export CLAUDE_CODE_SESSION_ID \
CLAUDE_CODE_TRANSCRIPT_PATH \
CLAUDE_CODE_CWD \
CLAUDE_CODE_HOOK_EVENT_NAME
function export_mise_env() {
if ! command -v mise >/dev/null 2>&1; then
echo "mise is not installed, skipping mise environment setup." >&2
return
fi
[[ -z "$CLAUDE_ENV_FILE" ]] && { echo "CLAUDE_ENV_FILE is not set, skipping mise environment setup." >&2; return; }
[[ -f "$CLAUDE_ENV_FILE" ]] || touch "$CLAUDE_ENV_FILE"
local mise_env_start="export __MISE_START__=''"
local mise_env_end="export __MISE_END__=''"
# Collapse multi-line values (e.g., RSA keys) to single lines.
# Claude Code parses env files line-by-line; multi-line values break it.
local exports
exports=$(mise env -s bash 2>/dev/null | awk '
/^export / { if (buf) print buf; buf=$0; next }
{ gsub(/\n/,"\\n"); buf=buf"\\n"$0 }
END { if (buf) print buf }
') || {
echo "mise env failed, skipping" >&2
return
}
mise_iteration=${MISE_ITER:-0}
sed -i '' "/$mise_env_start/,/$mise_env_end/d" "$CLAUDE_ENV_FILE"
echo "$mise_env_start" >> "$CLAUDE_ENV_FILE"
echo "export __CLAUDE_ENV_FILE='$CLAUDE_ENV_FILE'">> "$CLAUDE_ENV_FILE"
echo "export __CLAUDE_PROJECT_DIR='$CLAUDE_PROJECT_DIR'" >> "$CLAUDE_ENV_FILE"
echo "export __MISE_ITER='$((mise_iteration + 1))'" >> "$CLAUDE_ENV_FILE"
echo "$exports" >> "$CLAUDE_ENV_FILE"
echo "$mise_env_end" >> "$CLAUDE_ENV_FILE"
#debugging
echo "$exports\n\n----------------------" >> /tmp/mise_exports.log
}
hooks section of .claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/update-mise-env.sh",
"statusMessage": "Activating mise environment...",
"timeout": 5,
"type": "command"
}
]
}
],
"FileChanged": [
{
"hooks": [
{
"command": "bash \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/update-mise-env.sh",
"statusMessage": "Refreshing mise environment...",
"timeout": 5,
"type": "command"
}
],
"matcher": "mise.toml|mise.dev.toml"
}
]
},
}
claude:
Actually - mise rm argc ran via the Bash tool, not the Edit tool. The FileChanged hook watches for file changes made by Claude Code's file-writing tools (Edit/Write), not filesystem changes
from arbitrary Bash commands. That's why the FileChanged hook never fires when mise use/mise rm modify mise.toml through Bash.
Environment Info
- Platform: darwin
- Terminal: vscode
- Version: 2.1.94
- Feedback ID: b86ac5cb-dc47-4770-8f50-fcbd8d96a0d9
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗