Back to catalogue
ValidationPostToolUse· Write|EditPostToolUseAfter tool execution · non-blocking· non-blocking
ESLint lint after write
Lint errors fixed in the same loop, not in CI
Runs ESLint on the file just written and returns the errors to the agent so it fixes them immediately within the same loop.
What does the ESLint lint after write hook do?
ESLint lint 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. Lint errors fixed in the same loop, not in CI.
Use cases
- Continuous quality
- Auto-fix loop
- Lint standards
Tags
#validation#eslint#lint#quality
settings.json fragment
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/eslint-check.mjs",
"type": "command"
}
],
"matcher": "Write|Edit"
}
]
}
}Script · .claude/hooks/eslint-check.mjs
#!/usr/bin/env node
// Vérifie le fichier avec ESLint après écriture (PostToolUse Write|Edit)
import { readFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
function defaultExec(cmd) {
return execSync(cmd, { stdio: 'pipe', timeout: 15_000 });
}
export function run(input, { exec = defaultExec } = {}) {
const filePath = input.tool_input?.file_path ?? '';
if (!filePath || !/\.[cm]?[jt]sx?$/.test(filePath)) return null;
try {
exec(`npx --no-install eslint --max-warnings=0 "${filePath}"`);
return null;
} catch (err) {
const output = err.stdout?.toString() ?? '';
return output ? { message: `ESLint: ${output.trim()}\n` } : null;
}
}
/* 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?.message) process.stderr.write(result.message);
}