Preflight Checklist
What's Wrong?
Claude Code does not pass any input data to hook scripts. All hook-related environment variables and command-line arguments are empty or set to "unknown", making it impossible to implement context-aware hooks.
Specifically:
- $CLAUDE_TOOL_INPUT (process.argv[2]) is always an empty string
- $CLAUDE_EVENT_TYPE is always "unknown"
- $CLAUDE_TOOL_NAME is always "unknown"
- $CLAUDE_FILE_PATHS is always an empty string
This affects both PreToolUse and PostToolUse hooks for all tools (Read, Edit, Write, Bash, etc.).
What Should Happen?
According to the https://docs.claude.com/en/docs/claude-code/hooks-guide, Claude Code should populate the following:
Command-line argument:
- $CLAUDE_TOOL_INPUT should contain the tool input JSON, e.g.:
{"tool":"Read","parameters":{"file_path":"/path/to/file.ts"}}
Environment variables:
- $CLAUDE_EVENT_TYPE should be "PreToolUse" or "PostToolUse"
- $CLAUDE_TOOL_NAME should be the tool name (e.g., "Read", "Edit", "Bash")
- $CLAUDE_FILE_PATHS should be the space-separated list of file paths
These values should be accessible in the hook script via process.argv[2] and process.env.*.
Error Messages/Logs
Hook script output showing empty values:
Raw input (process.argv[2]): ""
Environment variables:
CLAUDE_EVENT_TYPE: unknown
CLAUDE_TOOL_NAME: unknown
CLAUDE_FILE_PATHS:
No error messages are generated - the hooks execute successfully but with empty inputs.
Steps to Reproduce
- Create a hook script test-hook.js:
console.log("TOOL_INPUT:", process.argv[2] || "EMPTY");
console.log("EVENT_TYPE:", process.env.CLAUDE_EVENT_TYPE || "EMPTY");
console.log("TOOL_NAME:", process.env.CLAUDE_TOOL_NAME || "EMPTY");
console.log("FILE_PATHS:", process.env.CLAUDE_FILE_PATHS || "EMPTY");
process.exit(0);
- Add hook to .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "node test-hook.js "$CLAUDE_TOOL_INPUT"",
"timeout": 5000
}
]
}
]
}
}
- Restart Claude Code
- Use the Read tool to read any file (e.g., via Claude AI assistant)
- Check the hook output - all values will be empty/unknown
Expected output:
TOOL_INPUT: {"tool":"Read","parameters":{"file_path":"/some/file.ts"}}
EVENT_TYPE: PostToolUse
TOOL_NAME: Read
FILE_PATHS: /some/file.ts
Actual output:
TOOL_INPUT: EMPTY
EVENT_TYPE: EMPTY
TOOL_NAME: EMPTY
FILE_PATHS: EMPTY
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
N/A (Unknown if this ever worked)
Claude Code Version
Latest version as of October 15, 2025
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Impact Severity: Critical - This bug makes the entire hooks system unusable for any context-aware logic.
Affected Use Cases:
- Cannot validate tool parameters (e.g., block dangerous file operations)
- Cannot log tool usage with context
- Cannot implement access control based on file paths
- Cannot provide user feedback based on tool actions
Testing Evidence:
- Manual testing with direct input: ✅ Hook logic works perfectly
- Automated tests: ✅ 100% pass rate
- Claude Code execution: ❌ Fails due to empty inputs
Related Issues:
Root Cause Hypothesis:
Claude Code's hook execution system is not implementing the input/environment variable passing mechanism described in the documentation. This may be an incomplete feature implementation rather than a regression.
Preflight Checklist
What's Wrong?
Claude Code does not pass any input data to hook scripts. All hook-related environment variables and command-line arguments are empty or set to "unknown", making it impossible to implement context-aware hooks.
Specifically:
This affects both PreToolUse and PostToolUse hooks for all tools (Read, Edit, Write, Bash, etc.).
What Should Happen?
According to the https://docs.claude.com/en/docs/claude-code/hooks-guide, Claude Code should populate the following:
Command-line argument:
{"tool":"Read","parameters":{"file_path":"/path/to/file.ts"}}
Environment variables:
These values should be accessible in the hook script via process.argv[2] and process.env.*.
Error Messages/Logs
Hook script output showing empty values: Raw input (process.argv[2]): "" Environment variables: CLAUDE_EVENT_TYPE: unknown CLAUDE_TOOL_NAME: unknown CLAUDE_FILE_PATHS: No error messages are generated - the hooks execute successfully but with empty inputs.Steps to Reproduce
console.log("TOOL_INPUT:", process.argv[2] || "EMPTY");
console.log("EVENT_TYPE:", process.env.CLAUDE_EVENT_TYPE || "EMPTY");
console.log("TOOL_NAME:", process.env.CLAUDE_TOOL_NAME || "EMPTY");
console.log("FILE_PATHS:", process.env.CLAUDE_FILE_PATHS || "EMPTY");
process.exit(0);
{
"hooks": {
"PostToolUse": [
{
"matcher": "Read",
"hooks": [
{
"type": "command",
"command": "node test-hook.js "$CLAUDE_TOOL_INPUT"",
"timeout": 5000
}
]
}
]
}
}
Expected output:
TOOL_INPUT: {"tool":"Read","parameters":{"file_path":"/some/file.ts"}}
EVENT_TYPE: PostToolUse
TOOL_NAME: Read
FILE_PATHS: /some/file.ts
Actual output:
TOOL_INPUT: EMPTY
EVENT_TYPE: EMPTY
TOOL_NAME: EMPTY
FILE_PATHS: EMPTY
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
N/A (Unknown if this ever worked)
Claude Code Version
Latest version as of October 15, 2025
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Impact Severity: Critical - This bug makes the entire hooks system unusable for any context-aware logic.
Affected Use Cases:
Testing Evidence:
Related Issues:
Root Cause Hypothesis:
Claude Code's hook execution system is not implementing the input/environment variable passing mechanism described in the documentation. This may be an incomplete feature implementation rather than a regression.