{
  "markdown": "# QA Radar\n\n**Give your AI coding agent the quality brain it doesn't have to grow from scratch.**\n\nQA Radar analyzes your codebase and produces a structured quality health report — combining git churn, test coverage, and test-to-source mapping into risk-scored modules. It works as an **MCP server** for AI coding agents (Claude Code, Cursor, Windsurf) and as a **standalone CLI** for humans and CI pipelines.\n\nBuilt for developers who want their AI agent to write *targeted* tests, not generic ones.\n\n## Quick Start\n\n**Claude Code — one step:**\n\n```\n/plugin marketplace add Muratkus/qaradar\n/plugin install qaradar@qaradar-marketplace\n```\n\nThen ask your agent: _\"What should I test first?\"_\n\nOr run directly without installing:\n\n```bash\nuvx qaradar serve\n```\n\n[Full install options ↓](#install-as-claude-code-plugin-recommended)\n\n## What It Does\n\nQA Radar answers the question every new team member (and every AI agent) asks: **\"What should I test first?\"**\n\nIt scans three signals and combines them into a per-file risk score:\n\n| Signal | What It Measures | Why It Matters |\n|--------|-----------------|----------------|\n| **Git Churn** | Commit frequency, lines changed, recency | High-churn files are regression magnets |\n| **Coverage Gaps** | Line & branch coverage from existing reports | Low coverage = blind spots |\n| **Test Mapping** | Which source files have corresponding tests | No tests = no safety net at all |\n\nThe output is a ranked list of modules by risk level (critical → low), with human-readable reasons for each rating.\n\n## Why Not Just Let the Agent Do It?\n\nA capable agent with bash access could run `git log --numstat`, parse `coverage.xml`, and glob for test files. So why an MCP server?\n\n| Concern | What QA Radar does instead |\n|---------|---------------------------|\n| **Token cost** | `git log` over 90 days on a medium repo is hundreds of KB. QA Radar returns ~5 KB of structured JSON. |\n| **Determinism** | A weighted risk score computed ad-hoc in-context is unreliable. Code is reproducible. |\n| **Speed** | One tool call vs. 4–6 sequential bash calls + reasoning between each. |\n| **Format normalization** | LCOV / Cobertura / coverage.py JSON / Go cover profiles all parse differently. QA Radar normalizes across formats so the agent doesn't have to. |\n| **Convention encoding** | `test_x.py` for Python, `x.test.ts` for JS/TS, `x_test.go` for Go, `FooTest.java` for Java — encoded once, not re-derived each session. |\n| **Portability** | The same MCP tools work across Claude Code, Cursor, and Windsurf without re-prompting. |\n\n## Install as Claude Code Plugin (Recommended)\n\nThe fastest path — one command wires up the MCP server and installs 4 slash commands. No manual config editing.\n\n**Step 0 — install uv** (if you don't have it):\n\n```bash\ncurl -LsSf https://astral.sh/uv/install.sh | sh\n# or: pip install uv\n```\n\nuv launches qaradar on demand from PyPI — you don't need to `pip install qaradar` separately.\n\n**Step 1 — add the marketplace:**\n\n```\n/plugin marketplace add Muratkus/qaradar\n```\n\n**Step 2 — install:**\n\n```\n/plugin install qaradar@qaradar-marketplace\n```\n\n**What you get:** 6 MCP tools auto-configured + 5 slash commands:\n\n| Command | What it does |\n|---------|-------------|\n| `/qaradar:qa-check` | Full health report — risk, coverage, untested files |\n| `/qaradar:qa-risky` | Ranked list of riskiest files with reasons |\n| `/qaradar:qa-untested` | Source files with no detected tests + scaffold suggestions |\n| `/qaradar:qa-plan` | Prioritized test plan (chains 3 tools) |\n| `/qaradar:qa-pr-risk` | Which changed files in this PR are riskiest |\n\n**Example:** after merging a big feature branch, run `/qaradar:qa-check` to see what regressed. Before opening a PR, run `/qaradar:qa-pr-risk` to see what you need to test first.\n\n## MCP Server (for AI Coding Agents)\n\n### Setup\n\n**Alternative: manual MCP config** (if you prefer not to use the plugin):\n\nAdd to your Claude Code MCP config (`~/.claude/mcp.json` for user-level, or `.mcp.json` in the project root for project-level):\n\n```json\n{\n  \"mcpServers\": {\n    \"qaradar\": {\n      \"command\": \"uvx\",\n      \"args\": [\"qaradar\", \"serve\"]\n    }\n  }\n}\n```\n\nOr start it manually:\n\n```bash\nuvx qaradar serve\n```\n\n### Example Prompts\n\nOnce connected, ask your agent:\n\n> \"What should I test first in this repo?\"\n> \"Which files are the riskiest right now?\"\n> \"Show me the highest-churn files from the last month.\"\n> \"Which source files have no tests at all?\"\n> \"Which of my changed files are risky?\" ← diff-aware\n\n### Available MCP Tools\n\n| Tool | When the Agent Uses It |\n|------|------------------------|\n| `qaradar_healthcheck` | Full quality overview of a repository |\n| `qaradar_risky_modules` | What to test first; which files are riskiest |\n| `qaradar_churn` | Hotspot detection; where regressions tend to occur |\n| `qaradar_coverage_gaps` | Files with low coverage; where the blind spots are |\n| `qaradar_untested_files` | Source files with no corresponding test files |\n| `qaradar_pr_risk` | Which changed files in this PR need attention |\n| `qaradar_should_run` | After finishing work: should QA Radar re-analyze, and over the diff or the whole repo? |\n\n### Diff-aware: what's risky in this PR?\n\n`qaradar_pr_risk` scores only the files changed between a base ref and HEAD — not the whole repo. It keeps risk scores calibrated by using full-repo normalization, so a file with 2 commits in a PR isn't falsely flagged CRITICAL just because it's the only changed file the agent knows about.\n\nAsk your agent:\n> \"Which of my changed files are risky?\"\n> \"Do any of the files I changed lack tests?\"\n> \"What should I review before opening this PR?\"\n\nOr from the CLI:\n\n```bash\n# Diff against main — shows only changed files\nqaradar analyze . --base main\n\n# Diff against a specific ref\nqaradar analyze . --base origin/main --days 60\n```\n\n`qaradar_pr_risk` auto-detects the base branch from `GITHUB_BASE_REF` (set automatically in GitHub Actions) or falls back to `main`/`master`. Pass `base_ref` explicitly to override.\n\n## CLI\n\n```bash\n# Full health check on current directory\nqaradar analyze\n\n# Analyze a specific repo with 180 days of history\nqaradar analyze /path/to/repo --days 180\n\n# Output as JSON (for piping to other tools)\nqaradar analyze --json-output\n\n# Show top 10 risky modules only\nqaradar analyze --top 10\n\n# Diff-aware: score only files changed since main\nqaradar analyze . --base main\n```\n\n## Install\n\n```bash\npip install qaradar\n```\n\nOr run without installing:\n\n```bash\nuvx qaradar serve\n```\n\n**From source** (for development):\n\n```bash\ngit clone https://github.com/Muratkus/qaradar.git\ncd qaradar\npip install -e .\n```\n\n## Language Support\n\nAll language support lives in one registry — `qaradar/analyzers/languages.py` — so\nadding a language is a single entry (extensions, test-name convention, test-function\ncounter), consumed by both churn and test-mapping.\n\n### Tier 1 — First-class, tested\n\n| Language | Test detection | Coverage |\n|----------|---------------|---------|\n| Python | `test_x.py`, `x_test.py` | coverage.py JSON + XML |\n| JavaScript / TypeScript | `x.test.*`, `x.spec.*`, `x-test.*` (React Native) | LCOV, Jest/Istanbul JSON |\n| Go | `x_test.go` | Go cover profile (`cover.out`) |\n| Swift | `XTests.swift` (XCTest `func test…`) | Cobertura / LCOV |\n| Kotlin | `XTest.kt` (`@Test`) | Cobertura / LCOV |\n| Dart / Flutter | `x_test.dart` (`test(`, `testWidgets(`) | LCOV (`coverage/lcov.info`) |\n| Objective-C | `XTests.m` / `.mm` (XCTest `- (void)test…`) | Cobertura / LCOV |\n\n### Tier 2 — Best-effort, naming-based\n\nJava, Ruby, Rust — test detection via naming conventions. Coverage via Cobertura XML or LCOV if emitted.\n\n> Coverage parsing is format-driven, so it spans more ecosystems than test-mapping detection, which is language-specific.\n\n**Monorepos:** Istanbul/Jest reports are auto-discovered under `packages/*/coverage` and\n`apps/*/coverage`, and absolute/package-relative coverage paths are normalized to\nrepo-relative so they join correctly against churn and test-mapping signals.\n\n## Supported Coverage Formats\n\n| Format | Tools |\n|--------|-------|\n| coverage.py JSON | Python `coverage run` + `coverage json` |\n| Istanbul / Jest JSON | `coverage-final.json`, `coverage-summary.json` (Jest/Vitest/nyc) |\n| Cobertura XML | Python, Java/Gradle, .NET (Coverlet) |\n| LCOV | JS/TS, Flutter/Dart, C/C++, Rust (grcov) |\n| Go cover profile | `go test -coverprofile=cover.out` |\n\n## Example Output\n\n```\n╭──────────────── QA Radar Health Report ─────────────────╮\n│ Repository: /home/user/my-service                       │\n│ Source files: 47  Test files: 23  Ratio: 0.49           │\n│ Avg coverage: 62.3%  Tested: 31  Untested: 16          │\n╰─────────────────────────────────────────────────────────╯\n\n  CRITICAL risk modules: 3\n  HIGH risk modules: 7\n\n┌─────────────────────────────────────────────────────────┐\n│ Risky Modules                                           │\n├──────────────────────┬──────────┬───────┬───────────────┤\n│ File                 │ Risk     │ Score │ Reasons       │\n├──────────────────────┼──────────┼───────┼───────────────┤\n│ src/payments/core.py │ CRITICAL │  0.87 │ High churn:   │\n│                      │          │       │ 34 commits;   │\n│                      │          │       │ No tests      │\n│ src/auth/tokens.py   │ CRITICAL │  0.82 │ Low coverage: │\n│                      │          │       │ 12.3%; Active │\n│                      │          │       │ recently      │\n└──────────────────────┴──────────┴───────┴───────────────┘\n```\n\n## Tracking Runs Over Time\n\nBy default QA Radar is stateless. Opt in to persistence to track a repo across runs\nand drive incremental re-analysis (daily/weekly, or after N diffs, or after an agent\nfinishes work).\n\n```bash\nqaradar analyze . --save      # record a snapshot to .qaradar/state.json (gitignore it)\nqaradar should-run .          # exit 0 if a re-run is warranted, 1 if not — prints JSON\nqaradar status .              # last run, commits/days since, current decision + risk delta\n```\n\n`should-run` is a **gate**, not a scheduler — wire it into whatever you already use:\n\n```bash\n# cron / CI / git hook: only do expensive work when criteria are met\nqaradar should-run . && qaradar analyze . --save\n```\n\nIt reports `scope: \"full\"` (interval elapsed) or `scope: \"diff\"` (enough files changed),\nso an agent calling the `qaradar_should_run` MCP tool knows whether to follow up with\n`qaradar_healthcheck` or `qaradar_pr_risk`. State is one `.qaradar/state.json` per repo,\nso a \"collection of repos\" is just a loop over repos in your own infra.\n\nTune the criteria in `qaradar.toml`:\n\n```toml\n[schedule]\ninterval_days = 7        # re-run the full healthcheck at least weekly\nmin_changed_files = 25   # ...or sooner, once this many files have changed\n```\n\n`--save` also reports a **delta** vs the previous run — which files newly became risky,\nwhich got worse, which improved or resolved.\n\n## Roadmap\n\n- [x] **v0.1.2** — Claude Code plugin + slash commands\n- [x] **v0.2.0** — Config file (`qaradar.toml`), Tier 2 language validation, hardening\n- [x] **v0.3.0** — Diff-aware mode: `qaradar_pr_risk` + `--base` CLI flag\n- [x] **v0.4.0** — Mobile/monorepo language coverage (Swift, Kotlin, Obj-C, Dart, React Native, Jest); run persistence + re-run criteria (`should-run`, `--save`, `qaradar_should_run`)\n- [ ] **v0.5.0** — Flaky test detection from CI history (JUnit XML parsing)\n\n## Philosophy\n\nQA Radar is built on three beliefs:\n\n1. **The bottleneck has moved.** AI makes writing tests easy. Knowing *which* tests matter is the hard part.\n2. **Quality is a landscape, not a number.** A single coverage percentage hides everything. Risk is per-module, per-signal, per-timeframe.\n3. **Agents need context.** An AI coding assistant that doesn't know your repo's fragile areas will write generic tests. Give it the quality landscape and it writes targeted ones.\n\n## License\n\nMIT\n\n<!-- mcp-name: io.github.MuratKus/qaradar -->\n",
  "bytes": 11939,
  "sha": "53917065fc153dbb63cf0b3a180f0e51f35276570a2d78166ffcb4de5d97425f",
  "repo_slug": "muratkus/qaradar",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_muratkus_qaradar_00959079/readme"
}