[BUG] Tilde (~) not expanded in hook command field — global UserPromptSubmit hook silently fails
Bug Description
When a global UserPromptSubmit hook uses ~ in the command path, the hook silently fails to execute in some Claude Code windows. No error is shown — the statusMessage never appears and Claude processes the input as if no hook exists.
Steps to Reproduce
- Add a global hook in
~/.claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "~/.claude/scripts/my-hook.sh",
"statusMessage": "Running my hook"
}
]
}
]
}
}
- Open Claude Code in project A (where the hook was originally configured/tested) — hook works fine, status message appears.
- Open a new Claude Code window in a different project directory — hook does NOT fire. No status message, no error.
- Verify the script works manually:
echo "test" | ~/.claude/scripts/my-hook.sh— works in all directories.
- Fix: replace
~with the absolute path (/Users/<name>/.claude/scripts/my-hook.sh) — hook now works in all windows.
Expected Behavior
~ in hook command fields should be expanded to $HOME, consistent with standard macOS/Linux shell behavior. Users on macOS in particular habitually use ~ in paths.
Alternatively, if ~ expansion is intentionally unsupported, Claude Code should warn when it encounters ~ in a hook command, rather than silently failing.
Actual Behavior
Hook silently does not execute. No error, no warning, no status message. The only indication is that Claude responds as if the hook doesn't exist.
Environment
- Claude Code v2.1.114
- macOS (Darwin 25.3.0)
- Shell: zsh
Related Issues
- #37580 — Same
~expansion problem but for MCP server args - #55230 — Feature request for
~expansion in permissions patterns
Suggested Fix
Expand ~ to $HOME in hook command fields before execution, matching standard shell behavior. This would align with macOS users' expectations and prevent silent failures.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗