{
  "markdown": "# RegressGuard\n\n[![Release](https://img.shields.io/github/v/release/Bharath-code/regressguard)](https://github.com/Bharath-code/regressguard/releases/latest)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)\n[![Go](https://img.shields.io/badge/go-1.25-00ADD8?logo=go)](go.mod)\n\n**Before you commit, know what broke.**\n\nWhen an AI coding agent edits your app it can silently break an API contract — a removed field, a changed status code, a test that now fails — and still report success. RegressGuard records a known-good baseline and tells you (or the agent) exactly what regressed.\n\n**It is built to live inside the agent's own loop.** RegressGuard ships as an [MCP](https://modelcontextprotocol.io) server, so agents like Claude Code and Cursor can verify their own work and self-correct *before* a human ever sees the diff — zero extra steps. The same engine also runs as a plain CLI for humans and CI.\n\n```\n# Agent-native (primary): the agent calls these as MCP tools in its loop\nsnapshot → check → status        # see \"Agent-native verification (MCP)\" below\n\n# Human / CI (also works): two commands, no test-writing, under 15 seconds\nrg snapshot   # record the known-good state\nrg check      # compare after edits — see what broke\n```\n\n![RegressGuard demo: an AI agent breaks an API contract, rg check blocks the commit and names the culprit file, the agent fixes it, check goes green](demo/demo.gif)\n\n*Break → detect → fix → green. Reproduce it yourself: `./demo/demo.sh`.*\n\n---\n\n## Install\n\n**macOS / Linux (recommended)**\n\n```sh\ncurl -fsSL https://raw.githubusercontent.com/Bharath-code/regressguard/main/install.sh | sh\n```\n\n**Homebrew**\n\n```sh\nbrew install Bharath-code/tap/rg\n```\n\n**Verify**\n\n```sh\nrg version   # first line must say \"RegressGuard\"\n```\n\n> **Have ripgrep installed?** ripgrep also ships as `rg`, and whichever comes first on\n> PATH wins — `rg check` could silently run ripgrep instead of RegressGuard. If\n> `rg version` doesn't say \"RegressGuard\", invoke the full path (e.g.\n> `/usr/local/bin/rg`). The pre-commit hook and GitHub Action already use absolute\n> paths and are unaffected; `rg doctor` flags the collision.\n\n---\n\n## Quickstart (3 minutes)\n\n### 1. Initialize your project\n\n```sh\ncd your-project\nrg init\n```\n\nRegressGuard detects your test command, framework, and dev server URL automatically.\n\n### 2. Record the baseline before your AI session\n\nMake sure your dev server is running, then:\n\n```sh\nrg snapshot\n```\n\nOutput:\n\n```\nSnapshot\n\nOK Tests       42 passed, 0 failed       6.8s\nOK Routes      6 captured, 2 skipped\nOK Schemas     6 hashed\n\nSaved:\n  .regressguard/snapshot.json\n\nNext:\n  Ask your AI agent to make the code change, then run:\n  rg check\n```\n\n### 3. Run your AI agent\n\nLet Claude Code, Cursor, or Codex make its changes.\n\n### 4. Check for regressions before committing\n\n```sh\nrg check\n```\n\n**Clean — safe to commit:**\n\n```\nCheck\n\nOK No regressions detected\n\n  Tests       42 passed, 0 failed\n  Routes      6 unchanged\n  Timing      within tolerance\n\nSafe to commit.\n```\n\n**Regression found — commit blocked:**\n\n```\nCheck\n\nX 2 regressions detected\n\n  Route                                 Before    After     Change\n  GET /api/users                        schema    schema    schema\n    - role (string, removed)\n    + age (number, added)\n  POST /api/user/update                 200       500       status\n\nLikely cause:\n  Auth/session behavior or routing changed during the last code edit.\n\nChanged files since snapshot:\n  app/api/users/route.ts\n  internal/auth/session.go\n\nNext:\n  rg check --verbose\n  git diff\n\nCommit blocked.\n```\n\nExit code `1` on critical — works with git hooks and CI.\n\n---\n\n## Git Hook (auto-protect every commit)\n\n```sh\nrg hook install\n```\n\nNow `rg check` runs automatically before every `git commit`. When a critical regression is detected, the commit is blocked with a compact output:\n\n```\nRegressGuard pre-commit\n\nX 1 regression detected\n  POST /api/user/update status changed from 200 to 500\n\nRun:\n  rg check --verbose\n\nCommit blocked. Use --no-verify only if you accept the risk.\n```\n\nBypass with `git commit --no-verify` only when you accept the risk.\n\n---\n\n## Agent-native verification (MCP)\n\nThis is RegressGuard's primary mode. Instead of waiting for a human to run `rg check`, the AI agent calls it **as a tool inside its own edit loop** — so it catches and fixes regressions it just introduced, before handing the change back to you.\n\nStart the server (stdio transport):\n\n```sh\nrg mcp serve\n```\n\n**Register with Claude Code:**\n\n```sh\nclaude mcp add regressguard -- rg mcp serve\n```\n\n**Register with Cursor** (`.cursor/mcp.json`):\n\n```json\n{\n  \"mcpServers\": {\n    \"regressguard\": { \"command\": \"rg\", \"args\": [\"mcp\", \"serve\"] }\n  }\n}\n```\n\nThe agent then has three tools:\n\n| Tool | Purpose |\n|---|---|\n| `snapshot` | Record the current passing state as the baseline |\n| `check` | Compare current state against the snapshot; returns structured findings with severity |\n| `status` | Sub-second health check (snapshot age, route/config/hook status) — no tests run |\n\nTool responses are the **same machine-readable payload as `rg check --json`** — see [`docs/json-contract.md`](docs/json-contract.md). Every tool call is recorded to an append-only audit log under `.regressguard/` (tool, status, duration, timestamp).\n\nA typical loop: the agent edits code → calls `check` → reads the structured findings → fixes the regression → calls `check` again → only then reports done.\n\n---\n\n## Commands\n\n| Command | Purpose |\n|---|---|\n| `rg init` | Configure RegressGuard for this project |\n| `rg quickstart` | Auto-configure and snapshot in one command |\n| `rg snapshot` | Record the current passing state |\n| `rg check` | Compare current state against the snapshot |\n| `rg status` | Sub-second health check (snapshot age, routes, hook) — no tests run |\n| `rg explain <route>` | Show before/after diff for a specific route |\n| `rg watch` | Watch files and auto-run check on changes |\n| `rg mcp serve` | Run the MCP server so AI agents can self-verify (see above) |\n| `rg hook install` | Install the pre-commit git hook |\n| `rg hook uninstall` | Remove the git hook |\n| `rg config get <key>` | Read a config value |\n| `rg config set <key> <value>` | Write a config value |\n| `rg doctor` | Diagnose setup issues |\n| `rg upgrade` | Update rg to the latest version |\n| `rg completion <shell>` | Generate shell autocompletions (bash, zsh, fish) |\n| `rg version` | Print version and build metadata |\n\nRun `rg <command> --help` for flags, examples, and exit codes.\n\n---\n\n## Configuration\n\nConfig lives in `.regressguard/config.json` (human-readable, git-ignoreable).\n\n```json\n{\n  \"version\": 1,\n  \"testCommand\": \"npm test\",\n  \"serverUrl\": \"http://localhost:3000\",\n  \"auth\": {\n    \"mode\": \"bearer\",\n    \"testToken\": \"your-test-token\",\n    \"headerName\": \"Authorization\",\n    \"prefix\": \"Bearer\"\n  },\n  \"ignoreFields\": [\"requestId\", \"traceId\"],\n  \"routes\": [\n    { \"method\": \"GET\", \"path\": \"/api/health\" },\n    { \"method\": \"GET\", \"path\": \"/api/users\" },\n    { \"method\": \"GET\", \"path\": \"/api/admin\", \"skip\": true }\n  ]\n}\n```\n\n**Auth modes:** `bearer` (Authorization header), `cookie` (Cookie header), or omit for public routes only.\n\n**ignoreFields:** Fields to exclude from schema comparison — useful for volatile app-specific values like `requestId` or `traceId`.\n\n---\n\n## How it works\n\n1. `rg snapshot` runs your test suite and hits each configured route. It records pass/fail counts, HTTP status codes, and a normalized schema hash for each response.\n\n2. `rg check` reruns the same tests and routes, then diffs against the snapshot:\n   - **CRITICAL**: test suite newly failing, status code changed, response schema changed (e.g. field removed/added/changed)\n   - **WARNING**: response time increased >200ms and >50% of baseline\n   - **PASS**: everything within acceptable variance\n\n3. Schema comparison automatically normalizes JSON payloads:\n   - **Default Dynamic Keys**: Strips 16 common dynamic keys (`id`, `uuid`, `token`, `nonce`, `timestamp`, `createdAt`, `updatedAt`, `deletedAt`, `created_at`, `updated_at`, `deleted_at`, `sessionId`, `accessToken`, `refreshToken`, `expiresAt`, `expires_at`) before hashing.\n   - **Pattern Detection**: Automatically detects ISO-8601 date strings, UUIDs, and JWTs, replacing them with generic type representations (`\"date\"`, `\"uuid\"`, `\"token\"`).\n   - **User Customization**: Respects custom `ignoreFields` defined in config.\n\n   This ensures the shape integrity of endpoints remains stable across runs even when database IDs and timestamps change.\n\n4. A route whose only change is a non-blocking **WARNING** (e.g. a timing regression) is reported on its own line and is **not** counted in the \"Routes: N unchanged\" summary or in `summary.passed` of `--json` output.\n\n### Known limitations\n\nThese are deliberate trade-offs in v1 — favoring zero false positives over exhaustive detection. They are on the roadmap, not accidental:\n\n- **Test identity comparison is best-effort.** `rg check` records failing test *names* (jest, vitest, bun, go test output) and flags a CRITICAL when a test that passed at baseline starts failing — even if the net failure count is unchanged. When names cannot be parsed from your runner's output (or the baseline predates name recording), it falls back to count comparison: a CRITICAL only when the number of failing tests *increases*. Pair `rg check` with your normal test runner in CI for exhaustive per-test assertions.\n- **Array schemas are inferred from the first element.** The schema normalizer represents a JSON array's shape using its first element. If later elements have a different shape (heterogeneous arrays), that divergence is not reflected in the schema hash and will not be flagged.\n\n---\n\n## Exit codes\n\n| Code | Meaning |\n|---|---|\n| `0` | Pass or warnings only — safe to commit |\n| `1` | Critical regression detected — commit blocked |\n| `2` | Usage, config, or runtime error |\n\n---\n\n## Scripting and CI\n\n```sh\n# JSON output for scripts and agents\nrg check --json | jq .status\n\n# Verbose diagnostics on stderr (stdout stays clean JSON)\nrg check --json --verbose\n\n# Disable color for CI\nNO_COLOR=1 rg check\n```\n\n**GitHub Action** — runs `rg check` on every PR and comments the findings:\n\n```yaml\n- uses: Bharath-code/regressguard@v0\n  with:\n    server-command: npm run dev\n```\n\nSee [`action.yml`](action.yml) for all inputs (version pinning, working directory, server URL).\n\n---\n\n## Supported stacks (v1)\n\n- **Frameworks**: Next.js App Router, Express, Hono\n- **Test runners**: Vitest, Jest, Bun test, npm test\n- **Package managers**: npm, pnpm, yarn, bun\n- **Auth**: Bearer token, Cookie header, public routes\n\nPython, FastAPI, and Django support is planned for v2.\n\n---\n\n## Demo fixture\n\nA minimal Next.js API fixture is included in `fixtures/nextjs-app` for demos and testing. See [fixtures/README.md](fixtures/README.md).\n\n---\n\n## Open core\n\nThis repo — the CLI and MCP server — is free and MIT, forever. A hosted team layer\n(cross-repo dashboard, history retention, compliance export) is scoped in\n[`docs/paid-layer-spec.md`](docs/paid-layer-spec.md). Anything that runs on one machine for\none repo stays free; the paid layer is strictly additive.\n\n---\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for release history.\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n\n---\n\n*From the same developer as [git-scope](https://github.com/Bharath-code/git-scope).*\n",
  "bytes": 11450,
  "sha": "6056d187b8d33477c1a6006c1eb44797d9432a8201ac7f72c660fcb363e9888d",
  "repo_slug": "bharath-code/regressguard",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_bharath_code_regressguard_02064397/readme"
}