CLI Reference
Complete reference for every FlakeMonster command, flag, and option. All commands are available via npx flake-monster or as a global install.
flake-monster test
The primary command. Injects deterministic async delays into your source files, runs your test suite multiple times with different seeds, analyzes the results for flaky tests, then restores your source files to their original state.
Usage
$ flake-monster test [options] [globs...]
Options
| Flag | Default | Description |
|---|---|---|
-r, --runs <n> |
10 |
Number of test runs to execute. Each run uses a different derived seed so timing varies between iterations. |
-m, --mode <mode> |
medium |
Injection density. Controls how many async points receive delays. One of: light, medium, hardcore. |
-s, --seed <seed> |
auto |
Base seed for deterministic delay generation. Use a number for reproducible runs, or auto to generate a random seed. Each run derives its own seed from this base. |
-c, --cmd <command> |
npm test |
The test command to execute on each run. Can be any shell command: npm test, npx jest, node --test, etc. |
--in-place |
true |
Modify source files directly (the default). Files are restored after all runs complete, or on error. |
--workspace |
false |
Use isolated workspace copies instead of modifying source files. Each run gets its own copy of the project under .flake-monster/workspaces/. |
--keep-on-fail |
false |
Keep the workspace directory when a test run fails (workspace mode only). Useful for inspecting injected code after a failure. |
--keep-all |
false |
Keep all workspace directories after runs complete, regardless of pass or fail (workspace mode only). |
-f, --format <format> |
text |
Output format. Use text for human-readable terminal output, or json for machine-readable output suitable for CI pipelines. |
--runner <runner> |
auto |
Test runner output parser. One of: jest, node-test, playwright, tap, auto. When set to auto, FlakeMonster detects the runner from your test command. |
--min-delay <ms> |
0 |
Minimum injected delay in milliseconds. Delays are computed at injection time and embedded directly in source code. |
--max-delay <ms> |
50 |
Maximum injected delay in milliseconds. Higher values increase the chance of exposing timing-dependent flakes, but slow down test execution. |
-e, --exclude <patterns...> |
— | Glob patterns to exclude from injection. Appends to any patterns defined in your config file. Example: --exclude "src/vendor/**". |
[globs...] |
src/**/*.js |
File patterns to inject delays into. Passed as positional arguments after all flags. |
Examples
Basic usage with defaults
$ npx flake-monster test --cmd "npm test"
Injects delays into src/**/*.js, runs npm test 10 times in medium mode, then restores.
Fast scan with fewer runs
$ npx flake-monster test --runs 3 --cmd "npx jest"
Quick 3-run check. Good for a first pass before committing to a longer run.
Reproduce a specific failure
$ npx flake-monster test --runs 1 --seed 948271536 --cmd "npm test"
Replays the exact same delays that caused a failure. The seed is printed in the output of each failing run.
Hardcore mode with custom delay range
$ npx flake-monster test --mode hardcore --max-delay 200 --runs 20 --cmd "npm test"
Maximum injection density with delays up to 200ms across 20 runs. Thorough but slow.
Custom file patterns with exclusions
$ npx flake-monster test --cmd "npm test" --exclude "src/generated/**" "src/**/*.js" "lib/**/*.js"
Injects into both src/ and lib/, skipping generated files.
Workspace mode with failure inspection
$ npx flake-monster test --workspace --keep-on-fail --cmd "npm test"
Runs each iteration in an isolated copy. When a run fails, the workspace is preserved so you can inspect the injected code.
JSON output for CI
$ npx flake-monster test --format json --cmd "npm test" > flake-report.json
Writes structured JSON to a file. See JSON Output for the full schema.
Using node:test
$ npx flake-monster test --cmd "node --test test/**/*.test.js" --runner node-test
FlakeMonster automatically appends --test-reporter tap when it detects node --test, since the default spec reporter outputs to stderr.
Tip: If a run is interrupted (Ctrl+C, crash, etc.), FlakeMonster detects stale injections on the next run and automatically restores your files before proceeding. You can also run
flake-monster restoremanually.
flake-monster inject
Inject async delays into source files without running tests. Useful for manual inspection of what FlakeMonster inserts, or for integrating with a custom test workflow.
Usage
$ flake-monster inject [options] [globs...]
Options
| Flag | Default | Description |
|---|---|---|
-m, --mode <mode> |
medium |
Injection density: light, medium, or hardcore. |
-s, --seed <seed> |
auto |
Random seed for deterministic delays. Use a number for reproducibility or auto for a random seed. |
--in-place |
true |
Modify source files directly (the default). |
--workspace |
false |
Create a workspace copy instead of modifying source files. The injected workspace path is printed to the terminal. |
--min-delay <ms> |
0 |
Minimum injected delay in milliseconds. |
--max-delay <ms> |
50 |
Maximum injected delay in milliseconds. |
-e, --exclude <patterns...> |
— | Glob patterns to exclude from injection. |
[globs...] |
src/**/*.js |
File patterns to inject delays into. |
Examples
Inject and inspect
$ npx flake-monster inject --seed 12345 # Now look at your source files to see the injected delays $ git diff # When done, restore them $ npx flake-monster restore
Inject into a workspace copy
$ npx flake-monster inject --workspace --seed 42 "src/**/*.js" # Workspace created: .flake-monster/workspaces/inject-seed-42 # Run tests manually against the workspace
Hardcore injection with high delays
$ npx flake-monster inject --mode hardcore --max-delay 500 "lib/**/*.js"
Safety: If you run
injectwhile a previous injection is still active, FlakeMonster will detect it and prompt you to restore first. This prevents double-injection.
What gets injected
FlakeMonster inserts two things into each file it touches:
- A runtime import at the top of the file that provides the delay function.
- One or more
await __FlakeMonster__(N)statements at async injection points, whereNis a deterministic delay in milliseconds. Each injected line is tagged with a marker comment for reliable removal.
The delay value N is computed at injection time from the seed, not at runtime. You can manually edit the delay value in the source if you want to experiment with specific timings.
flake-monster restore
Remove all injected delays and restore source files to their original state. Normally called automatically at the end of a test run, but available as a standalone command for manual cleanup.
Usage
$ flake-monster restore [options]
Options
| Flag | Default | Description |
|---|---|---|
--in-place |
true |
Restore in-place modified files (the default). |
--recover |
false |
Interactive recovery mode. Scans source files for traces of injected code, shows what was found, and asks for confirmation before removing. |
--dir <path> |
project root | Directory to restore. Defaults to the current working directory. |
Normal restore
When a manifest file exists (created during injection), restore reads it to know exactly which files were modified and removes all injected lines:
$ npx flake-monster restore Restored 12 file(s), removed 47 injection(s)
The manifest is deleted after a successful restore.
Recovery mode
If the manifest is missing or corrupt (e.g., after a crash or manual file deletion), recovery mode scans your source files for any remaining traces of FlakeMonster injection. It matches on two patterns:
- The marker comment stamp (
@flake-monster[jt92-se2j!]) that tags every injected line - The
__FlakeMonster__identifier used in runtime imports and delay calls
$ npx flake-monster restore --recover Scanning all source files... src/api/client.js (3 matches): L2 [import] import { __FlakeMonster__ } from '../flake-monster.runtime.js'; L15 [stamp] await __FlakeMonster__(23); // @flake-monster[jt92-se2j!] v1 L42 [stamp] await __FlakeMonster__(7); // @flake-monster[jt92-se2j!] v1 src/utils/cache.js (2 matches): L1 [import] import { __FlakeMonster__ } from '../flake-monster.runtime.js'; L28 [stamp] await __FlakeMonster__(31); // @flake-monster[jt92-se2j!] v1 Total: 5 line(s) across 2 file(s) Remove these lines? (y/N) y Recovered 2 file(s), removed 5 line(s)
Tip: If you run
restorewith no manifest and no--recoverflag, FlakeMonster will automatically scan for leftover injections and offer to run recovery if any are found.
Restore a specific directory
$ npx flake-monster restore --dir ./packages/api
Restores files within the specified directory. Useful in monorepo setups or when you need to target a specific package.
Exit Codes
FlakeMonster uses conventional exit codes so it integrates cleanly with CI systems, shell scripts, and other tooling.
| Code | Meaning |
|---|---|
0 |
All runs passed. Every test run exited cleanly. No flaky tests detected under the current configuration. |
1 |
At least one run failed. One or more test runs returned a non-zero exit code, indicating potential flaky tests. The report will include which seeds triggered failures. |
In a CI pipeline, you can use the exit code to gate merges:
# .github/workflows/flake-check.yml - name: Check for flaky tests run: npx flake-monster test --runs 5 --cmd "npm test" # Step fails if exit code is 1 (flakes detected)
Note: Source files are always restored before FlakeMonster exits, even when runs fail. The exit code reflects test results, not the restore status.
JSON Output
Use --format json to get machine-readable output. This is ideal for CI pipelines, dashboards, or custom tooling that needs to parse FlakeMonster results programmatically.
$ npx flake-monster test --format json --cmd "npm test"
When --format json is set, all human-readable terminal output (progress bars, injection stats, run summaries) is suppressed. Only the final JSON object is written to stdout.
Schema
{
"version": 1,
"baseSeed": 3221704130,
"runs": [
{
"runIndex": 0,
"seed": 3221704130,
"exitCode": 0,
"durationMs": 4523,
"parsed": true,
"totalPassed": 15,
"totalFailed": 0
},
{
"runIndex": 1,
"seed": 1847293651,
"exitCode": 1,
"durationMs": 5102,
"parsed": true,
"totalPassed": 13,
"totalFailed": 2
}
],
"analysis": {
"totalTests": 15,
"flakyTests": [
{
"name": "checkout > applies discount",
"file": "test/checkout.test.js",
"passedRuns": [0, 2, 3, 4],
"failedRuns": [1],
"flakyRate": 0.2
}
],
"stableTests": [
{
"name": "auth > login succeeds",
"file": "test/auth.test.js",
"verdict": "stable-pass"
}
],
"alwaysFailingTests": []
}
}
Field reference
| Field | Type | Description |
|---|---|---|
version |
number |
Schema version. Currently always 1. |
baseSeed |
number |
The base seed used for the test session. All per-run seeds are derived from this value. |
runs |
array |
One entry per test run, in execution order. |
runs[].runIndex |
number |
Zero-based index of the run. |
runs[].seed |
number |
The derived seed used for this run. Pass this to --seed with --runs 1 to reproduce. |
runs[].exitCode |
number |
Exit code of the test command. 0 = passed, non-zero = failed. |
runs[].durationMs |
number |
Wall-clock time of the test command in milliseconds. |
runs[].parsed |
boolean |
Whether the test output was successfully parsed by the runner parser. If false, individual test results are unavailable. |
runs[].totalPassed |
number |
Count of individual tests that passed in this run. |
runs[].totalFailed |
number |
Count of individual tests that failed in this run. |
analysis |
object |
Flakiness analysis computed across all runs. |
analysis.totalTests |
number |
Total unique tests observed across all runs. |
analysis.flakyTests |
array |
Tests that passed in some runs and failed in others. Sorted by flakyRate descending (most flaky first). |
analysis.flakyTests[].name |
string |
Full test name as reported by the runner. |
analysis.flakyTests[].file |
string |
Source file containing the test (when available from the runner). |
analysis.flakyTests[].passedRuns |
number[] |
Run indices where this test passed. |
analysis.flakyTests[].failedRuns |
number[] |
Run indices where this test failed. |
analysis.flakyTests[].flakyRate |
number |
Ratio of failed runs to total runs for this test (0 to 1). |
analysis.stableTests |
array |
Tests that passed in every run. Each entry has name, file, and verdict: "stable-pass". |
analysis.alwaysFailingTests |
array |
Tests that failed in every run (broken, not flaky). Each entry has name, file, and verdict: "always-failing". |
Example: parse results in CI
# Run FlakeMonster and capture JSON output $ npx flake-monster test --format json --cmd "npm test" > results.json 2>/dev/null # Extract flaky test names with jq $ jq -r '.analysis.flakyTests[].name' results.json # Check if any tests are flaky $ jq -e '.analysis.flakyTests | length > 0' results.json