HookStack
Back to catalogue
ValidationPostToolUse· Write|Edit

Automatic formatting after write

Every file lands already Prettier-clean

After every file write or edit, runs Prettier on the modified file to ensure consistent formatting without agent intervention.

What does the Automatic formatting after write hook do?

Automatic formatting after write is a Claude Code PostToolUse hook matching Write|Edit. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Every file lands already Prettier-clean.

As a PostToolUse hook it runs after the action, reacting to what just happened rather than blocking it. 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

  • Style consistency
  • Reduced diff noise
  • Code quality

Tags

#validation#prettier#format#quality

settings.json fragment

{
  "hooks": {
    "PostToolUse": [
      {
        "hooks": [
          {
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/autoformat.mjs",
            "type": "command"
          }
        ],
        "matcher": "Write|Edit"
      }
    ]
  }
}

Script · .claude/hooks/autoformat.mjs

#!/usr/bin/env node
// @hookstack post-write-autoformat
// Formate le fichier avec Biome après écriture (PostToolUse Write|Edit)
import { execSync } from "node:child_process";
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";

function defaultExec(cmd) {
	execSync(cmd, { stdio: "ignore", timeout: 10_000 });
}

export function run(input, { exec = defaultExec } = {}) {
	const filePath = input.tool_input?.file_path ?? "";
	if (!filePath) return null;

	try {
		exec(`npx --no-install biome check --write "${filePath}"`);
		return { formatted: filePath };
	} catch {
		// biome absent, fichier hors périmètre, ou erreurs non auto-fixables — non bloquant
		return null;
	}
}

/* v8 ignore next 4 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
	const input = JSON.parse(readFileSync(0, "utf8"));
	run(input);
}

Learn more

Related hooks