fucini-coverage
v2.2026.4
Published
Fucini Coverage Studio on the command line: the same reader as the VS Code and Visual Studio editions, for CI gates, exports, reports, badges, baseline compares and an MCP server for AI agents. Free.
Maintainers
Readme
fucini-coverage
Fucini Coverage Studio on the command line. The same reader as the VS Code and Visual Studio editions — the same report gives the same numbers, to the digit — for the places an editor is not: a CI gate, a pull-request check, a badge in the README, an HTML report on a build server, and an MCP server an AI agent can ask what ran and what never did.
Free. Windows, Linux, WSL and macOS, Node 20 or newer.

npm install -g fucini-coverage # or: npx fucini-coverage <command>
fucini-coverage summary coverage/lcov.infoLines 83.89% 99/118
Branches 71.73%
Functions 86.66%
MC/DC 45.45%
File Lines
src/buffer.c 73.91% 17/23
src/calc.c 77.27% 17/22
src/sensor.c 78.94% 30/38What it reads
Any report the editors read, recognised by what is in it rather than by its
name: LCOV, llvm-cov JSON, gcov and gcovr (JSON and text, with gcc 14's
condition coverage), Cobertura, JaCoCo, Istanbul and nyc, Coverlet and
OpenCover, dotnet-coverage, coverage.py, Go cover profiles, SimpleCov, Clover,
Coveralls, SonarQube generic, GNATcoverage, BullseyeCoverage, Visual Studio
.coveragexml, Xcode xccov, VectorCAST, Testwell CTC++, Lauterbach TRACE32,
EMMA, UCIS, NCover, dotCover, and the mutation reports of Stryker and PIT.
fucini-coverage formats lists them. A .gz is unpacked first.
Several reports are merged into one run as the editors merge them: a newer report of a file replaces an older one, a report written per test adds its tests to the lines, a mutation report adds its mutants beside the coverage.
A report's relative paths are rooted where that report was written — its own
folder, then the folders above it, up to the one the command runs in. So an
llvm-cov report of full paths and a gcovr report written in a build folder
several levels down meet as one set of files, without a pathRemap rule for
each build directory.
Commands
| Command | What it does |
| --- | --- |
| summary | The run in numbers: the totals, then one line per file. --markdown for a pull request, --json for a script. |
| check | The gate: exit 1 when the run is below a threshold — lines, branches, functions, MC/DC, conditions, regions, mutation, the weighted score, or the lines changed against a git ref. |
| export | The run in another format: CSV per file or per function, Markdown, LCOV, Cobertura, SARIF, the exclusions list, a badge, Fucini's JSON. |
| report | The HTML report: an index per folder, a page per file with every line in its colour, the riskiest methods, the surviving mutants. |
| badge | The coverage badge as SVG, coloured by the settings' scale. |
| compare | This run against a baseline: the files that moved, regressions first; --fail-on-regression for a pull-request check. |
| mcp | An MCP server over the run for an AI agent: the gaps of a function, the tests that ran a line, what moved. |
| formats | The formats the reader knows. |
| help | fucini-coverage help <command> — every command documents itself. |
Reports are named as files, folders (every file in them) or patterns
(coverage/**/lcov.info). With none named, the settings file's
fuciniCoverage.coverageFile.paths is read.
check — the gate
fucini-coverage check coverage/lcov.info --lines 80 --branches 70
fucini-coverage check --new-code 80 --base-ref origin/main # the lines this branch changed
fucini-coverage check --require-reasons # every exclusion marker says whyFAIL 1 of 2 gate(s):
✗ Statement 75.00% < 80%The thresholds come from the settings (fuciniCoverage.threshold.*, the
keys the editors judge by) and each can be set on the command line. The
new-code gate runs git diff <ref> -- . itself, in the folder the command
runs in, and judges the changed lines the run can measure.
Exit codes: 0 every gate passed, 1 a gate failed or coverage regressed, 2 the command line was wrong, 3 nothing could be read or written. A pipeline stops on anything but 0.
export, report, badge
fucini-coverage export --format lcov coverage/*.xml --out merged.info # two Cobertura files as one LCOV
fucini-coverage export --format markdown --stdout >> "$GITHUB_STEP_SUMMARY"
fucini-coverage report --out coverage-report # then open index.html
fucini-coverage badge --metric branches --out docs/coverage.svgcompare — against the last green run
fucini-coverage compare --baseline main.lcov.info coverage/lcov.info --fail-on-regressionbaseline → this run: 83.89% → 81.20% (-2.69%), 2 file(s) moved
src/sensor.c 78.94% → 60.52% -18.42%
src/calc.c 77.27% → 81.81% +4.54%mcp — for an AI agent
fucini-coverage mcp coverage/lcov.infoServes the Model Context Protocol on 127.0.0.1 with the six tools the
editors offer an agent and prints the entry for the client's mcp.json
(Claude Code, Copilot, Cursor and the rest take it) with the token the
client must send. The token is made up at each start, or given with
--token; keep it out of the repository.
The settings file
fucini-coverage.json beside the code — the file the Visual Studio edition
reads — with the same fuciniCoverage.* keys as the VS Code settings, so a
team configures its thresholds once and every edition judges by them.
.vscode/settings.json is read as well, with fucini-coverage.json over it;
--config <file> names another. Comments are allowed.
{
"fuciniCoverage.coverageFile.defaultLocation": "${workspaceFolder}/coverage",
"fuciniCoverage.coverageFile.paths": ["lcov.info", "per-test/**/coverage.cobertura.xml"],
"fuciniCoverage.pathRemap": [{ "from": "/work/app", "to": "${workspaceFolder}" }],
"fuciniCoverage.ignore": ["**/*.generated.cs"],
"fuciniCoverage.threshold.statement": 80,
"fuciniCoverage.threshold.branch": 70,
"fuciniCoverage.threshold.newCode": 80,
"fuciniCoverage.gitDiff.baseRef": "origin/main"
}What is read: coverageFile.*, pathRemap, ignore, threshold.* with
compliance.thresholdProfile, excluded.includeInTotals,
exclusions.requireReason, gitDiff.baseRef, baseline.report,
badge.metric, colorScale.*, whmWeights.* and mcp.port.
In a pipeline
GitHub Actions:
- run: npx fucini-coverage check coverage/lcov.info --lines 80 --new-code 80 --base-ref origin/${{ github.base_ref || 'main' }}
- run: npx fucini-coverage export --format markdown --stdout coverage/lcov.info >> "$GITHUB_STEP_SUMMARY"GitLab CI:
coverage:
script:
- npx fucini-coverage check coverage/cobertura.xml --lines 80
- npx fucini-coverage badge coverage/cobertura.xml --out public/coverage.svgAzure Pipelines:
- script: npx fucini-coverage check $(Build.SourcesDirectory)/coverage/lcov.info --branches 70
displayName: Coverage gateThe flags for every command: --config <file>, --cwd <folder>,
--include-excluded, --json, --quiet, --no-color (NO_COLOR in the
environment does the same).
Windows, Linux, WSL
One package, one behaviour. Paths may be written either way (coverage\x.info
or coverage/x.info), patterns use forward slashes, a report's own paths are
mapped onto the checkout by pathRemap whatever machine wrote it, and colour
appears only on a terminal. Under WSL the same npx fucini-coverage runs on
a repository on /mnt/c as on ~.
Privacy
The first command run on a machine sends one anonymous message, so installs can be counted: a random install id, the version and the operating system (platform, release, architecture). Nothing about the code, the reports, the folder or you; the server takes the country from the address the message comes from, as it does for the editions. It is sent once — never again after — and never in CI, where every run is a fresh machine.
Any of these turns it off:
export FUCINI_COVERAGE_TELEMETRY=off # or DO_NOT_TRACK=1{ "fuciniCoverage.telemetry.enabled": false } // in fucini-coverage.jsonThe install id is kept in %APPDATA%\Fucini\CoverageStudio\cli-install.json
on Windows and ~/.config/fucini-coverage/install.json elsewhere. The
privacy policy says
the rest.
The editors
The gate, the exports and the report are what the editors do without a window; the editors add what needs one — the gutters, the hovers, the lenses, the Coverage view, which tests ran a line, a run from a save. Both are at fucini.software/coverage-studio.
Licence
Free of charge, under the Fucini Coverage Studio licence. Copyright © 2026 Fucini Consulting (LLC Fucini Consulting, Reg. No. 46062728, Ukraine) — https://www.fucini.consulting
