Watch Kalku explain it in three minutes

Your tests pass. But do they test anything?

kalku breaks your code on purpose, one small defect at a time, and sees whether any test notices. A defect that no test catches is a hole in your suite, and kalku shows it to you with a file, a line and a diff.

brew install lnds/kalku/kalku

why this name?

Kalku, the mascot of kalku: a black condor in a red headband and scarf, grinning with a mouthful of teeth
kalku run
$ kalku run lib/green.ex --limit 6 --verbose
lib/green.ex:4  compare  Green.classify/1
  - >=
  + >
  covered by 4 tests
  No test tells `>=` apart from `>` in
  `Green.classify/1`. Add a case at the boundary
  where the two sides are equal.

score 60% · 3 killed · 2 survived · 1 compile error

the report of a run, as it appears in the README of kalku

What it does

Six reasons to let Kalku break your code

Coverage tells you which lines ran. kalku tells you whether any test would notice when one of them is wrong.

01

Holes first

A report starts with the survivors: the defects no test caught, each with its file, its line, its diff and a hint. The score comes after, as context, because the survivor is the thing you can act on.

$ kalku run lib/green.ex --limit 6
lib/green.ex:4  compare  Green.classify/1
  - >=
  + >
  covered by 4 tests
02

An honest score

The score is killed / (killed + survived) and nothing else moves it. A timeout, a crash, a wekufe that did not compile or a line no test reaches are reported apart: they never count as a kill.

$ kalku info outcomes
  killed         counts towards the score
  survived       counts towards the score
  timeout        reported apart from the score
  no_coverage    reported apart from the score
  compile_error  reported apart from the score
  crashed        reported apart from the score

score 60% · 3 killed · 2 survived · 1 compile error
03

Your project is never touched

Wekufe are cast in the reni, an isolated workspace under the temporary directory of your machine. A project with no configuration is measured as it is and left as it is: nothing is written into it.

$ kalku run lib/thing.ex
kalku: no .kalku.toml in this directory:
measuring it as elixir and leaving it as it is.
What the run keeps is in $TMPDIR/kalku/thing;
`kalku init` sets the project up to keep it.
04

Fast: a warm kalku

Each wekufe is loaded into a warm kalku and runs only against the tests that cover it, stopping at the first one that fails. With kalku serve, the kalku a project was measured with outlive the run, and the next one does not set the project up again.

$ kalku serve          # a 0600 Unix socket
$ kalku cast <wekufe>  # re-cast just that one,
                       # against a warm kalku
05

In CI, only what changed

kalku run --since origin/main measures the lines the change touched and blocks only on the holes that change introduced. Old debt does not punish whoever touches the file, and the exit codes separate "your tests have holes" from "kalku could not measure".

$ kalku run --since origin/main
# exit 0  measured; nothing to report
# exit 1  your tests have holes
# exit 2  kalku could not measure
06

Built for coding agents

Agents write tests fast; kalku tells them whether those tests test anything. Each survivor arrives as one JSON object with everything needed to act, and kalku mcp serves four tools over stdio. None of them suppresses, excludes or ignores anything.

Hints come from a fixed template per spell, not from a model. An agent can only propose an equivalent mutant; a person has to accept it.

$ kalku run lib/my_app/parser.ex --format agent
{"wekufe":"c1f3…",
 "file":"lib/my_app/parser.ex","line":42,
 "enclosing":"MyApp.Parser.next_token/2",
 "spell":"compare",
 "original":">=","replacement":">",
 "covering_count":1,"hint":"No test tells…"}

Video

kalku, explained by Kalku

Three minutes on what mutation testing is, how you use kalku and why it matters. Kalku tells it in the first person: he is a sorcerer, and breaking code is his trade.

Míralo en español

Commands

Everything kalku brings

One binary. And kalku info documents the spells, the outcomes and the formats from the program itself.

Measure

kalku run
Casts wekufe over those files and reports the survivors
kalku cast
Re-casts a wekufe after a test was written
kalku show
One wekufe in full: site, diff, tests, hint and history

In the project

kalku init
Detects the language and writes .kalku.toml and .kalku/summon
kalku propose-equivalent
Proposes a wekufe as equivalent, with its reason
kalku accept
A person accepts the proposal, which goes into .kalku/equivalent
kalku reject
Turns the proposal down: the wekufe wants a test again

Tools

kalku info
Spells, outcomes, formats and the agent loop
kalku serve
Keeps the kalku warm behind a local socket
kalku mcp
Serves the agent tools to an MCP host, over stdio

Shall we let him break something?

It installs with one command and needs no configuration. Start with kalku run on one file of your project.

brew install lnds/kalku/kalku