---
name: mutineer
description: Clean-room mutation testing for Ruby (Prism + stdlib, zero deps). Mutates source one change at a time, runs the suite against each mutant, and reports the mutants tests fail to catch, with a versioned JSON contract and CI/agent gating. Use when checking whether a Ruby test suite would catch a change, finding weak or missing tests, gating CI on a mutation score, or acting on mutineer's JSON report.
---

# Mutineer

Mutation testing for Ruby, built for CI gates and AI coding agents. Line coverage tells
you which code *ran*; mutation testing tells you whether your tests would *notice if it
broke*.

## Install

```sh
gem install mutineer
```

## Run

```sh
mutineer run <source...> --test <test> [--test <test>...] [options]
```

Example — mutate `lib/calculator.rb`, gate CI below 90%:

```sh
mutineer run lib/calculator.rb --test test/calculator_test.rb --threshold 90
```

## Agent loop

1. Edit code + tests on a branch.
2. Run diff-scoped, as JSON:
   ```sh
   mutineer run app/ --since origin/main --threshold 90 --format json --output .mutineer/run.json
   ```
3. Parse `survivors[]` — each carries a `diff` and an `id`. File moves, renames,
   project-root changes, and changes to repeated-name or repeated-mutation order can
   change ids; see [Mutant ids](https://github.com/davidteren/mutineer#mutant-ids). For each, write/strengthen a
   test that fails under that change.
4. Re-run. Accept the result only when this run exits `0`, `summary.score` is not `null`,
   and `summary.score >= 90`. If every scored mutant must be killed, also require `summary.survived == 0`;
   the score is rounded, so `--threshold 100` alone can still pass with a survivor.

A survivor you cannot kill after a few attempts may be equivalent: no test can
tell it from the original. Do not loop on it. Report it for human review. To
suppress it, `mutineer triage .mutineer/run.json --reason TEXT --id ID` prints an
`ignore:` entry for `.mutineer.yml` (Mutineer 1.7 or later reads it). See
[Suppressing equivalent mutants](https://github.com/davidteren/mutineer#suppressing-equivalent-mutants).

Keep `fail_fast` disabled (the default). If the active `.mutineer.yml` sets it to
`true`, temporarily change that value to `false` for the loop. Restore the original
value when the loop ends, before committing. A fail-fast run is partial,
and its score and exit code do not cover the full scope.

Zero survivors alone is not success: an empty or fully suppressed scope, or a run
with no usable verdicts, also has zero survivors. If the score is null, stop and
report “no score”. Check `no_coverage[]` for test gaps and `no_verdict[]` for
harness failures, and fix them before starting a new run. A positive threshold fails when nothing can be scored and something
broke, or when more than one mutant has no verdict and they exceed 10% of those
attempted; it does not require zero errors. Set the threshold to your target.

An empty run (`summary.total` is 0) exits 0 in 1.x and prints a warning on stderr. Treat it as "no score". Pass `--allow-empty` only when an empty run is expected. A `--since` run whose changes hold no mutable code says "nothing to test in the changes since REF"; that is a valid success. Warnings that start with `mutineer:` or `[mutineer]` also go to stderr: the empty-run warning, "did you mean" hints, notes about Mutineer 2.0, the count of errored mutants, and a notice that a `PARALLEL_WORKERS` value you set was replaced with 1.

## Exit codes

<!-- contract:exit-codes -->
| Code | Meaning |
|------|---------|
| `0` | Score ≥ threshold (or no gate) **and** no baseline regression. |
| `1` | Score below `--threshold`, OR nothing could be scored and something broke, or more than one mutant produced no verdict and they exceed 10% of those attempted, OR a `--baseline` regression, OR a runtime error. |
| `2` | Usage / invalid-flag error (mistyped flag, bad path, unreadable baseline). |
<!-- /contract:exit-codes -->

## References

- Docs: https://davidteren.github.io/mutineer/
- Agent & CI guide: https://davidteren.github.io/mutineer/agentic-coding.html
- JSON schema: https://davidteren.github.io/mutineer/json-schema.html
- Ruby API: https://davidteren.github.io/mutineer/api/
- Source: https://github.com/davidteren/mutineer
