Skip to main content
hook

lint-on-save — Claude Code hook: lint after every edit

The hook fires a linter right after the agent changes a file. ESLint, Pylint or RuboCop runs on its own, no manual call needed.

Install into Claude Code · claude-code-templates All methods and platforms ↓
npx claude-code-templates@latest --hook development-tools/lint-on-save
Open on GitHub

What lint-on-save does

It attaches to the PostToolUse event with the matcher Edit|MultiEdit. When Claude touches a file, the command reads the extension and picks a tool: npx eslint with --fix for .js, .ts, .jsx and .tsx, pylint for .py, rubocop --auto-correct for .rb. Linter failures are swallowed by 2>/dev/null || true, so a noisy warning never derails the agent.

The file path comes from $CLAUDE_TOOL_FILE_PATH. Anything outside those extensions falls through the if chain and nothing runs. There is no project-wide sweep either — only the file the agent just edited gets linted.

Worth adding if your project already has one of the three linters configured. ESLint goes through npx, so you need Node and the package installed locally, otherwise the command quietly does nothing. Same story for pylint and rubocop: both must be on your PATH.

What it helps with

  • catch a style error right after a file edit
  • stop running the linter by hand on every changed file
  • auto-fix small JS and TS issues with --fix
  • check Python files after the agent rewrites them
  • keep Ruby code tidy without a separate pipeline step

Example prompts for the agent

  • fix src/utils.ts and let the linter run afterwards
  • rewrite app/models/user.rb, the hook will call rubocop
  • edit scripts/parse.py and show me what pylint says

How to install lint-on-save

1claude-code-templates

npx claude-code-templates@latest --hook development-tools/lint-on-save

2Manually: put the files in place

.claude/settings.json

The hooks block: event (PreToolUse, PostToolUse, Stop…) → command. Personal ones go to ~/.claude/settings.json

Step by step, with commands for each platform: Claude Code hooks: what they are, where to configure them, how to block a risky command

Questions about lint-on-save

How do I install lint-on-save in Claude?

Run npx claude-code-templates@latest --hook development-tools/lint-on-save, then check the entry in .claude/settings.json.

What does lint-on-save do?

After a file edit it runs the matching linter: ESLint for JS and TS, Pylint for Python, RuboCop for Ruby. Linter errors do not interrupt the agent.

Which files does the hook cover?

Only .js, .ts, .jsx, .tsx, .py and .rb. Other extensions are skipped because no branch of the condition matches.

Source text

lint-on-save.json · MIT
{
  "description": "Automatically run linting tools after file modifications. Supports ESLint for JavaScript/TypeScript, Pylint for Python, and RuboCop for Ruby.",
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "if [[ \"$CLAUDE_TOOL_FILE_PATH\" == *.js || \"$CLAUDE_TOOL_FILE_PATH\" == *.ts || \"$CLAUDE_TOOL_FILE_PATH\" == *.jsx || \"$CLAUDE_TOOL_FILE_PATH\" == *.tsx ]]; then npx eslint \"$CLAUDE_TOOL_FILE_PATH\" --fix 2>/dev/null || true; elif [[ \"$CLAUDE_TOOL_FILE_PATH\" == *.py ]]; then pylint \"$CLAUDE_TOOL_FILE_PATH\" 2>/dev/null || true; elif [[ \"$CLAUDE_TOOL_FILE_PATH\" == *.rb ]]; then rubocop \"$CLAUDE_TOOL_FILE_PATH\" --auto-correct 2>/dev/null || true; fi"
          }
        ]
      }
    ]
  }
}

© davila7 · MIT · davila7/claude-code-templates

Similar hooks

All hooks for Agent setup: memory, context, orchestration →

From the same set205

The whole set →

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor