# How to Implement a `console.log` Detection Hook in Everything-Claude-Code

> Learn to implement a console.log detection hook in Everything-Claude-Code. Add a PostToolUse hook to scan JS/TS files for console statements effectively.

- Repository: [WorldFlowAI/everything-claude-code](https://github.com/WorldFlowAI/everything-claude-code)
- Tags: how-to-guide
- Published: 2026-09-07

---

**Add a `PostToolUse` hook in [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json) that matches `Edit` calls on JS/TS files and runs a Node script to scan for `console.log` statements.**

The **Everything-Claude-Code** repository provides a powerful hook system that runs custom commands automatically after Claude Code tools finish executing. Implementing a `console.log` detection hook helps catch stray debug statements before they reach production, enforcing clean JavaScript and TypeScript codebases without interrupting your development flow.

---

## Understanding the Hook Architecture

Claude Code hooks are defined in **[`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json)** and triggered by lifecycle events. The **`PostToolUse`** event fires after any tool completes, making it ideal for lint-style checks on file modifications.

Each hook entry contains three components:

- **Matcher** – a boolean expression determining when the hook fires
- **Command** – the executable to run (shell command or inline script)
- **Description** – human-readable explanation of the hook's purpose

The hook receives tool execution data via `stdin` as a JSON payload, allowing inspection of which file was edited and what operation occurred.

---

## Step-by-Step Implementation

### Step 1: Define the Matcher Expression

The matcher restricts execution to `Edit` operations on web-convention files:

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

```

This pattern ensures the hook only processes relevant file types, avoiding unnecessary computation on non-JavaScript assets.

### Step 2: Create the Detection Command

The command reads the edited file from disk, scans line-by-line for the `/console\.log/` regex, and reports matches to `stderr`:

```json
// hooks/hooks.json – complete PostToolUse entry
{
  "matcher": "tool == \"Edit\" && tool_input.file_path matches \"\\.(ts|tsx|js|jsx)$\"",
  "hooks": [
    {
      "type": "command",
      "command": "node -e \"const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&fs.existsSync(p)){const c=fs.readFileSync(p,'utf8');const lines=c.split('\\n');const matches=[];lines.forEach((l,idx)=>{if(/console\\.log/.test(l))matches.push((idx+1)+': '+l.trim())});if(matches.length){console.error('[Hook] WARNING: console.log found in '+p);matches.slice(0,5).forEach(m=>console.error(m));console.error('[Hook] Remove console.log before committing')}}console.log(d)})\""
    }
  ],
  "description": "Warn about console.log statements after edits"
}

```

The Node script performs four operations:

1. **Buffer stdin** – accumulates the JSON payload from Claude Code
2. **Extract file path** – parses `tool_input.file_path` from the payload
3. **Scan for matches** – tests each line against `/console\.log/`
4. **Emit warnings** – prints line numbers and snippets (limited to first 5 matches)
5. **Passthrough** – echoes original payload to `stdout` for downstream processing

### Step 3: Test the Hook Manually

Before relying on automatic execution, simulate the Claude Code payload:

```bash

# Simulate a Claude-code Edit tool payload

echo '{"tool":"Edit","tool_input":{"file_path":"src/example.js"}}' \
  | node -e "const fs=require('fs');let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>{const i=JSON.parse(d);const p=i.tool_input?.file_path;if(p&&fs.existsSync(p)){const c=fs.readFileSync(p,'utf8');const lines=c.split('\\n');const matches=[];lines.forEach((l,idx)=>{if(/console\\.log/.test(l))matches.push((idx+1)+': '+l.trim())});if(matches.length){console.error('[Hook] WARNING: console.log found in '+p);matches.slice(0,5).forEach(m=>console.error(m));console.error('[Hook] Remove console.log before committing')}}console.log(d)})"

```

Given a file [`src/example.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/src/example.js) containing:

```javascript
function processData(data) {
  console.log('debug start');
  const result = transform(data);
  console.log(result);
  return result;
}

```

The hook outputs:

```

[Hook] WARNING: console.log found in src/example.js
2: console.log('debug start');
4: console.log(result);
[Hook] Remove console.log before committing

```

---

## Extending the Detection Pattern

The same architecture supports additional lint-style checks by modifying the regex or adding parallel hook entries:

| Pattern | Regex Modification | Use Case |
|---------|-------------------|----------|
| `debugger` statements | `/\bdebugger\b/` | Prevent accidental breakpoints in production |
| `alert()` calls | `/\balert\(/` | Block debugging dialogs |
| Hardcoded secrets | `/password|secret|key|token/i` | Basic secret detection |
| TODO/FIXME comments | `/TODO|FIXME/` | Surface incomplete work |

Each extension follows the identical three-step pattern: update the matcher if needed, modify the detection regex in the command, and adjust the description accordingly.

---

## Key Files Reference

| File | Purpose |
|------|---------|
| **[`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json)** | Central configuration for all Claude Code hooks; the `PostToolUse` array holds detection logic |
| **[`scripts/hooks/pre-compact.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/scripts/hooks/pre-compact.js)** | Reference implementation showing Node-based hook scripts in action |
| **[`tests/hooks/hooks.test.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/tests/hooks/hooks.test.js)** | Test suite for hook behavior—extend here to add detection coverage |
| **[`README.md`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/README.md)** | Architecture documentation and hook lifecycle details |

The hook system in **WorldFlowAI/everything-claude-code** operates entirely through configuration, requiring no modifications to Claude Code's core—making it safe to upgrade without losing custom checks.

---

## Summary

- **Hooks live in [`hooks/hooks.json`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/hooks/hooks.json)** under the `PostToolUse` section
- **Matchers filter by tool type and file extension** using boolean expressions
- **Commands receive JSON via stdin** and must passthrough data to `stdout`
- **`console.log` detection uses `/console\.log/` regex** with line-by-line scanning
- **Warnings go to `stderr`** to surface issues without breaking the tool chain

---

## Frequently Asked Questions

### Does the `console.log` detection hook block file edits or commits?

No. The hook runs **after** the `Edit` tool completes and only writes to `stderr`. It surfaces warnings without modifying the exit code or preventing the operation from succeeding. This design keeps development velocity high while maintaining visibility into code quality issues.

### Can I detect other console methods like `console.warn` or `console.error`?

Yes. Modify the regex in the command from `/console\.log/` to `/console\.(log|warn|error|info|debug)/` to catch all console method calls. You can also create separate hooks with distinct descriptions if you want differentiated handling for production-appropriate methods versus debug methods.

### How do I test hooks without triggering actual Claude Code edits?

Use the manual testing approach shown above: construct a JSON payload matching Claude Code's `PostToolUse` format and pipe it through the Node command. The **[`tests/hooks/hooks.test.js`](https://github.com/WorldFlowAI/everything-claude-code/blob/main/tests/hooks/hooks.test.js)** file contains additional patterns for automated testing that you can adapt for your detection logic.

### What happens if the hook script throws an error?

Claude Code's hook system generally logs hook failures but proceeds with the operation. However, always ensure your command ends with `console.log(d)` to passthrough the original payload—failure to do so may break downstream processing. The inline Node script includes error-adjacent checks like `fs.existsSync(p)` to avoid crashes on missing files.