ReportGenerator: turning coverlet, OpenCover and JaCoCo output into readable coverage reports
ReportGenerator converts coverage reports generated by coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov into human readable reports in various formats.
At a glance
- What is it?
- ReportGenerator is a command line tool that parses coverage files from coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov and lcov, merges them, and emits HTML, Markdown, Cobertura, badges and more. It is for .NET teams that already produce coverage data and have nowhere readable to put it.
- Who is it for?
- Adopt ReportGenerator if you already emit coverage files from coverlet, OpenCover, JaCoCo, gcov or lcov and need one merged, browsable report per build. Do not adopt it as a coverage collector: it parses files it is given and does not instrument or run your tests.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 17 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap between a coverage file and a coverage report
Coverage collection in .NET is a solved problem. coverlet, OpenCover, dotCover and the Visual Studio collector all produce machine-readable files. What they do not produce is something a reviewer will open. A Cobertura XML file tells a CI job whether a threshold passed; it does not tell a developer which branch of a switch statement nobody has ever executed.
ReportGenerator exists for that second job. The README describes it as converting coverage reports generated by coverlet, OpenCover, dotCover, Visual Studio, NCover, Cobertura, JaCoCo, Clover, gcov or lcov into human readable reports in various formats. The format list is the interesting part: the input side spans .NET collectors, Java tooling (JaCoCo), and C/C++ tooling (gcov, lcov). That makes it usable in a polyglot repository where one pipeline produces several coverage artifacts and someone has to reconcile them.
The audience is narrower than the input list suggests. This is a tool for people who own a build pipeline. If you never run coverage in CI, ReportGenerator has nothing to read. It is a post-processing step, not a coverage system.
How ReportGenerator merges coverage files and writes reports
The mechanism is a parse, merge, render pipeline. The -reports parameter takes one or more coverage files separated by semicolons, and the README notes that globbing is supported, so a wildcard over a test results directory is a valid input. Multiple files are merged into a single report, which is how you combine results from several test projects or several frameworks into one number.
Rendering is driven by -reporttypes. The list in the README is long and split by purpose: Html and its variants (Html_Light, Html_Dark, Html_BlueRed, HtmlInline) for browsing, HtmlSummary and the Markdown summaries for pasting into a pull request or a build summary, Cobertura, Clover and OpenCover for feeding another tool, CsvSummary and JsonSummary for scripting, Badges for a README, and CodeClimate and Latex for their respective consumers.
The source visualisation is the part that justifies the HTML output. The README states that reports show coverage quotas and also visualize which lines of your source code have been covered. That requires source, which is why -sourcedirs exists: it points the renderer at the directories holding the code so line-level highlighting can be produced. Without it you get numbers without the code view.
Filtering is handled by assemblyfilters, classfilters and filefilters, each accepting + or - prefixed values. This is the knob that keeps generated code, migrations or test assemblies out of the denominator. Two additional filter parameters, riskhotspotassemblyfilters and riskhotspotclassfilters, apply only to the risk hotspot analysis rather than to the report contents.
History is a separate concern. -historydir points at a directory where past runs are accumulated, which is what enables trend output over time. The directory has to persist between builds; on an ephemeral CI agent it will not, unless you cache or commit it.
Installing ReportGenerator as a dotnet tool and generating a first report
The README offers several packages. For a .NET Core project the intended path is the global tool, dotnet-reportgenerator-globaltool, which requires .NET Core 8.0 or later and installs a reportgenerator command.
dotnet tool install -g dotnet-reportgenerator-globaltoolAfter installation the command is available on the path. The README also documents a local variant for repositories that prefer pinned, per-checkout tooling:
dotnet new tool-manifest
dotnet tool install dotnet-reportgenerator-globaltoolWith a manifest in place the tool is invoked through dotnet rather than directly, so the version is recorded in the manifest file and restored with the repository. The README gives the invocation as dotnet reportgenerator [options].
The README documents the command line parameters rather than a worked example, so a first run means supplying -reports, -targetdir and -reporttypes yourself, with -sourcedirs added when you want the annotated source view instead of a table of percentages. The parameter list in the README is the source for each of those names.
The reader should end up with a target directory containing an HTML entry page that can be opened directly from disk. If the command is not found after a global install, the usual cause is that the .NET tools directory is not on PATH; the README's alternative is the --tool-path form, which places the executable in a directory you choose:
dotnet tool install dotnet-reportgenerator-globaltool --tool-path toolsInvoked that way the binary is tools\reportgenerator.exe on Windows, per the README's usage line.
Where ReportGenerator is the wrong tool
The most common mismatch is expecting it to measure coverage. It does not instrument assemblies or execute tests. If your project produces no coverage file, ReportGenerator's input list is empty and the tool has nothing to do. Every complaint about a missing or zero report traces back to the collector, not to this renderer.
The second mismatch is language. Despite the JaCoCo, Clover, gcov and lcov inputs, the tool itself is .NET. The README states it works with full .NET Framework and .NET Core, and the global tool requires .NET Core 8.0 or later. A Java or C++ team that wants a coverage report has to install and run a .NET runtime to get one. That is a real cost in a container image that otherwise carries only a JDK or a compiler toolchain, and it is the point at which a language-native reporter is the better choice.
The third is the source view. Line-level highlighting needs -sourcedirs pointing at the actual source. In a pipeline where only compiled artifacts are published to the reporting stage, the HTML report will render coverage numbers without the annotated code, which removes the main reason to prefer HTML over a summary format.
Finally, the README points to a PRO license and sponsor tier with access to additional features. The free command line and the licensed feature set are not the same thing, and the README does not enumerate the boundary. Teams should establish which features they depend on before standardising on the tool.
ReportGenerator compared with a language-native coverage reporter
The closest alternative in the .NET world is the built-in reporting of the collector you already use. coverlet emits Cobertura and other formats directly, and dotnet test can be configured to produce them without an extra tool. The difference in approach is that the collector's own output is a single file per run with no rendering stage. You get XML, and whatever consumes it is your problem.
ReportGenerator inserts a merge and render step between collection and consumption. That step buys three things the collector does not provide: merging several files into one report, line-level source visualisation in HTML, and a set of output formats (Markdown summaries, badges, CodeClimate, Latex) aimed at different consumers rather than at a build threshold.
For a single test project on a single framework, that step may not be worth the extra dependency. The collector's Cobertura output plus a CI coverage gate covers the same ground. The trade-off flips as soon as you have more than one coverage file, more than one language, or a reviewer who needs to see which lines are uncovered rather than which percentage was reached.
Maintenance, licensing and the cost of upgrading
The repository is not archived, and the last push was on 2026-09-13. Releases are frequent: v5.5.11 on 2026-07-27, v5.5.10 on 2026-05-10 and v5.5.9 on 2026-05-02. That cadence matters because coverage file formats drift, and a parser that stops tracking a collector's output becomes useless quickly.
Upgrade cost is low for command line users. The global tool is versioned by NuGet, and a tool manifest pins the version in the repository, so a bump is a manifest edit plus a restore. The larger upgrade risk sits with the core package: ReportGenerator.Core targets .NET Standard 2.0 and is the entry point for plugins and for calling the tool from code. Anyone who writes a custom report or a custom history storage plugin is tied to that package's API surface, and the README links the plugin documentation to the project wiki rather than to the README itself, so the contract is only as stable as the wiki says.
On licensing, the project is under the Apache License, Version 2.0, and the README links the license file in the repository. Apache-2.0 permits commercial use and modification, but the README also describes a separate PRO license and a GitHub sponsor tier with exclusive access to additional features, so the free and paid surfaces coexist in one product. Whether a given deployment needs the paid tier depends on features the README does not list; that question belongs with whoever owns the build pipeline, not with this article.
Editorial conclusion
Adopt ReportGenerator if you already emit coverage files from coverlet, OpenCover, JaCoCo, gcov or lcov and need one merged, browsable report per build. Do not adopt it as a coverage collector: it parses files it is given and does not instrument or run your tests. Before wiring it into a pipeline, verify which report types your build server can consume, whether your NuGet feed serves ReportGenerator.Core if you plan a plugin, and whether the free command line covers your needs or the PRO-licensed features do.
Frequently asked questions
How do I install ReportGenerator for a .NET project?
Install the dotnet-reportgenerator-globaltool package with dotnet tool install -g dotnet-reportgenerator-globaltool, which requires .NET Core 8.0 or later and provides the reportgenerator command. The README also documents a local install using a tool manifest and a --tool-path install into a chosen directory.
How do I install dotnet-reportgenerator-globaltool?
Run dotnet tool install -g dotnet-reportgenerator-globaltool for a global install, or dotnet new tool-manifest followed by dotnet tool install dotnet-reportgenerator-globaltool to pin it per repository. The README lists .NET Core 8.0 or later as the requirement for this package.
Why is reportgenerator not recognized as a command?
A global tool installs its executable into the .NET tools directory, which must be on PATH for the bare reportgenerator command to resolve. The README's alternative is dotnet tool install dotnet-reportgenerator-globaltool --tool-path tools, after which the executable lives in the tools directory and is invoked from there.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/danielpalme-reportgenerator)