Umpire

Built by modmyclaude

Runs your tests after Claude edits code and makes the call. Off by default.

Workflowv0.2.0
Umpire running in Claude Code
An illustration of Umpire, drawn from the mod's own text.
Tests36 passing
Model callsnone
Commands1
Settings4

Run tests after file edits

Umpire runs your tests after Claude Code edits files with its own tools and shows the result. Automatic runs are off by default.

Reported behavior and access

Files Engine-managed mod store

Runs your one test command in the project root and reads the project files that name it. Keeps run output in memory and your per-project command in its own store.

Shell commands Subprocesses used

Runs your one test command in the project root and reads the project files that name it. Keeps run output in memory and your per-project command in its own store.

Network No network

The reviewed README reports no network requests of its own. Your test command may do anything your tests do.

Added model calls None reported

The reviewed README reports no model calls of its own. Ordinary Claude Code work still uses your model.

Sound Not reviewed

Behavior has not been source-reviewed for this version. Check the README before relying on its access.

Handled events config.set "umpire.enabled", session.start, tool.call, turn.start, turn.complete, ui.render AbovePrompt, ui.render Pane, command.run /umpire

Event registration does not mean blocking. Read the source for whether an event observes, changes or holds an action.

README-reported behavior, not a sandbox guarantee. Source v0.2.0, 8da3430, reviewed 22 Oct 2026

Original Claude Code validator report

reads files

Can read files, but cannot write them.

commands

Can run commands.

network

Does not make network requests.

model

Does not call a model.

sound

Does not play sound.

Validator hook registrations

Uses hooks: config.set, tool.call.

Static validator signals can miss indirect effects, optional configuration and engine-managed storage.

How it works

Slash commands

/umpire

Runs your tests after Claude edits code: on, off, run, show, command, tell

Settings

enabledDefault: true
Switch umpire off without uninstalling it. The modmyclaude hub flips this too.
startOnDefault: false
Run the tests after every turn that changes files, in every session, without typing /umpire on.
commandDefault:
The command to run, as you would type it (run through sh). Empty: found from the project (package.json's test script, pytest, go test, cargo test).
maxSecondsDefault: 120
A run longer than this is stopped and called timed out. 5 to 600.

Hook events

config.set "umpire.enabled"session.starttool.callturn.startturn.completeui.render AbovePromptui.render Panecommand.run /umpire

The prompt

Details

Runs your tests after Claude edits code and makes the call: passed and failed counts above the prompt, a toast when it flips. Off by default.

umpire: 142 passed · 2 failed · auth.test.ts, user.test.ts · 8.3 s

Use it

Type /umpire on. From then on, at the end of every turn in which Claude changed files with its own tools (Edit, Write, NotebookEdit), umpire runs your project's tests once, and:

  • A line above the prompt makes the call: passed and failed counts, the first three failing tests or files (+2 more past that) and how long it took, in the error colour when something fails. While the tests run it says so.
  • A toast only when the call flips: the tests started failing, or they pass again. Never on every run.
  • The status line keeps the count: tests 142/144.
  • /umpire show opens the last run: the call, a mark per run for the last ten, the failing names, and the end of the output. tell Claude puts the failing names and the output's last 30 lines in your prompt box, after anything you typed, with anything that looks like a secret redacted. You decide whether to send it.
  • A hold when a file that says what the tests run changes: package.json, pyproject.toml, pytest.ini, go.mod or Cargo.toml. Claude editing one anywhere in the project, or anything changing one at the project root (a shell command, you), stops the runs that start on their own, and the line says which file. They wait until you start a run with /umpire run or run again, so a test command Claude just changed waits for you to start it.

It finds the test command once per session: your setting, else the one you set for this project with /umpire command, else package.json's test script (through pnpm, yarn, bun or npm, by lockfile), pytest, go test ./... or cargo test. It understands the summaries of Jest, Vitest, pytest, go test and cargo test; for anything else, the exit code makes the call.

CommandWhat it does
/umpire onRun the tests after each turn that changes files (only when you type it)
/umpire offStop
/umpire runRun them now (only when you type it)
/umpire showThe last run, in a pane
/umpire command <cmd>Set this project's test command, as you would type it (only when you type it)
/umpire tellPut the failures in your prompt box (only when you type it)

"Only when you type it" means typed by you in the terminal, the desktop app or Remote Control. A program you run that drives Claude Code through its SDK counts as you too, since the desktop app sends that way; another mod, a peer session or Claude running the command is refused.

Settings

Every setting has a default, so the notice at install about options not yet set is expected; change them in /config.

  • On: on by default. Off, Umpire runs nothing and draws nothing, and every /umpire command says it is off; switched on again, /umpire on (or the setting below) decides, as before. /config or the modmyclaude hub flips it, live. It runs commands, so another mod cannot switch it on; anyone can switch it off.
  • On from the start: run in every session without /umpire on. Off by default.
  • Test command: the command to run, as you would type it. Empty: found from the project.
  • Time limit (seconds): 120 by default; a longer run is stopped and called timed out.

What it can touch

  • Runs: the one test command, in the project root, with CI=1 and colour off so test runners do not wait in watch mode, stopped at the time limit. A command you typed (the setting or /umpire command) runs through sh as you wrote it. Nothing else.
  • Reads: the project's package.json, pyproject.toml, pytest.ini, go.mod and Cargo.toml, and whether a lockfile or tests/ exists, to find the command and to see when one of those files changes. The paths of the files Claude's tools edit, to hold the runs when one of them is such a file.
  • Keeps: the last ten runs' output, a million characters at most, in the mod's memory only. The command you set per project in its own store, keyed by a hash of the project's path.
  • Writes: its session state (on or off, the runs' calls, the hold), the line, the status line, toasts, and your prompt box when you press tell Claude, never sent.
  • Network, model calls: none of its own. Your tests may do anything your tests do.

Limits

  • Changes a shell command made (a formatter, a codegen script) do not trigger a run; only Claude's own file tools do. /umpire run covers the rest.
  • One run at a time: a turn that ends during a run queues exactly one more, run when the first is done.
  • Counts come from the test runner's summary line; go test without -v names failing tests but counts no passes.
  • The run's output is shown as the runner printed it, without colour. Long output keeps its end. Past 4 MB the engine stops keeping it: the call then says output cut at 4 MB and may have no counts.
  • The hold covers the files that say what the command runs. The tests themselves are code, and Claude may have written them: umpire runs them as your test runner would, so turn it on only where you would run the tests yourself. A command you set that reads another file (a Makefile) is not held when that file changes.
  • The line, the pane and the presses are checked through the engine's test kit on the terminal and desktop surfaces, with the test runner stood in for.

Built from a prompt

This mod was built from the Umpire prompt.

added 12 Oct 2026updated 23 Oct 2026MITSource on GitHub

Pairs well with