Skip to content

Hooks Not Working: Troubleshooting Guide ​

Your Current Problem ​

You've configured Hooks, but they're not working as expected. You might encounter:

  • Dev server not blocked from running outside tmux
  • No SessionStart or SessionEnd logs visible
  • Prettier auto-formatting not working
  • TypeScript checks not running
  • Strange error messages appearing

Don't worry—these issues usually have clear solutions. This lesson helps you systematically diagnose and fix Hooks-related problems.

🎒 Prerequisites ​

Before You Start

Ensure you have:

  1. ✅ Completed Everything Claude Code installation
  2. ✅ Understood basic concepts of Hooks Automation
  3. ✅ Read the Hooks configuration section in the project README

Common Issue 1: Hooks Not Triggering At All ​

Symptoms ​

After executing commands, you see no [Hook] log output, and Hooks seem completely uninvoked.

Possible Causes ​

Cause A: Incorrect hooks.json Path ​

Problem: hooks.json is not in the correct location, so Claude Code can't find the configuration file.

Solution:

Verify that hooks.json is in the correct location:

bash
# Should be in one of these locations:
~/.claude/hooks/hooks.json              # User-level configuration (global)
.claude/hooks/hooks.json                 # Project-level configuration

Verification Method:

bash
# Check user-level configuration
ls -la ~/.claude/hooks/hooks.json

# Check project-level configuration
ls -la .claude/hooks/hooks.json

If the file doesn't exist, copy from the Everything Claude Code plugin directory:

bash
# Assuming plugin is installed at ~/.claude-plugins/
cp ~/.claude-plugins/everything-claude-code/hooks/hooks.json ~/.claude/hooks/

Cause B: JSON Syntax Errors ​

Problem: hooks.json has syntax errors, preventing Claude Code from parsing it.

Solution:

Validate JSON format:

bash
# Use jq or Python to validate JSON syntax
jq empty ~/.claude/hooks/hooks.json
# Or
python3 -m json.tool ~/.claude/hooks/hooks.json > /dev/null

Common Syntax Errors:

  • Missing commas
  • Unclosed quotes
  • Using single quotes (must use double quotes)
  • Incorrect comment format (JSON doesn't support // comments)

Cause C: Environment Variable CLAUDE_PLUGIN_ROOT Not Set ​

Problem: Hook scripts use ${CLAUDE_PLUGIN_ROOT} to reference paths, but the environment variable is not set.

Solution:

Check if the plugin installation path is correct:

bash
# View installed plugin paths
ls -la ~/.claude-plugins/

Ensure the Everything Claude Code plugin is correctly installed:

bash
# You should see a directory structure like this:
~/.claude-plugins/everything-claude-code/
├── scripts/
├── hooks/
├── agents/
└── ...

If installed from the plugin marketplace, the environment variable will be automatically set after restarting Claude Code.

If manually installed, check the plugin path in ~/.claude/settings.json:

json
{
  "plugins": [
    {
      "name": "everything-claude-code",
      "path": "/path/to/everything-claude-code"
    }
  ]
}

Common Issue 2: Specific Hooks Not Triggering ​

Symptoms ​

Some Hooks work (e.g., SessionStart), but others don't trigger (e.g., PreToolUse for formatting).

Possible Causes ​

Cause A: Incorrect Matcher Expression ​

Problem: The Hook's matcher expression has errors, so matching conditions aren't met.

Solution:

Check the matcher syntax in hooks.json:

json
{
  "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx)$\""
}

Important Notes:

  • Tool names must be wrapped in double quotes: "Edit", "Bash"
  • Backslashes in regular expressions need double escaping: \\\\. instead of \\.
  • File path matching uses the matches keyword

Testing Matchers:

You can manually test matching logic:

bash
# Test file path matching
node -e "console.log(/\\\\.(ts|tsx)$/.test('src/index.ts'))"
# Should output: true

Cause B: Command Execution Failed ​

Problem: The Hook command itself fails to execute, but no error message appears.

Solution:

Manually run Hook commands to test:

bash
# Navigate to plugin directory
cd ~/.claude-plugins/everything-claude-code

# Manually run a Hook script
node scripts/hooks/session-start.js

# Check for error output

Common Failure Causes:

  • Node.js version incompatibility (requires Node.js 14+)
  • Missing dependencies (e.g., prettier, typescript not installed)
  • Script permission issues (see below)

Common Issue 3: Permission Issues (Linux/macOS) ​

Symptoms ​

You see an error like this:

Permission denied: node scripts/hooks/session-start.js

Solution ​

Grant execute permissions to Hook scripts:

bash
# Navigate to plugin directory
cd ~/.claude-plugins/everything-claude-code

# Grant execute permissions to all hook scripts
chmod +x scripts/hooks/*.js

# Verify permissions
ls -la scripts/hooks/
# Should see something like: -rwxr-xr-x  session-start.js

Batch Fix All Scripts:

bash
# Fix all .js files under scripts
find ~/.claude-plugins/everything-claude-code/scripts -name "*.js" -exec chmod +x {} \;

Common Issue 4: Cross-Platform Compatibility Issues ​

Symptoms ​

Works fine on Windows but fails on macOS/Linux, or vice versa.

Possible Causes ​

Cause A: Path Separators ​

Problem: Windows uses backslashes \, Unix uses forward slashes /.

Solution:

Everything Claude Code scripts already handle cross-platform compatibility (using Node.js path module), but if you customize Hooks, note:

Incorrect:

json
{
  "command": "node scripts/hooks\\session-start.js"  // Windows style
}

Correct:

json
{
  "command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/hooks/session-start.js\"  // Use environment variable and forward slashes
}

Cause B: Shell Command Differences ​

Problem: Different platforms have different command syntax (e.g., which vs where).

Solution:

Everything Claude Code's scripts/lib/utils.js already handles these differences. When customizing Hooks, refer to cross-platform functions in that file:

javascript
// Cross-platform command detection in utils.js
function commandExists(cmd) {
  if (isWindows) {
    spawnSync('where', [cmd], { stdio: 'pipe' });
  } else {
    spawnSync('which', [cmd], { stdio: 'pipe' });
  }
}

Common Issue 5: Auto-Formatting Not Working ​

Symptoms ​

After editing TypeScript files, Prettier doesn't automatically format the code.

Possible Causes ​

Cause A: Prettier Not Installed ​

Problem: PostToolUse Hook calls npx prettier, but it's not installed in the project.

Solution:

bash
# Install Prettier (project-level)
npm install --save-dev prettier
# Or
pnpm add -D prettier

# Or install globally
npm install -g prettier

Cause B: Prettier Configuration Missing ​

Problem: Prettier can't find a configuration file, so it uses default formatting rules.

Solution:

Create a Prettier configuration file:

bash
# Create .prettierrc in project root
cat > .prettierrc << 'EOF'
{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5"
}
EOF

Cause C: File Type Mismatch ​

Problem: The edited file extension is not in the Hook's matching rules.

Current Matching Rules (hooks.json L92-97):

json
{
  "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx|js|jsx)$\"",
  "description": "Auto-format JS/TS files with Prettier after edits"
}

If you need to support other file types (e.g., .vue), modify the configuration:

json
{
  "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\\\.(ts|tsx|js|jsx|vue)$\""
}

Common Issue 6: TypeScript Checks Not Working ​

Symptoms ​

After editing .ts files, you don't see type checking error output.

Possible Causes ​

Cause A: tsconfig.json Missing ​

Problem: Hook scripts search upward for tsconfig.json, but can't find it.

Solution:

Ensure tsconfig.json exists in the project root or a parent directory:

bash
# Find tsconfig.json
find . -name "tsconfig.json" -type f

# If it doesn't exist, create a basic configuration
cat > tsconfig.json << 'EOF'
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}
EOF

Cause B: TypeScript Not Installed ​

Problem: Hook calls npx tsc, but TypeScript is not installed.

Solution:

bash
npm install --save-dev typescript
# Or
pnpm add -D typescript

Common Issue 7: SessionStart/SessionEnd Not Triggering ​

Symptoms ​

When starting or ending a session, you don't see [SessionStart] or [SessionEnd] logs.

Possible Causes ​

Cause A: Session File Directory Doesn't Exist ​

Problem: The ~/.claude/sessions/ directory doesn't exist, so Hook scripts can't create session files.

Solution:

Manually create the directory:

bash
# macOS/Linux
mkdir -p ~/.claude/sessions

# Windows PowerShell
New-Item -ItemType Directory -Force -Path "$env:USERPROFILE\.claude\sessions"

Cause B: Script Path Incorrect ​

Problem: The script path referenced in hooks.json is incorrect.

Verification Method:

bash
# Verify that scripts exist
ls -la ~/.claude-plugins/everything-claude-code/scripts/hooks/session-start.js
ls -la ~/.claude-plugins/everything-claude-code/scripts/hooks/session-end.js

If they don't exist, check if the plugin is completely installed:

bash
# View plugin directory structure
ls -la ~/.claude-plugins/everything-claude-code/

Common Issue 8: Dev Server Blocking Not Working ​

Symptoms ​

Running npm run dev directly isn't blocked and the dev server starts.

Possible Causes ​

Cause A: Regular Expression Not Matching ​

Problem: Your dev server command is not in the Hook's matching rules.

Current Matching Rules (hooks.json L6):

json
{
  "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)\""
}

Test Matching:

bash
# Test if your command matches
node -e "console.log(/(npm run dev|pnpm( run)? dev|yarn dev|bun run dev)/.test('npm run dev'))"

If you need to support other commands (e.g., npm start), modify hooks.json:

json
{
  "matcher": "tool == \"Bash\" && tool_input.command matches \"(npm (run dev|start)|pnpm( run)? (dev|start)|yarn (dev|start)|bun run (dev|start))\""
}

Cause B: Not Running in tmux But Not Blocked ​

Problem: Hook should prevent dev server from running outside tmux, but it's not taking effect.

Check Points:

  1. Confirm Hook command executes successfully:
bash
# Simulate Hook command
node -e "console.error('[Hook] BLOCKED: Dev server must run in tmux');process.exit(1)"
# Should see error output and exit code 1
  1. Check if process.exit(1) correctly blocks the command:

    • process.exit(1) in the Hook command should prevent subsequent command execution
  2. If it still doesn't work, you may need to upgrade Claude Code version (Hooks support might require the latest version)


Diagnostic Tools and Tips ​

Enable Verbose Logging ​

View Claude Code's detailed logs to understand Hook execution:

bash
# macOS/Linux
tail -f ~/Library/Logs/claude-code/claude-code.log

# Windows
Get-Content "$env:APPDATA\claude-code\logs\claude-code.log" -Wait -Tail 50

Manually Test Hooks ​

Manually run Hook scripts in the terminal to verify their functionality:

bash
# Test SessionStart
cd ~/.claude-plugins/everything-claude-code
node scripts/hooks/session-start.js

# Test Suggest Compact
node scripts/hooks/suggest-compact.js

# Test PreCompact
node scripts/hooks/pre-compact.js

Check Environment Variables ​

View Claude Code's environment variables:

bash
# Add debug output in Hook scripts
node -e "console.log('CLAUDE_PLUGIN_ROOT:', process.env.CLAUDE_PLUGIN_ROOT); console.log('COMPACT_THRESHOLD:', process.env.COMPACT_THRESHOLD)"

Checklist ✅ ​

Go through this checklist item by item:

  • [ ] hooks.json is in the correct location (~/.claude/hooks/ or .claude/hooks/)
  • [ ] hooks.json JSON format is correct (verified with jq)
  • [ ] Plugin path is correct (${CLAUDE_PLUGIN_ROOT} is set)
  • [ ] All scripts have execute permissions (Linux/macOS)
  • [ ] Dependency tools are installed (Node.js, Prettier, TypeScript)
  • [ ] Session directory exists (~/.claude/sessions/)
  • [ ] Matcher expressions are correct (regex escaping, quote wrapping)
  • [ ] Cross-platform compatibility (using path module, environment variables)

When to Seek Help ​

If the above methods don't solve the problem:

  1. Collect Diagnostic Information:

    bash
    # Output the following information
    echo "Node version: $(node -v)"
    echo "Claude Code version: $(claude-code --version)"
    echo "Plugin path: $(ls -la ~/.claude-plugins/everything-claude-code)"
    echo "Hooks config: $(cat ~/.claude/hooks/hooks.json | jq -c .)"
  2. Check GitHub Issues:

  3. Submit an Issue:

    • Include complete error logs
    • Provide operating system and version information
    • Attach hooks.json content (redact sensitive information)

Lesson Summary ​

Hooks not working usually falls into these categories:

Issue TypeCommon CausesQuick Diagnosis
Not Triggering At Allhooks.json path error, JSON syntax errorsCheck file location, validate JSON format
Specific Hook Not TriggeringMatcher expression errors, command execution failuresCheck regex syntax, run scripts manually
Permission IssuesScripts missing execute permissions (Linux/macOS)chmod +x scripts/hooks/*.js
Cross-Platform CompatibilityPath separators, Shell command differencesUse path module, reference utils.js
Functionality Not WorkingDependency tools not installed (Prettier, TypeScript)Install corresponding tools, check config files

Remember: Most issues can be resolved by checking file paths, validating JSON format, and confirming dependency installation.


Next Lesson Preview ​

In the next lesson, we'll learn about MCP Connection Troubleshooting.

You will learn:

  • Common MCP server configuration errors
  • How to debug MCP connection issues
  • MCP environment variable and placeholder settings

Appendix: Source Code Reference ​

Click to expand source code locations

Updated: 2026-01-25

FunctionFile PathLine Numbers
Hooks main confighooks/hooks.json1-158
SessionStart Hookscripts/hooks/session-start.js1-62
SessionEnd Hookscripts/hooks/session-end.js1-83
PreCompact Hookscripts/hooks/pre-compact.js1-49
Suggest Compact Hookscripts/hooks/suggest-compact.js1-61
---------

Key Functions:

  • getHomeDir() / getClaudeDir() / getSessionsDir(): Get configuration directory paths (utils.js 19-34)
  • ensureDir(dirPath): Ensure directory exists, create if not (utils.js 54-59)
  • log(message): Output logs to stderr (visible in Claude Code) (utils.js 182-184)
  • findFiles(dir, pattern, options): Cross-platform file search (utils.js 102-149)
  • commandExists(cmd): Check if command exists (cross-platform compatible) (utils.js 228-246)

Key Regular Expressions:

  • Dev server blocking: npm run dev|pnpm( run)? dev|yarn dev|bun run dev (hooks.json 6)
  • File edit matching: \\.(ts|tsx|js|jsx)$ (hooks.json 92)
  • TypeScript files: \\.(ts|tsx)$ (hooks.json 102)

Environment Variables:

  • ${CLAUDE_PLUGIN_ROOT}: Plugin root directory path
  • CLAUDE_SESSION_ID: Session identifier
  • COMPACT_THRESHOLD: Compression suggestion threshold (default 50)