test-runner — Claude Code hook: run tests after every edit
This hook fires a test command right after Claude edits a file. Handy when you keep forgetting to re-run checks by hand.
npx claude-code-templates@latest --hook testing/test-runnerWhat test-runner does
The hook listens on PostToolUse with an Edit matcher. Once the agent saves a change, the command inspects the file extension and what sits next to it in the project.
For .js and .ts it wants a package.json, then runs npm test and falls back to yarn test. Python files go through pytest on that single file, gated on pytest.ini, setup.cfg or pyproject.toml. Ruby needs a Gemfile, after which bundle exec rspec takes over. Errors are suppressed, so a failing suite won't break your session — and you won't see why it failed either.
Dropping it into a repo with no test setup does nothing: without package.json, pytest.ini or Gemfile, no branch of the command runs.
What it helps with
- run tests right after a file edit
- catch a regression while the agent still has context
- skip switching to a terminal for
npm test - check one changed file instead of the whole suite
- cover Python and Ruby in the same project
Example prompts for the agent
- Edit
src/api/users.tsand run the tests afterwards - Fix
app/models/order.py— the hook will run pytest on that file - Update
lib/parser.rband confirm rspec passes
How to install test-runner
1claude-code-templates
npx claude-code-templates@latest --hook testing/test-runner2Manually: put the files in place
.claude/settings.jsonThe 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 test-runner
How do I install test-runner in Claude?
Run npx claude-code-templates@latest --hook testing/test-runner, then check .claude/settings.json — the hook entry should be written there.
What does test-runner do?
After each file edit it runs the matching test command: npm test or yarn test for JS and TS, pytest for Python, bundle exec rspec for Ruby.
Why aren't my tests running?
The hook only fires when project markers exist: package.json for JS and TS, pytest.ini, setup.cfg or pyproject.toml for Python, Gemfile for Ruby. Without them the command exits quietly.
Source text
test-runner.json · MIT
{
"description": "Automatically run relevant tests after code changes. Detects test files and runs appropriate test commands based on file extensions and project structure.",
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "if [[ \"$CLAUDE_TOOL_FILE_PATH\" == *.js || \"$CLAUDE_TOOL_FILE_PATH\" == *.ts ]] && [[ -f package.json ]]; then npm test 2>/dev/null || yarn test 2>/dev/null || true; elif [[ \"$CLAUDE_TOOL_FILE_PATH\" == *.py ]] && [[ -f pytest.ini || -f setup.cfg || -f pyproject.toml ]]; then pytest \"$CLAUDE_TOOL_FILE_PATH\" 2>/dev/null || python -m pytest \"$CLAUDE_TOOL_FILE_PATH\" 2>/dev/null || true; elif [[ \"$CLAUDE_TOOL_FILE_PATH\" == *.rb ]] && [[ -f Gemfile ]]; then bundle exec rspec \"$CLAUDE_TOOL_FILE_PATH\" 2>/dev/null || true; fi"
}
]
}
]
}
}
© davila7 · MIT · davila7/claude-code-templates