An MCP server, command line utility, and library for Ruby SimpleCov test coverage analysis.
Hand one prompt to your AI coding agent and get a written report of where your tests fall short and why it matters.
The Test Coverage Analysis prompt has the agent use cov-loupe to:
- Map your code into logical areas, from whole subsystems down to a single critical class or method inside a larger file, rather than reporting by file or directory
- Measure coverage for each area from cov-loupe's line-level data, with totals that reconcile to the project's
- Rank the gaps by risk and difficulty, with a concrete failure example for each and a check for dead code
- Review test quality: unit vs. integration balance, weak assertions, testing anti-patterns, and the well-tested areas worth copying
- Recommend next steps in priority order, each with a ready-to-use prompt for an agent to implement it
To run it:
-
Install cov-loupe (
gem install cov-loupe). Setting up the MCP server is optional; without it, the agent uses the CLI. -
Run your full test suite and make sure it passes. The prompt does not run tests; it checks that the coverage data is current and stops if it isn't.
-
From your project root, give the prompt to your agent. The gem includes the prompt matching its version:
PROMPT="$(dirname "$(cov-loupe -p docs-local)")/docs/user/prompts/test-coverage-analysis-prompt.md" # Interactive: tell the agent to follow the prompt in "$PROMPT", or paste its contents. # Headless: claude -p "$(cat "$PROMPT")"
The agent writes a timestamped Markdown report to untracked/ if your project root has that directory (useful if you gitignore it), otherwise to the project root. It runs unattended and changes nothing else, so you can run several agents (Claude, Codex, Gemini, ...) at once against the same coverage data and compare their reports.
cov-loupe makes SimpleCov coverage data queryable and actionable through three interfaces:
- CLI - command-line execution of single reports or queries
- MCP server - stdio (local, no network) server assists AI analysis of your coverage
- Ruby library - Programmatic API for custom tooling
Reads SimpleCov's coverage.json, the documented JSON formatter output that SimpleCov 1.0.0 and later write alongside the HTML reportβno runtime dependency on your test suite.
- β Multiple interfaces - CLI, MCP server, and Ruby API
- β
Annotated source code -
-s full|uncovered|none/--source full|uncovered|none(insummary,uncovered, anddetailed), with-n N/--context-lines Nsetting the context lines around uncovered code with-s uncovered - β Staleness detection - Identify outdated coverage (deleted, newer, line count mismatched, or unreadable files)
- β
Multi-suite aware - Reads SimpleCov's already-merged
coverage.json, so RSpec + Cucumber (etc.) appear as one coverage map - β Flexible path resolution - Works with absolute or relative paths
- β Comprehensive error handling - Context-aware messages for each mode
- Get a full, risk-ranked analysis of your test suite with the Test Coverage Analysis prompt
- Query coverage data from AI assistants, e.g.:
- "Using the cov-loupe MCP server, analyze test coverage data and write a report to a markdown file containing a free text analysis of each issue and then two tables, one sorted in descending order of urgency, the other in ascending order of level of effort."
- "Using the cov-loupe MCP server, generate a table of directories and their average coverage rates, in ascending order of coverage."
- For prompts that explain what your tests miss and why it matters, see AI Assistant Prompts.
- Find files with the lowest coverage
- Investigate specific files or directories
- Generate CI/CD coverage reports
- Create custom pass/fail predicates for scripts and CI - use the library API or CLI JSON output to implement arbitrarily complex coverage rules beyond simple thresholds (e.g., require higher coverage for critical paths, exempt test utilities, track coverage trends)
gem install cov-loupe
# Or, for the most current version you may need to specify prerelease:
gem install --pre cov-loupeIf you are upgrading from a previous version, please refer to the Migration Guides.
If your project doesn't use SimpleCov yet, add it to your Gemfile and install it:
bundle add simplecov --group test --require falseThen start it at the very top of spec/spec_helper.rb (or test/test_helper.rb), before your application code loads:
require 'simplecov'
SimpleCov.startThen run your test suite:
# Generate your SimpleCov test coverage data with your test suite run command, e.g.:
bundle exec rspec
# Verify coverage was generated
ls -l coverage/coverage.jsonThis needs SimpleCov 1.0 or later; a coverage.json from 0.x is rejected (see Quick Start).
CLI - View Coverage Table: This is the default command, so any of the following will work:
cov-loupe
cov-loupe l
cov-loupe listCLI - Check Specific File:
cov-loupe summary lib/my_app/order.rb
# or use abbreviations: s (summary), u (uncovered)
cov-loupe s lib/my_app/order.rb
cov-loupe u lib/my_app/cli.rbCLI - Find Project Resources:
The repo URL, documentation site URL, and path to the installed README are output in the header of the online help, e.g. (excerpt):
Repository: https://github.com/keithrbennett/cov-loupe
Documentation (Web): https://keithrbennett.github.io/cov-loupe/
Documentation (Local): /path/to/gems/cov-loupe-VERSION/README.md
Screencast: https://www.bbs-software.com/screencasts/cov-loupe
The -p/--path-for option prints the repository and documentation paths individually:
cov-loupe -p repo
cov-loupe -p docs
cov-loupe -p docs-local
You can use your operating system's application open command (usually open for Mac, xdg-open on Linux, and start on Windows) to assemble this into a single command:
open `cov-loupe -p docs`
Ruby Library:
require "cov_loupe"
model = CovLoupe::CoverageModel.new
list_result = model.list
# => { "schema_version" => 1, "files" => [...], ... }
files = list_result["files"]
# => [{ "file" => "lib/my_app/order.rb", "covered" => 114, "total" => 118, "percentage" => 96.61, "stale" => "ok" }, ...]
summary = model.summary_for("lib/my_app/order.rb")
# => { "schema_version" => 1, "file" => "lib/my_app/order.rb", "summary" => { "covered" => 114, "total" => 118, "percentage" => 96.61 } }Library payloads report file paths relative to the project root, like the CLI and MCP output; files outside the root keep absolute paths. See Library API for the payload compatibility rules.
Only the public API defined under Public API and Versioning, including Ruby classes and methods tagged @api public, follows Semantic Versioning; other classes and methods in the gem are internal and may change in any release.
MCP Server: See MCP Integration Guide for AI assistant setup.
Important for MCP users: An MCP server's stdout must carry only protocol messages, from startup until it exits, so project_validate predicates must not print to it. If cov-loupe -m mcp prints text such as Resolving dependencies... before responding, see Troubleshooting and MCP Integration for wrapper and RubyGems launcher guidance.
SimpleCov merges the results of the suites that ran (RSpec + Cucumber, etc.) before writing coverage.json, dropping results older than its merge timeout (10 minutes by default), so cov-loupe sees one combined coverage map and does no merging of its own. coverage.json has one timestamp for the merged result, so if only some suites were re-run after a change, staleness may be under-reported. To combine coverage from separate CI jobs, keep each job's coverage/.resultset.json and merge them with SimpleCov.collate (for example, SimpleCov.collate Dir['coverage-*/.resultset.json']), which ignores the merge timeout by default and writes a combined coverage.json through the configured formatters, as a test run does; SimpleCov.collate reads .resultset.json files, not coverage.json.
Full documentation is available at https://keithrbennett.github.io/cov-loupe/.
User Guides:
- Quick Start - Get up and running in 3 steps
- User Docs Overview - Map of all end-user guides
- Installation - Setup for different environments
- Installing a Prerelease - Trying an unreleased version
- CLI Usage - Command-line reference
- Examples - AI assistant prompts, CLI and Ruby recipes, CI/CD integration
- Advanced Usage - Staleness detection, error modes, path resolution
- Library API - Ruby API documentation
- Error Handling - Error modes and exceptions
- Logging - Log targets, initialization probes, and file creation
- MCP Integration - AI assistant configuration
- Troubleshooting - Common issues
Special Topics & Prompts:
- CLI Fallback for LLMs - When MCP isn't available
- Test Coverage Analysis Prompt - Full, risk-ranked analysis of your test suite by logical area
- Sample MCP Prompts - Ready-to-use ChatGPT/Claude/Gemini prompts
- Migration Guides
Developer Docs:
- Developer Docs Overview - Entry point for contributors
- Architecture - Design and internals
- Development Guide - Local dev workflow
- Documentation Server - Local docs server and publishing
- Releasing - Release checklist
- Future Enhancements - Planned improvements
- Architecture Decision Records - Design history
Project Docs & Examples:
- Ruby >= 3.3 (the oldest Ruby that has not reached end of life)
mcpgem >= 0.15 and < 2.0- A
coverage.jsonwritten by SimpleCov 1.x (SimpleCov itself is not a cov-loupe dependency)
gem install installs mcp and the other runtime dependencies (amazing_print and logger) automatically.
Applications pinned to an mcp version older than 0.15 must upgrade it (required since cov-loupe v6), and projects on SimpleCov 0.x must upgrade SimpleCov to produce the coverage.json cov-loupe v7 reads. See Migrating to v7.
The test suite passes on JRuby, and to the best of our knowledge the project is JRuby-compatible, except that non-ASCII paths under LANG=C are unsupported because the JVM cannot open them in that locale.
If you encounter any JRuby-specific issues, please open a GitHub issue, including as much detail as possible.
cov-loupe reads coverage.json, the output of SimpleCov's JSON formatter. It is described by a versioned JSON schema in the SimpleCov repository, and from SimpleCov 1.0.0 on the default HTML formatter writes it alongside its report, so most projects have one after every test run.
SimpleCov's .resultset.json is not read. It is SimpleCov's internal merge cache with no compatibility promises. cov-loupe 6.x and earlier read only that file; 7.0 replaced it with coverage.json.
Discovery. With no --coverage-file argument, coverage/coverage.json under the project root is used. That is where SimpleCov writes it by default; for any other location, pass --coverage-file (-c).
When --coverage-file names a directory, coverage.json inside it is used. When it names a file, that file is used as given. A relative path is tried against both the current directory and the project root; if both resolve to different valid coverage locations, it is an ambiguity error, so use an absolute path.
For non-standard locations:
# Command-line option (highest priority) - use -c or --coverage-file
cov-loupe -c /path/to/your/coverage
# Environment variable (project-wide default)
export COV_LOUPE_OPTS="-c /path/to/your/coverage"
# MCP server configuration
# Add to your MCP client config (used as defaults for MCP tools):
# "args": ["-m", "mcp", "-c", "/path/to/your/coverage"]MCP precedence: For MCP tool calls, per-request JSON parameters win over the CLI args used to start the server (including COV_LOUPE_OPTS). Presentation flags such as -f and -o don't apply to MCP, though -O sets the default output_chars; see the option table. If neither is provided, built-in defaults are used (root: '.', raise_on_stale: false, etc.). Coverage data is cached globally and automatically reloaded when the coverage file changes.
See CLI Usage Guide for complete details.
CLI Subcommands: list (l), summary (s), uncovered (u), detailed (d), raw (r), totals (t), validate (v)
MCP Tools: file_coverage_summary, file_coverage_detailed, file_coverage_raw, file_uncovered_lines, project_coverage, project_coverage_totals, project_validate (only when the server is started with --allow-code-predicates), help, version
π See also:
- CLI Usage Guide - Complete command-line reference
- MCP Integration Guide - MCP tools documentation
- "command not found" - See Installation Guide
- "cannot load such file -- mcp" - The
mcpgem is not installed for the Ruby you are running. Reinstall cov-loupe (gem install cov-loupe) or runbundle install. - "Could not find coverage.json" - Ensure SimpleCov is configured in your test suite, then run tests to generate coverage. See the Configuring the Coverage File section for more details.
- MCP server won't connect - Check PATH and Ruby version in MCP Troubleshooting
- RVM in sandboxed environments (macOS) - RVM requires
/bin/pswhich may be blocked by sandbox restrictions. Use rbenv or chruby instead.
For more detailed help, see the full Troubleshooting Guide.
# Clone and setup
git clone https://github.com/keithrbennett/cov-loupe.git
cd cov-loupe
bundle install
# Run tests
bundle exec rspec
# Test locally
bundle exec exe/cov-loupe
# Build and install
gem build cov-loupe.gemspec
gem install cov-loupe-*.gemSee docs/dev/DEVELOPMENT.md for more.
cov-loupe does not depend on the simplecov gem and never loads it. It reads coverage.json written by SimpleCov 1.x, which is already merged across suites. On load it checks the file's meta.schema_version (SimpleCov's output format version, e.g. "1.0") and rejects a missing value or a major version other than 1 with an error naming the file and the value found. That includes coverage.json files written for SimpleCov 0.x by the separate simplecov_json_formatter gem, which carry no schema_version.
Contributions are welcome! Please open an issue first and wait for explicit approval before submitting a pull request. Then:
- Fork the repository and create a feature branch
- Add tests for new functionality
- Ensure RuboCop and the tests pass (
bundle exec rubocopandbundle exec rspec) - Submit a pull request
See the Contributing Guide for details.
MIT License - see LICENSE file for details.
- GitHub: https://github.com/keithrbennett/cov-loupe
- RubyGems: https://rubygems.org/gems/cov-loupe
- Issues: https://github.com/keithrbennett/cov-loupe/issues
- Changelog: RELEASE_NOTES.md
π¦ Install: gem install cov-loupe
π Read: CLI Usage Guide | MCP Integration
π Report issues: GitHub Issues
β Star the repo if you find it useful!
