Coverage Priority Analyzer — Parses lcov.info and ranks files by testing priority. Helps answer: "Where should I focus testing efforts next?"
Brennpunkt is a command-line tool that analyzes test coverage reports and tells you where to focus your testing efforts for maximum impact. Instead of showing you raw percentages, it calculates a priority score for each file based on coverage gaps, file size, and configurable weights.
Think of it as a coverage report that actually tells you what to do next.
When you run tests with coverage enabled, your test framework generates a coverage report. This report is typically stored in a format called LCOV (originally from the Linux Test Project). Brennpunkt reads this LCOV data and transforms it into actionable priorities.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Your Tests │ ──▶ │ Coverage Tool │ ──▶ │ lcov.info │
│ (Jest, etc.) │ │ (v8, istanbul) │ │ (raw data) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Prioritized │ ◀── │ Brennpunkt │ ◀── │ Parses LCOV │
│ Action List │ │ (this tool) │ │ Calculates │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Most JavaScript/TypeScript test frameworks can generate LCOV coverage data:
| Test Framework | Coverage Provider | Command |
|---|---|---|
| Vitest | v8 (built-in) | vitest run --coverage |
| Jest | istanbul/v8 | jest --coverage |
| Mocha | c8 / nyc | c8 mocha or nyc mocha |
| Node.js | c8 | c8 node script.js |
| Karma | karma-coverage | Configure in karma.conf.js |
| AVA | c8 | c8 ava |
| Playwright | v8 | npx playwright test --coverage |
The output is typically a file called lcov.info in a coverage/ directory.
Brennpunkt works with any tool that produces LCOV format output:
- ✅ Vitest (recommended for new projects)
- ✅ Jest (most popular)
- ✅ c8 (native V8 coverage)
- ✅ NYC/Istanbul (legacy but widely used)
- ✅ Karma (Angular projects)
- ✅ Any CI system that archives coverage artifacts
- You have tests — Brennpunkt analyzes coverage, it doesn't run tests
- You have LCOV output — Run your tests with
--coveragefirst - You want to improve coverage — This tool helps prioritize, not measure
You're staring at a failed CI build: "Coverage threshold not met: 85.2% < 90%"
Now what? You open the coverage report and see a wall of percentages. File after file, each showing line coverage, branch coverage, function coverage. Some files are at 45%, others at 98%. The "Uncovered Lines" column shows cryptic ranges like 23-27, 45, 89-102.
The problem: You need to close a 5% coverage gap, but the standard coverage report doesn't tell you where to focus. You're left doing mental math:
- Which files have the most uncovered lines?
- Which gaps are in critical code vs. tiny utilities?
- Should you prioritize that file with 50% line coverage or the one with 0% branch coverage?
Traditional coverage tools show you what isn't covered. They don't tell you what matters most.
Brennpunkt was built to solve this. Instead of presenting raw percentages, it calculates a priority score that weighs coverage gaps against file importance. Run one command and immediately see which files will have the biggest impact on your coverage goals.
It was also designed with agentic coding tools in mind. When an AI assistant needs to improve test coverage, it shouldn't wade through percentage tables—it needs a ranked list of where to focus. Brennpunkt's JSON output integrates directly into automated workflows, giving coding agents clear, actionable targets.
npm install -g @redaksjon/brennpunktOr use directly with npx:
npx @redaksjon/brennpunkt# Analyze coverage (auto-discovers lcov.info location)
brennpunkt
# Specify a custom coverage file path
brennpunkt path/to/lcov.info
# Show only top 10 priority files
brennpunkt --top 10
# Output as JSON for tooling integration
brennpunkt --json
# Custom weights for branches, functions, lines
brennpunkt --weights 0.6,0.2,0.2
# Exclude files with fewer than 50 lines
brennpunkt --min-lines 50When no coverage file is specified, brennpunkt automatically searches common locations:
| Search Order | Location | Test Framework |
|---|---|---|
| 1 | coverage/lcov.info |
Jest, Vitest, c8 (most common) |
| 2 | .coverage/lcov.info |
Some configurations |
| 3 | coverage/lcov/lcov.info |
Karma |
| 4 | lcov.info |
Project root |
| 5 | .nyc_output/lcov.info |
NYC legacy |
| 6 | test-results/lcov.info |
Some CI configurations |
The first file found is used. When a file is auto-discovered, brennpunkt shows which file was selected:
Using coverage file: coverage/lcov.info
📊 Coverage Priority Report
...
To skip discovery and use a specific file:
brennpunkt path/to/your/lcov.info| Option | Description | Default |
|---|---|---|
[coverage-path] |
Path to lcov.info file | Auto-discovered |
-w, --weights <B,F,L> |
Custom weights for branches, functions, lines | 0.5,0.3,0.2 |
-m, --min-lines <N> |
Exclude files with fewer than N lines | 10 |
-j, --json |
Output as JSON | false |
-t, --top <N> |
Show only top N priority files | (all) |
-c, --config <path> |
Path to configuration file | brennpunkt.yaml |
--init-config |
Generate a default configuration file | |
--check-config |
Display resolved configuration and exit | |
-V, --version |
Show version | |
-h, --help |
Show help |
Brennpunkt reads configuration from a brennpunkt.yaml file in your project directory. This follows the pattern of other development tools like ESLint, Prettier, and TypeScript.
Generate a default configuration file in your project:
brennpunkt --init-configThis creates a brennpunkt.yaml file with all available options commented out.
Create a brennpunkt.yaml file in your project root:
# Brennpunkt Configuration
# https://github.com/redaksjon/brennpunkt
# Path to lcov.info coverage file
coveragePath: coverage/lcov.info
# Priority weights for branches, functions, lines (should sum to 1.0)
# Higher branch weight = untested branches are prioritized more heavily
weights: "0.5,0.3,0.2"
# Minimum number of lines for a file to be included
# Helps filter out tiny utility files
minLines: 10
# Output format (true for JSON, false for table)
json: false
# Limit results to top N files (remove for all files)
top: 20| Option | Type | Description | Default |
|---|---|---|---|
coveragePath |
string | Path to the lcov.info file | coverage/lcov.info |
weights |
string | Comma-separated weights for branches,functions,lines | "0.5,0.3,0.2" |
minLines |
number | Exclude files with fewer than N lines | 10 |
json |
boolean | Output as JSON instead of table | false |
top |
number | Limit output to top N priority files | (all files) |
Configuration is resolved in this order (highest priority first):
- CLI arguments — Always override everything
- Config file —
brennpunkt.yamlin current directory - Built-in defaults — Fallback values
View the resolved configuration with source tracking:
brennpunkt --check-configOutput:
================================================================================
BRENNPUNKT CONFIGURATION
================================================================================
Config file: brennpunkt.yaml
Status: Found
RESOLVED CONFIGURATION:
--------------------------------------------------------------------------------
[config file] coveragePath : "coverage/lcov.info"
[config file] weights : "0.6,0.2,0.2"
[config file] minLines : 20
[default] json : false
[config file] top : 10
================================================================================
# Use a config file in a different location
brennpunkt --config .config/brennpunkt.yaml
# Generate config in a specific location
brennpunkt --init-config --config .config/brennpunkt.yamlFiles are ranked by a priority score that considers:
- Coverage gaps — The difference between 100% and actual coverage for branches, functions, and lines
- Weights — Customizable weights determine relative importance (default: branches 50%, functions 30%, lines 20%)
- File size — Larger files with low coverage rank higher (logarithmic scaling)
Formula:
priorityScore = (branchGap × branchWeight + functionGap × functionWeight + lineGap × lineWeight) × log10(lines + 1)
- Branches (50%) — Untested branches hide conditional bugs. A function might execute but still have untested error paths.
- Functions (30%) — Untested functions indicate dead code or missing feature tests.
- Lines (20%) — Basic execution coverage. High line coverage doesn't guarantee correctness.
# Prioritize branch coverage heavily
weights: "0.7,0.2,0.1"
# Equal weights for all metrics
weights: "0.33,0.33,0.34"
# Focus on function coverage
weights: "0.2,0.6,0.2"📊 Coverage Priority Report
┌─────────────────────────────────────────────────────────────────┐
│ OVERALL COVERAGE │
├─────────────────┬─────────────────┬─────────────────────────────┤
│ Lines: 78.50% │ Functions: 82.30% │ Branches: 65.20% │
│ (1234/1572) │ (156/190) │ (98/150) │
└─────────────────┴─────────────────┴─────────────────────────────┘
Files: 25 | Weights: B=0.5, F=0.3, L=0.2 | Min lines: 10
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Priority File Lines Funcs Branch Uncov Lines Score
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
#1 src/complex-module.ts 45.2% 50.0% 35.0% 120 156.3
#2 src/another-module.ts 62.5% 70.0% 55.0% 75 98.7
...
🎯 Recommended Focus (Top 3):
1. src/complex-module.ts
13 untested branches, 5 untested functions, 120 uncovered lines
2. src/another-module.ts
9 untested branches, 3 untested functions, 75 uncovered lines
{
"overall": {
"lines": { "found": 1572, "hit": 1234, "coverage": 78.5 },
"functions": { "found": 190, "hit": 156, "coverage": 82.3 },
"branches": { "found": 150, "hit": 98, "coverage": 65.2 },
"fileCount": 25
},
"files": [
{
"file": "src/complex-module.ts",
"lines": { "found": 218, "hit": 98, "coverage": 45.2 },
"functions": { "found": 10, "hit": 5, "coverage": 50 },
"branches": { "found": 20, "hit": 7, "coverage": 35 },
"priorityScore": 156.3,
"uncoveredLines": 120,
"uncoveredBranches": 13
}
]
}The simplest integration is adding brennpunkt to your package.json as a post-test script:
{
"scripts": {
"test": "vitest run --coverage",
"posttest": "brennpunkt --top 10"
}
}Now every time you run npm test, you'll automatically see prioritized coverage guidance:
$ npm test
✓ tests/auth.test.ts (15 tests)
✓ tests/api.test.ts (23 tests)
Coverage: 85.2%
Using coverage file: coverage/lcov.info
📊 Coverage Priority Report
...
🎯 Recommended Focus (Top 3):
1. src/auth/login.ts - 13 untested branchesAdd brennpunkt to your CI workflow to surface coverage priorities in pull requests:
name: Test & Coverage
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npm test -- --coverage
# Add coverage priority analysis
- name: Coverage Priority Analysis
run: npx @redaksjon/brennpunkt --top 10
# Optional: Save JSON report as artifact
- name: Generate Priority Report
run: npx @redaksjon/brennpunkt --json > coverage-priority.json
- uses: actions/upload-artifact@v4
with:
name: coverage-priority
path: coverage-priority.jsonFor any CI system, add brennpunkt after your test command:
# Run tests with coverage
npm test -- --coverage
# Analyze and display priorities
npx @redaksjon/brennpunkt --top 10
# Or save for later processing
npx @redaksjon/brennpunkt --json > coverage-priority.jsonUse brennpunkt with jq to fail builds when critical files have low coverage:
#!/bin/bash
# fail-on-priority.sh
# Get the top priority file's score
TOP_SCORE=$(brennpunkt --json --top 1 | jq '.files[0].priorityScore')
# Fail if priority score exceeds threshold
if (( $(echo "$TOP_SCORE > 100" | bc -l) )); then
echo "❌ High-priority coverage gap detected (score: $TOP_SCORE)"
echo "Run 'brennpunkt --top 5' to see recommended files to test"
exit 1
fi
echo "✅ Coverage priorities within acceptable range"Brennpunkt is designed to work with AI coding assistants. Instead of running tests repeatedly, AI tools can query existing coverage data for prioritized, actionable insights.
When you ask an AI to "improve test coverage," it typically runs tests, parses text output, and guesses priorities. This is slow (30s-5min per test run) and wasteful when coverage data already exists.
The simplest integration—include brennpunkt output in your prompts:
# In your prompt to Cursor/Claude/etc:
"I need to improve test coverage. Here's the priority analysis:
$(brennpunkt --json --top 3)
Write tests for the #1 priority file, focusing on untested branches."For deeper integration, Brennpunkt runs as an MCP (Model Context Protocol) server, allowing AI tools like Cursor and Claude to query coverage data directly.
Key features:
- Works with any test framework producing lcov format (Jest, Vitest, Mocha, c8, NYC, Karma, AVA, Playwright, etc.)
- One-time setup for all your projects—no per-project configuration
- Reads existing coverage data—does NOT run tests
- Respects project configuration—automatically loads
brennpunkt.yamlfrom each project - Sub-100ms responses—fast enough for interactive use
Available MCP Tools:
| Tool | Purpose |
|---|---|
brennpunkt_get_priorities |
Get files ranked by testing priority with reasons and suggestions |
brennpunkt_coverage_summary |
Quick overview: percentages, status, quick wins |
brennpunkt_get_file_coverage |
Detailed coverage for a specific file |
brennpunkt_estimate_impact |
"If I test these files, will I hit 90%?" |
Available MCP Resources (NEW):
| Resource URI | Purpose |
|---|---|
brennpunkt://coverage/{projectPath} |
Full coverage data as JSON for analysis |
brennpunkt://file/{projectPath}/{filePath} |
Detailed single-file coverage |
brennpunkt://priorities?project={path}&top={n} |
Pre-ranked priority list |
brennpunkt://config/{projectPath} |
Project configuration (yaml or defaults) |
brennpunkt://quick-wins?project={path} |
Small files with high impact |
Resources allow AI assistants to read coverage data directly without tool calls, enabling complex analysis like "Compare branch coverage across all auth files" and parallel data access.
Available MCP Prompts (NEW):
| Prompt | Purpose | Key Arguments |
|---|---|---|
improve_coverage |
Complete workflow to reach target percentage | projectPath (optional), targetPercentage, focusMetric |
analyze_gaps |
Understand patterns in coverage gaps | projectPath (optional), targetPercentage |
quick_wins_workflow |
Find fast paths to improvement | projectPath (optional), timeConstraint |
coverage_review |
Detailed review with test suggestions | projectPath (optional), filePattern |
Note: All prompts now support optional projectPath parameter. If not provided, the AI will infer it from conversation context (workspace paths, open files, git repositories, etc.), making prompts more convenient to use.
Prompts transform brennpunkt from a data provider to a coverage improvement partner, guiding you through actionable workflows instead of just showing numbers.
One-Time Setup (works for all projects):
{
"mcpServers": {
"brennpunkt": {
"command": "npx",
"args": ["-y", "-p", "@redaksjon/brennpunkt", "brennpunkt-mcp"]
}
}
}Or if installed globally (npm install -g @redaksjon/brennpunkt):
{
"mcpServers": {
"brennpunkt": {
"command": "brennpunkt-mcp"
}
}
}The AI passes the current workspace path as projectPath to each tool—no need to configure per-project.
Project Configuration Respected:
If a project has a brennpunkt.yaml, the MCP server automatically uses it:
# /path/to/project/brennpunkt.yaml
weights: "0.7,0.2,0.1" # This project prioritizes branch coverage
minLines: 20Each response includes configUsed so the AI knows what settings are active.
Example Workflows:
Human: What files should I focus on to improve test coverage?
AI: [calls brennpunkt_get_priorities with projectPath from workspace]
AI: The highest priority file is src/auth/login.ts (score: 156.3).
It has 35% branch coverage with 13 untested branches.
Suggested focus: Test error handling paths in validateCredentials().
Human: If I fully test login.ts and handler.ts, will I hit 90%?
AI: [calls brennpunkt_estimate_impact with those files]
AI: Current: 85.2% → Estimated: 91.8% (+6.6%)
Yes, testing those two files should get you above 90%.
Human: Compare coverage between auth-service and user-service.
AI: [calls brennpunkt_coverage_summary for each project]
AI: auth-service: 92.1% lines, 85.3% branches
user-service: 78.4% lines, 62.1% branches
user-service needs attention, especially branch coverage.
Why MCP Instead of Running Tests:
| Aspect | Running Tests | MCP Query |
|---|---|---|
| Speed | 30s-5min | <100ms |
| Data | Raw percentages | Prioritized + actionable suggestions |
| Efficiency | Redundant test runs | Reads existing coverage |
| Multi-project | Reconfigure each time | Query any project path |
See guide/ai-integration.md for complete documentation.
Don't want to configure MCP? Add this to your project's .cursorrules file for instant AI-powered coverage prioritization:
# Coverage Priority Analysis
When working on test coverage improvements:
1. Run `npx @redaksjon/brennpunkt --json --top 5` to get prioritized files
2. Focus on the highest priority file first (highest priorityScore)
3. Pay special attention to:
- Files with low branch coverage (untested conditionals hide bugs)
- Files with high uncoveredLines count
4. After writing tests, re-run brennpunkt to see updated priorities
When I ask about test coverage, run brennpunkt and interpret the results.
Suggest specific test cases based on the uncovered branches and functions.Usage: After adding this rule, just ask Cursor:
- "What files need test coverage?"
- "Help me improve test coverage"
- "Where should I focus my testing efforts?"
The AI will automatically run brennpunkt and provide actionable recommendations.
You can also use brennpunkt as a library:
import { parseLcov, analyzeCoverage, formatJson } from '@redaksjon/brennpunkt';
import { readFileSync } from 'node:fs';
const lcovContent = readFileSync('coverage/lcov.info', 'utf-8');
const files = parseLcov(lcovContent);
const result = analyzeCoverage(files, {
branches: 0.5,
functions: 0.3,
lines: 0.2,
}, 10, null);
console.log(formatJson(result));# Install dependencies
npm install
# Run tests
npm test
# Build
npm run build
# Lint
npm run lintApache-2.0 TEST TEST