Runs mutation testing.
Options
--files "PATTERN"— Only mutate files matching glob pattern. Quote globs so your shell does not expand them first. Repeat the flag, pass multiple path tokens after it, or use comma-separated patterns to mutate several paths.--test-paths "PATH"— Restrict test discovery to these paths (default:test/for a single app, every child app's<apps_path>/<child>/test/for an umbrella). Repeat the flag, pass multiple path tokens after it, or use comma-separated paths, exactly like--files. Paths must be project-relative.--mutators NAMES— Comma-separated mutator name list--enable TARGETS— Comma-separated enabled targets. Defaults:dispatch,guard,env_walker(only AtomLiteral active; pass it explicitly to run all env-walker literals),pattern_shape. Opt-in:module_attribute,body_literal,pattern_literal,variable,conditional,statement_delete,clause_delete,guard_boolean,pipeline_drop,map_update_drop,receive_timeout. Passing --enable replaces the default enabled targets and selects the default selectable mutator set gated by the listed targets. Note: an opt-in mutator selected via--mutatorsALSO needs its target enabled, and a few experimental mutators require--mutatorsexplicitly (see docs/MUTATORS.md).--fail-at SCORE— Mutation score threshold; exit 1 below (default: 80)--reporters NAMES— Comma-separated:terminal,stryker-json(default: both),html,github-actions(opt-in)--output-path PATH— Report output path (default:stryker.report.json). Absolute paths are honored; relative paths are under the project root. Thehtmlreporter writes the same path with a.htmlextension.--concurrency N— Worker pool size for parallel mutant execution. Default: min(schedulers_online, 4). Use--concurrency 1for sequential execution. Explicit values are bounded to avoid pathological sandbox startup/teardown costs.--max-mutants N— Cap total mutants (stable-id sorted sample if exceeded). Limits planned mutant executions before coverage collection. Oracle construction and planning still run in full; coverage still collects the selected test files.--debug-plan— Dump plan JSON to plan.debug.json and exit before any mutant runs. It still builds the oracle and baseline plan; it is not a zero-cost parser-only mode.--selection MODE— Test selection mode:static,coverage,coverage_with_static_fallback(default).staticis the fully-portable escape hatch — also the fast choice on macro-heavy/generated apps (e.g. Phoenix) where coverage collection is slow before it falls back.--keep-work-copy— Skip cleanup of the run's temporary work copies on exit and print their retained paths (debug aid; default: false)--test-timeout-ms N— Per-test ExUnit timeout in milliseconds. Default 10000. Range 1000..600000.--suite-timeout-ms N— Whole-suite host budget, in milliseconds, for one mutant's selected tests (range 1000..3600000). The host kills the mutant's test port aftermax(test_timeout_ms, suite_timeout_ms)plus a 10000 ms drain buffer. Unset (the default) it is derived from the measured baseline run:max(test_timeout_ms, min(baseline_wall_ms * 2, 600000)) + 10000. Deriving it matters because several individually valid slow tests can otherwise exceed a budget sized for a single test, and the resulting host timeout counts as a detection and inflates the score.--priv-fingerprint stat|hash— How each sandbox's copiedpriv/tree is fingerprinted for the between-mutant reset.stat(the default) compares size + mtime: cheap, but it misses a rewrite that keeps the byte size AND lands in the same mtime second.hashcompares content: exact, at the cost of reading everypriv/file on every reset (per mutant, per worker). Usehashwhen tests rewrite fixtures underpriv/in place.--incremental— Reuse verdicts from a prior run's history for unchanged mutants instead of re-executing them (opt-in; seehistory_pathconfig). Materially changes execution and report interpretation.--since REF— With--incremental, force execution of mutants whose file changed since gitREF(e.g.HEAD~1,main). Other mutants remain eligible only if all digest checks pass. Outside a git repo or with an unknown ref, reuse falls back to digest checks with a warning.
Configuration
Settings can come from four layers, lowest to highest precedence:
.mutalisk.exs project file < legacy `config :mut` < config :mutalisk < CLI flagsA CLI flag always wins; config :mutalisk overrides both config :mut (a
deprecated, still-accepted namespace kept for compatibility) and the file;
the file is the base. Keys (same names in all layers): files, test_paths, mutators,
enabled_targets, selection, fail_at, concurrency, test_timeout_ms,
suite_timeout_ms, priv_fingerprint, reporters, output_path, exclude, max_mutants,
since, incremental, history_path, and
coverage_timeout_ms. exclude, history_path, and
coverage_timeout_ms are config-only (no CLI flag); the rest accept a CLI
flag that overrides config. history_path controls where every run writes
reusable verdict history for future --incremental runs. coverage_timeout_ms
is a positive integer in milliseconds for each per-test-file coverage
collection attempt. Timed-out or failed files have unknown coverage and are
included conservatively in every mutant's selection. Run-scoped switches
debug_plan and keep_work_copy are CLI-only.
When test_paths is unset it defaults to test/ for a single app and to
every child app's <apps_path>/<child>/test/ for an umbrella. Set it explicitly only
to override that — note a bare ["test"] finds no tests in an umbrella.
.mutalisk.exs (in the project root, loaded if present) is a plain
keyword-list term — no Config runtime needed:
# .mutalisk.exs
[
selection: :coverage_with_static_fallback,
fail_at: 75.0,
concurrency: 8,
exclude: [~r"lib/my_app_web/router.ex"]
]Or via application config:
config :mutalisk,
exclude: [~r/lib\/my_app_web\/router.ex/],
fail_at: 80.0,
selection: :coverage_with_static_fallback,
concurrency: System.schedulers_online()Source-level ignores
Add @mutalisk_ignore true to a module to exclude every mutant in that
module (generated/DSL modules, intentionally-untested code):
defmodule MyApp.Generated do
@mutalisk_ignore true
# ... no mutants are produced for this module ...
endRun as MIX_ENV=test mix mut.