Skip to content
keithrbennettPublic

About

Refines Ruby Simplecov test coverage data as CLI, MCP server, and library

Resources

Code of conduct

Contributing

Stars

48 stars

Watchers

5 watching

Forks

Latest commit

Β 

History

1,205 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

CovLoupe

CovLoupe logo

An MCP server, command line utility, and library for Ruby SimpleCov test coverage analysis.

Documentation Website

Gem Version Documentation

⭐ AI 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:

  1. Install cov-loupe (gem install cov-loupe). Setting up the MCP server is optional; without it, the agent uses the CLI.

  2. 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.

  3. 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.

What is cov-loupe?

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.

Key Features

  • βœ… Multiple interfaces - CLI, MCP server, and Ruby API
  • βœ… Annotated source code - -s full|uncovered|none / --source full|uncovered|none (in summary, uncovered, and detailed), with -n N / --context-lines N setting 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

Practical Use Cases

  • 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)

Quick Start

Installation

gem install cov-loupe

# Or, for the most current version you may need to specify prerelease:
gem install --pre cov-loupe

Upgrading

If you are upgrading from a previous version, please refer to the Migration Guides.

Generate Coverage Data

If your project doesn't use SimpleCov yet, add it to your Gemfile and install it:

bundle add simplecov --group test --require false

Then start it at the very top of spec/spec_helper.rb (or test/test_helper.rb), before your application code loads:

require 'simplecov'
SimpleCov.start

Then 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.json

This needs SimpleCov 1.0 or later; a coverage.json from 0.x is rejected (see Quick Start).

Basic Usage

CLI - View Coverage Table: This is the default command, so any of the following will work:

cov-loupe
cov-loupe l
cov-loupe list

CLI - 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.rb

CLI - 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.

Multi-Suite Coverage

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.

Documentation Index

Full documentation is available at https://keithrbennett.github.io/cov-loupe/.

User Guides:

Special Topics & Prompts:

Developer Docs:

Project Docs & Examples:

Requirements

  • Ruby >= 3.3 (the oldest Ruby that has not reached end of life)
  • mcp gem >= 0.15 and < 2.0
  • A coverage.json written 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.

JRuby Compatibility

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.

Configuring the Coverage File

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.

Commands and Tools

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:

Troubleshooting

  • "command not found" - See Installation Guide
  • "cannot load such file -- mcp" - The mcp gem is not installed for the Ruby you are running. Reinstall cov-loupe (gem install cov-loupe) or run bundle 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/ps which may be blocked by sandbox restrictions. Use rbenv or chruby instead.

For more detailed help, see the full Troubleshooting Guide.

Development

# 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-*.gem

See docs/dev/DEVELOPMENT.md for more.

SimpleCov Compatibility

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.

Contributing

Contributions are welcome! Please open an issue first and wait for explicit approval before submitting a pull request. Then:

  1. Fork the repository and create a feature branch
  2. Add tests for new functionality
  3. Ensure RuboCop and the tests pass (bundle exec rubocop and bundle exec rspec)
  4. Submit a pull request

See the Contributing Guide for details.

License

MIT License - see LICENSE file for details.

Links


Next Steps

πŸ“¦ Install: gem install cov-loupe

πŸ“– Read: CLI Usage Guide | MCP Integration

πŸ› Report issues: GitHub Issues

⭐ Star the repo if you find it useful!

About

Refines Ruby Simplecov test coverage data as CLI, MCP server, and library

Resources

Code of conduct

Contributing

Stars

48 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages