HookStackGitHub
Back to catalogue
ContextPreToolUse· ReadPreToolUseBefore tool execution · can block⚡ blocking

Binary file read blocker

Stop Claude from wasting tokens trying to read .exe, .pyc, .pkl or .zip files

Intercepts Read tool calls on binary files (executables, compiled bytecode, archives, databases, ML model files, WebAssembly) and immediately blocks them with a helpful message. Claude cannot process binary content meaningfully — this hook prevents it from consuming tokens on garbage data and suggests Bash alternatives like `file` or `ls -lh`.

What does the Binary file read blocker hook do?

Binary file read blocker is a Claude Code PreToolUse hook matching Read. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Stop Claude from wasting tokens trying to read .exe, .pyc, .pkl or .zip files.

Use cases

  • Preventing token waste on .pyc/.class bytecode files
  • Blocking reads of ML model weights (.pkl, .pt, .onnx)
  • Stopping accidental reads of archives or compiled binaries

Tags

#context-optimization#security#binary#tokens#productivity

settings.json fragment

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/pre-read-block-binary.mjs",
            "type": "command"
          }
        ],
        "matcher": "Read"
      }
    ]
  }
}

Script · .claude/hooks/pre-read-block-binary.mjs

#!/usr/bin/env node
// Bloque les lectures de fichiers binaires inutilisables par Claude (PreToolUse Read)
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';
import { extname, basename } from 'path';

const BINARY_EXTENSIONS = new Set([
  // Exécutables et librairies compilées
  'exe', 'dll', 'so', 'dylib', 'bin',
  // Bytecode compilé
  'pyc', 'pyo', 'pyd', 'class', 'o', 'a', 'lib', 'obj',
  // Archives
  'zip', 'tar', 'gz', 'bz2', 'xz', '7z', 'rar', 'jar', 'war', 'ear',
  // Bases de données
  'db', 'sqlite', 'sqlite3',
  // Modèles ML / artefacts
  'pkl', 'pickle', 'pt', 'pth', 'h5', 'pb', 'onnx', 'npy', 'npz',
  // WebAssembly et autres
  'wasm', 'node',
]);

export function run(input) {
  if (input.tool_name !== 'Read') return null;

  const filePath = input.tool_input?.file_path ?? '';
  if (!filePath) return null;

  const ext = extname(filePath).toLowerCase().replace('.', '');
  if (!BINARY_EXTENSIONS.has(ext)) return null;

  const name = basename(filePath);
  return {
    decision: 'block',
    reason: `[block-binary] \`${name}\` is a binary file (.${ext}) — Claude cannot process it meaningfully. Inspect metadata with Bash instead (e.g. \`file\`, \`ls -lh\`).`,
  };
}

/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const input = JSON.parse(readFileSync(0, 'utf8'));
  const result = run(input);
  if (result) process.stdout.write(JSON.stringify(result));
}