HookStack
Back to catalogue
ValidationPreToolUse· WritePreToolUseBefore tool execution · can block⚡ blocking

Block oversized file writes

Stops a 500 KB dump from bloating your repo

Blocks a single Write whose content exceeds ~500 KB — almost always an accidental dump, a generated blob, or a runaway paste that balloons the repo and the diff. Pure byte-length check, no file I/O, so it is effectively free.

What does the Block oversized file writes hook do?

Block oversized file writes is a Claude Code PreToolUse hook matching Write. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Stops a 500 KB dump from bloating your repo.

As a PreToolUse hook it runs before the action completes, so it can block or adjust what Claude is about to do. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.

Use cases

  • Repo hygiene
  • Reviewable diffs
  • Catch accidental dumps

Tags

#validation#files#repo-hygiene#size-limit#guardrail

settings.json fragment

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/block-huge-write.mjs",
            "type": "command"
          }
        ],
        "matcher": "Write"
      }
    ]
  }
}

Script · .claude/hooks/block-huge-write.mjs

#!/usr/bin/env node
// Bloque l'écriture d'un fichier anormalement volumineux (PreToolUse Write)
import { readFileSync } from 'fs';
import { fileURLToPath } from 'url';

// 500 Ko : au-delà, c'est presque toujours un dump, un blob généré ou un collage accidentel.
const MAX_BYTES = 500_000;

export function run(input, { maxBytes = MAX_BYTES } = {}) {
  // Seul Write fournit le contenu complet ; Edit est un patch ciblé, on l'ignore.
  if (input.tool_name && input.tool_name !== 'Write') return null;
  const content = input.tool_input?.content;
  if (typeof content !== 'string') return null;

  const bytes = Buffer.byteLength(content, 'utf8');
  if (bytes <= maxBytes) return null;

  const filePath = input.tool_input?.file_path ?? 'le fichier';
  const kb = Math.round(bytes / 1024);
  return {
    decision: 'block',
    reason:
      `Écriture de ${filePath} bloquée : ${kb} Ko (> ${Math.round(maxBytes / 1024)} Ko). ` +
      'Un fichier de cette taille est généralement un dump ou un blob généré qui gonfle le repo et le diff. ' +
      'Vérifiez l\'intention : générez-le à la volée, gitignorez-le, ou découpez-le.',
  };
}

/* 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));
}

Learn more

Related hooks