{"id":"eae1c627-4c03-47f3-9d66-ef048df1fb5b","slug":"pr-guardian","kind":"mcp","name":"pr-guardian","summary":"AI-assisted code review and release automation for Python repos — built to learn every Claude Code feature (agents, hooks, skills, slash commands, MCP).","owner":"SumitCodesAI","repoUrl":"https://github.com/SumitCodesAI/pr-guardian","license":"MIT","licenseTier":"permissive","trust":"community","stars":2,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-08-11T05:02:16.000Z","addedAt":"2026-10-21T17:54:11.114Z","logoUrl":"https://avatars.githubusercontent.com/u/176538002?u=ff52446363c8a3f3b7198e45c7658a85d8a3db07&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["developer-tools"],"tags":[],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T22:47:18.768Z","sample":false,"url":"https://conduits.dev/tools/pr-guardian","language":"Python","transports":["stdio"],"install":{"pypi":"pr-guardian"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# PR Guardian\n\n**AI-assisted code review and release automation for Python repos — built to\nteach every major Claude Code feature by doing.**\n\nPR Guardian reviews a Python diff across four specialized passes — **security,\nstyle, test coverage, docs** — each with a pass/fail verdict, and generates\nKeep-a-Changelog release notes from git history. The same review categories run\nin **two cooperating layers**: a fast, offline, fully unit-tested deterministic\nPython CLI, and a Claude Code AI layer that drives the *same* passes with\nsubagents, skills, slash commands, hooks, and an MCP server.\n\n> **Why this project exists.** It is a hands-on playground for learning Claude\n> Code. Every feature below does *real* work in this repo — nothing is a toy —\n> so by the time you've read this and run it, you will have used\n> **CLAUDE.md, agents, hooks, slash commands, skills, and MCP** in one coherent\n> project, and you'll understand *why* each feature exists and *when* to reach\n> for it.\n\n---\n\n## Table of contents\n\n1. [The big picture: two layers, one format](#the-big-picture-two-layers-one-format)\n2. [Quick start](#quick-start)\n3. [Setting up on a new machine](#setting-up-on-a-new-machine)\n4. [Feature-by-feature tour](#feature-by-feature-tour)\n5. [How the two layers mirror each other](#how-the-two-layers-mirror-each-other)\n6. [End-to-end flows](#end-to-end-flows)\n7. [Project layout](#project-layout)\n8. [Usage reference](#usage-reference)\n9. [The demo repository](#the-demo-repository)\n10. [Testing](#testing)\n11. [Troubleshooting](#troubleshooting)\n12. [Further reading](#further-reading)\n\n---\n\n## The big picture: two layers, one format\n\n```\nPR GUARDIAN — one codebase, two layers, one finding format\n==========================================================\n\n  LAYER 1 · DETERMINISTIC ENGINE          LAYER 2 · CLAUDE CODE AI LAYER\n  Python · offline · fully tested         Claude running in your editor\n\n  pr-guardian CLI                         /review\n    ├─ review                             /security-scan\n    ├─ scan                               /release-notes\n    └─ release-notes\n\n  src/pr_guardian/                        .claude/\n    ├─ diff_parser.py                       ├─ agents/    4 scoped review subagents\n    ├─ git_utils.py                         ├─ skills/    security-finding, changelog-entry\n    ├─ reviews/     4 review passes         ├─ commands/  the slash commands above\n    ├─ changelog.py                         ├─ hooks/     guard_bash · format_on_save · summary\n    └─ output.py                            └─ CLAUDE.md  session context + conventions\n\n                                          MCP:  .mcp.json → filesystem server tools\n\n  both layers emit the SAME finding shape:\n  category · severity · file:line · explanation · suggested fix\n```\n\n- **Layer 1 — deterministic engine** (`src/pr_guardian/`): pure Python, no API\n  keys, no network. It parses git history and unified diffs, runs static\n  analyzers for each review category, and renders Rich terminal reports. Fully\n  covered by unit + end-to-end tests.\n- **Layer 2 — Claude Code AI layer** (`.claude/`): the *richer* version of the\n  same categories, run by Claude. Each category is a scoped **subagent**;\n  findings are formatted by reusable **skills**; slash **commands** orchestrate\n  the pipeline; **hooks** gate destructive commands and auto-format on save;\n  an **MCP** server gives Claude filesystem tools; **CLAUDE.md** tells Claude\n  how to behave in this repo.\n\n**Why two layers?** You get the best of both: the CLI is instant, offline, and\ntestable (great for CI), while the AI layer understands intent, reads\nsurrounding context, and can *fix* issues — not just report them. And because\nboth layers speak the same \"finding shape,\" a human can move between a\n`pr-guardian scan` report and a `/security-scan` report without relearning the\nformat.\n\n---\n\n## Quick start\n\n**Prerequisites**\n\n- Python **3.11+** and `git` on your PATH\n- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/setup) (for the AI layer)\n- Node.js + `npx` (only for the MCP server — see [MCP](#mcp))\n\n**1. Install**\n\n```bash\npython -m pip install -e \".[dev]\"\n```\n\n**2. Try the deterministic CLI** against a throwaway demo repo that is\n*deliberately* full of issues:\n\n```bash\npython tests/fixtures/build_demo_repo.py demo-repo-build/\ncd demo-repo-build\npython -m pr_guardian.cli review main      # or `pr-guardian review main` once installed\npython -m pr_guardian.cli release-notes v0.1.0 v0.2.0\ncd ..\n```\n\nYou'll see FAIL verdicts on every category — that is the point. Each finding is\na real, deliberate bug in the demo app.\n\n**3. Try the Claude Code AI layer** — from inside this repo, ask Claude Code:\n\n- `/review` — full four-pass review of the current diff\n- `/security-scan` — fast security-only pass\n- `/release-notes` — release notes from a commit range\n\n**4. Try MCP** — see the [MCP section](#mcp) below for the one-time approval\nstep, then just ask Claude: *\"list the files in this project with the\nfilesystem MCP server.\"*\n\n---\n\n## Setting up on a new machine\n\nPR Guardian is designed so a fresh clone works with as little setup as\npossible. How much you need depends on which layer you want:\n\n| You want to…                              | What you need                  | Extra step                    |\n| ----------------------------------------- | ------------------------------ | ----------------------------- |\n| Use the CLI and run the tests             | Python 3.11+ and git           | none — works immediately      |\n| Run the AI review passes                  | Claude Code, logged in         | start `claude` from repo root |\n| Use the MCP filesystem tools              | Node.js + `npx` (network once) | approve the server on first run |\n\n**1. Clone and install**\n\n```bash\ngit clone <your-repo-url>\ncd pr-guardian\npython -m pip install -e \".[dev]\"\n```\n\n**2. Verify the deterministic layer** — no keys, no network, no extra config:\n\n```bash\npytest               # full suite (engine + CLI end-to-end)\nruff check .         # lint clean\npr-guardian --help   # CLI installed as a `pr-guardian` command\n```\n\n**3. The AI layer runs inside Claude Code.** The `.claude/` agents, commands,\nskills, and hooks ship with the repo, but they only execute when you're in a\nClaude Code session — and they run on **your** Claude Code account, not the\nrepo author's. Install\n[Claude Code](https://docs.anthropic.com/en/docs/claude-code/setup), log in,\nthen start a session **from the repo root** (the hooks use project-relative\npaths):\n\n```bash\nclaude\n/review\n```\n\nOn your first session Claude will ask you to **approve the filesystem MCP\nserver** — this is the standard security prompt for a project-scoped server,\nand it can only read/write this project directory. First use downloads the\nserver via `npx`, so you need network once.\n\n**4. CI needs nothing from you.** [`.github/workflows/ci.yml`](.github/workflows/ci.yml)\nruns the same `ruff` + `pytest` checks automatically on every push and PR.\n\n---\n\n## Feature-by-feature tour\n\nFor each feature: **what it is** → **where it lives** → **what this project\ndoes with it** → **try it**.\n\n### CLAUDE.md\n\n**What it is.** A project-instructions file that Claude Code reads at session\nstart and treats as standing context. It's how you tell Claude *who you are,\nwhat the project is, how code should be written, and what not to touch* — no\nneed to re-explain in every prompt.\n\n**Where it lives.** [`CLAUDE.md`](CLAUDE.md) at the repo root.\n\n**What this project does with it.** It defines the whole project: the\ntwo-layer architecture, the directory layout, the enforced Python conventions\n(type hints, docstrings, no bare `except:`, line length 100 — which ruff also\nenforces in CI and the `style-reviewer` subagent enforces in the AI layer),\nand how to run everything.\n\n**Try it.** Open `CLAUDE.md` and note how `style-reviewer` reads it before\nreviewing — a subagent that pulls its rules from the same file humans read is\nthe reason conventions stay consistent. Ask Claude Code *\"what are the coding\nconventions here?\"* and watch it answer from this file.\n\n### Agents\n\n**What they are.** Scoped, reusable Claude sessions with a specific role,\nnarrowed tools, and a focused system prompt. Agents keep each task small,\nsafe, and parallelizable — instead of one giant Claude doing everything, you\ndispatch specialists.\n\n**Where they live.** `.claude/agents/*.md`. Each file's frontmatter declares\nthe agent's `name`, `description` (when Claude auto-selects it), and the\n`tools` it may use.\n\n**What this project does with it.** Four review subagents, one per pass:\n\n| Agent | Job | Tools |\n| --- | --- | --- |\n| `security-reviewer` | secrets, eval/exec, `shell=True`, SQL injection, unsafe deserialization, missing validation | Read, Glob, Grep |\n| `test-coverage-reviewer` | changed code vs. its test file; flags untested branches | Read, Glob, Grep |\n| `style-reviewer` | CLAUDE.md conventions (type hints, docstrings, bare excepts, naming) | Read, Glob, Grep |\n| `docs-writer` | missing docstrings / README gaps on changed public API — **may edit** | Read, Glob, Grep, Edit, Write |\n\n`/review` dispatches all four in parallel and consolidates their findings.\nNote the intentional tool restriction: three agents are read-only (a reviewer\nshould *report*, not modify), while `docs-writer` gets Edit/Write because its\njob is to fix documentation.\n\n**Try it.** Run `/review` and watch four agents fan out. Or ask directly:\n*\"use the security-reviewer agent on the current diff.\"*\n\n### Slash commands\n\n**What they are.** Reusable prompt templates you invoke with `/name`. They turn\na one-word command into a precise, multi-step instruction — so a routine task\nalways runs the same way.\n\n**Where they live.** `.claude/commands/*.md` (the filename without `.md` is the\ncommand name; the frontmatter `description` shows in the command picker).\n\n**What this project does with it.**\n\n| Command | What it does | Layers used |\n| --- | --- | --- |\n| `/review` | Finds the base branch, captures the diff, dispatches all four review subagents in parallel, consolidates into a verdict report | agents, skills, (docs-writer may edit) |\n| `/security-scan` | Security-only fast pass | `security-reviewer` + `security-finding` skill |\n| `/release-notes` | Resolves a commit range, formats each commit via a skill, assembles a Keep-a-Changelog doc | `changelog-entry` skill |\n\n**Try it.** Run `/review` now. Then open [.claude/commands/review.md](.claude/commands/review.md) and see exactly what steps Claude follows.\n\n### Skills\n\n**What they are.** Reusable *procedures* — packaged instructions for a repeatable\npiece of work. A skill is invoked explicitly by Claude when the task calls for\nit, and can be shared across commands and projects. Think: \"how to do X well,\"\nnot \"do X once.\"\n\n**Where they live.** `.claude/skills/<name>/SKILL.md`.\n\n**What this project does with it.** Two skills that keep output consistent\nacross the AI layer:\n\n- [`security-finding`](.claude/skills/security-finding/SKILL.md) — turns any\n  flagged security issue into the standard finding shape (severity, location,\n  category, explanation, suggested fix) with a severity rubric. Every agent\n  that reports a security issue formats it through this skill, so a `/review`\n  finding and a `pr-guardian scan` finding read identically.\n- [`changelog-entry`](.claude/skills/changelog-entry/SKILL.md) — turns one\n  commit (message + diff) into exactly one Keep-a-Changelog line: parses\n  conventional-commit prefixes, handles breaking changes, writes from behavior\n  not code. `/release-notes` invokes it once per commit.\n\n**Try it.** Run `/release-notes`, then compare a line Claude produced with the\nskill's documented output format — they match, because the skill drove it.\n\n### Hooks\n\n**What they are.** Scripts Claude Code runs automatically around tool calls and\nsession events. This is the feature that makes behavior *deterministic*: hooks\nfire on real events (before a tool runs, after it runs, on stop), regardless\nof what Claude \"feels\" like doing. Configured in `.claude/settings.json`.\n\n**Where they live.** `.claude/settings.json` (config) + `.claude/hooks/*.py`\n(the scripts). Each hook reads a JSON payload from stdin and writes a JSON\nresponse to stdout.\n\n**What this project does with it.** Three hooks, one per lifecycle stage:\n\n| Event | Hook | Behavior |\n| --- | --- | --- |\n| `PreToolUse` (Bash) | [`guard_bash.py`](.claude/hooks/guard_bash.py) | Detects destructive commands (`rm -rf`, `git push --force`, `git reset --hard`, `git clean -f`, …) and routes them through the permission prompt with a warning instead of letting them run blindly. Fail-open: safe commands pass straight through. |\n| `PostToolUse` (Edit/Write) | [`format_on_save.py`](.claude/hooks/format_on_save.py) | Runs `ruff format` + `ruff check --fix` on every Python file Claude edits, and reports back what changed. Fail-open: missing ruff, non-Python files, or bad payloads are no-ops. |\n| `Stop` | [`summary.py`](.claude/hooks/summary.py) | Tails the session transcript and prints a short \"✓ Done: …\" summary of the last thing Claude said. |\n\n**Try it.** Make a trivial edit to any Python file and watch the auto-format\nhook report what it reformatted. Then try to convince Claude to run\n`git reset --hard` and watch `guard_bash` intercept it. (Note: hook commands\nuse project-relative paths, so launch Claude Code from the repo root.)\n\n### MCP\n\n**What it is.** **M**odel **C**ontext **P**rotocol — a standard way to plug\nexternal tools and data into Claude. An MCP *server* exposes a set of *tools*\n(plus optionally resources and prompts) over a simple protocol; Claude Code\ndiscovers them and calls them like any other tool. It's how Claude gets access\nto things it can't do natively — in this project, filesystem operations via a\nwell-known community server.\n\n**Where it lives.** MCP servers are registered in [`.mcp.json`](.mcp.json) at\nthe project root. This file is read by Claude Code **at session start**, so\nafter editing it you must start a new session.\n\n**What this project does with it.** We connect the official reference\n**filesystem server**, scoped to this project directory:\n\n```json\n{\n  \"mcpServers\": {\n    \"filesystem\": {\n      \"type\": \"stdio\",\n      \"command\": \"npx\",\n      \"args\": [\n        \"-y\",\n        \"@modelcontextprotocol/server-filesystem\",\n        \"C:/Claude_Projects/pr-guardian\"\n      ]\n    }\n  }\n}\n```\n\n- `type: \"stdio\"` — the server speaks over standard input/output (the default for local servers).\n- `command: \"npx\"` + `-y` — Node's package runner downloads and launches the server (first run needs network; later runs are instant).\n- The last argument is an **allowlist of directories** the server may touch. We scope it to the repo root so Claude can read and write files *inside the project* only.\n\nOnce connected, Claude gains tools named `mcp__filesystem__*`, including:\n`read_file`, `write_file`, `edit_file`, `list_directory`, `directory_tree`,\n`search_files`, `create_directory`, `move_file`, and more.\n\n**Try it.**\n\n1. **Verify the server is registered** — from a terminal in this repo:\n   ```bash\n   claude mcp list          # should list \"filesystem\"\n   claude mcp get filesystem\n   ```\n   The first time a session sees a project-scoped server it asks you to\n   **approve** it (a cloned repo must never silently launch processes on your\n   machine). If you declined earlier, reset with\n   `claude mcp reset-project-choices`.\n2. **Inside a Claude Code session**, the `/mcp` panel shows connected servers\n   and their tool counts.\n3. **Use it** — ask: *\"Use the filesystem MCP server to list the top-level\n   files in this project.\"* Claude will call\n   `mcp__filesystem__list_directory` and show you the tree.\n\n**Gotchas.** MCP tools only appear **after** the session that reads `.mcp.json`\nis started — restart after editing the file. If `npx` isn't found, install\nNode.js or point `command` at its full path. The server can only reach the\ndirectories you listed, so it's safe by construction.\n\n---\n\n## How the two layers mirror each other\n\nOne idea drives the whole repo: **a finding from the CLI and a finding from\nClaude should be readable the same way.** The table shows the mirrors:\n\n| Concept | Deterministic engine (`src/pr_guardian/`) | Claude Code layer (`.claude/`) |\n| --- | --- | --- |\n| Review command | `pr-guardian review` | `/review` |\n| Security pass | [`reviews/security.py`](src/pr_guardian/reviews/security.py) | `agents/security-reviewer.md` + `skills/security-finding` |\n| Style pass | [`reviews/style.py`](src/pr_guardian/reviews/style.py) | `agents/style-reviewer.md` |\n| Test-coverage pass | [`reviews/test_coverage.py`](src/pr_guardian/reviews/test_coverage.py) | `agents/test-coverage-reviewer.md` |\n| Docs pass | [`reviews/docs.py`](src/pr_guardian/reviews/docs.py) | `agents/docs-writer.md` |\n| Release notes | `pr-guardian release-notes` | `/release-notes` + `skills/changelog-entry` |\n| Finding shape | `Finding` dataclass ([`reviews/base.py`](src/pr_guardian/reviews/base.py)) | `security-finding` skill's YAML fields |\n| Conventions | ruff + `CLAUDE.md` | `style-reviewer` (reads `CLAUDE.md`) |\n\n---\n\n## End-to-end flows\n\n### Deterministic review (CLI)\n\n```\npr-guardian review main\n        │\n        ▼\n  discover repo (git) ──► git diff main...HEAD ──► parse unified diff (diff_parser.py)\n        │\n        ▼\n  run 4 reviewers over the added lines (reviews/)\n   ├─ security        (regex + SQL-injection heuristics)\n   ├─ test-coverage   (does the test file exist / changed?)\n   ├─ style           (AST: type hints, bare excepts, naming)\n   └─ docs            (AST: docstrings on new public API)\n        │\n        ▼\n  render verdict table + findings (Rich) ──► exit code 0 (pass) / 1 (fail)\n```\n\n### AI review (Claude Code)\n\n```\n/review\n   │\n   ▼\nfind base branch ──► git diff <base>...HEAD ──► list changed files\n   │\n   ▼\ndispatch 4 subagents in PARALLEL\n   ├─ security-reviewer        findings formatted with the security-finding skill\n   ├─ test-coverage-reviewer\n   ├─ style-reviewer           reads CLAUDE.md for the conventions\n   └─ docs-writer              may Edit docstrings/README — surface edits for approval\n   │\n   ▼\nconsolidate into one verdict table (PASS/FAIL per category) + findings\n```\n\n### Release notes (both layers)\n\n```\nCLI  (changelog.py)                 AI  (/release-notes)\n  classify_commit()                   changelog-entry skill, once per commit\n  feat→Added · fix→Fixed              parses conventional-commit prefixes\n  refactor!→Changed (BREAKING)        handles breaking changes\n  docs/chore→skipped                  writes from behavior, not code\n         │                                     │\n         └───────────────► assemble the same Keep-a-Changelog layout:\n                              ## [version] - date\n                              ### Added  /  ### Changed  /  ### Fixed\n```\n\n### MCP flow\n\n```\n.mcp.json  (project root — read by Claude Code at session start)\n   │\n   ▼\nClaude Code spawns:  npx @modelcontextprotocol/server-filesystem <dir>\n   │\n   ▼\nClaude gains tools named  mcp__filesystem__*\n   │   read_file · write_file · edit_file · list_directory\n   │   directory_tree · search_files · create_directory · move_file\n   │\n   ▼\nyou ask \"list the project files\" ──► Claude calls a tool ──►\n   server reads the allowlisted directory ──► result shown to you\n```\n\n---\n\n## Project layout\n\n```\npr-guardian/\n├── CLAUDE.md                  # session context for Claude Code (this is a feature!)\n├── README.md                  # you are here\n├── pyproject.toml             # packaging + ruff + pytest config\n├── .mcp.json                  # MCP server registration (the MCP feature)\n├── .gitignore\n├── .claude/                   # the Claude Code AI layer\n│   ├── settings.json          # hooks config (PreToolUse / PostToolUse / Stop)\n│   ├── agents/                # 4 scoped review subagents\n│   ├── skills/                # security-finding, changelog-entry\n│   ├── commands/              # /review, /security-scan, /release-notes\n│   └── hooks/                 # guard_bash.py, format_on_save.py, summary.py\n├── src/pr_guardian/           # the deterministic engine\n│   ├── cli.py                 # Typer app: review, scan, release-notes\n│   ├── diff_parser.py         # unified diff → structured FileChange/Hunk/Line\n│   ├── git_utils.py           # GitPython: diff + commit history extraction\n│   ├── changelog.py           # commits → categorized changelog\n│   ├── output.py              # Rich rendering of reports\n│   └── reviews/               # one analyzer module per review category\n│       ├── base.py            # Reviewer protocol + Finding dataclass\n│       ├── security.py / style.py / test_coverage.py / docs.py\n└── tests/\n    ├── conftest.py            # demo_repo fixture (builds real git history)\n    ├── test_*.py              # unit + CLI end-to-end tests\n    └── fixtures/\n        ├── demo_repo/         # final-state working tree (deliberate issues)\n        └── build_demo_repo.py # materializes history, tags, a feature branch\n```\n\n---\n\n## Usage reference\n\n### CLI\n\n```\npr-guardian review [BASE]          # full four-pass review vs BASE (default: main)\npr-guardian scan [BASE]            # security-only pass\npr-guardian release-notes FROM TO  # Keep-a-Changelog from a commit range\npr-guardian --help                 # all commands/options\n```\n\nOptions: `review --categories security,style` limits passes; `release-notes\n--date YYYY-MM-DD` sets the release date. Exit code is `0` when no ERROR-level\nfindings, `1` when there are — CI-friendly.\n\n### Slash commands (Claude Code)\n\n`/review` · `/security-scan` · `/release-notes`\n\n### MCP tools (Claude Code)\n\n`mcp__filesystem__*` — `read_file`, `write_file`, `edit_file`,\n`list_directory`, `directory_tree`, `search_files`, `create_directory`,\n`move_file`, …\n\n---\n\n## The demo repository\n\n`tests/fixtures/build_demo_repo.py` materializes a throwaway git repo — real\ncommits, two tags (`v0.1.0`, `v0.2.0`), and a `feature/ai-review` branch whose\ndiff is *deliberately* full of issues. It is the review pipeline's own test\ndata: this is exactly the kind of code a reviewer is supposed to catch.\n\n| Demo file | Deliberate issue | Pass that flags it |\n| --- | --- | --- |\n| `auth.py` | hardcoded API key + `eval()` | security |\n| `review_pipeline.py` | `subprocess.run(..., shell=True)`, bare `except:`, missing type hints/docstrings | security, style, docs |\n| `slack.py` | hardcoded webhook URL, no tests, missing hints/docstrings | security, test-coverage, style, docs |\n| `db.py` | SQL built by f-string interpolation | security |\n\nThe fixture tree is **excluded** from ruff and pytest (`pyproject.toml`) —\nlinting it would fail by design. A nested `.git` isn't committed (git treats it\nas an embedded repo), so the repo ships the final-state working tree\n(`tests/fixtures/demo_repo/`) plus the builder script that recreates the full\nhistory on demand.\n\n---\n\n## Testing\n\n```bash\npython -m pytest            # 35 tests: unit + CLI end-to-end (green)\npython -m ruff check .      # lint (src + tests) — green\npython -m ruff format --check .   # formatting — green\n```\n\nTests cover the diff parser, changelog categorization, each reviewer pass, and\nthe full CLI via `typer.testing.CliRunner` against the real built demo repo\n(the `demo_repo` fixture in `tests/conftest.py`).\n\n---\n\n## Troubleshooting\n\n| Symptom | Fix |\n| --- | --- |\n| MCP server shows `⏸ Pending approval` | Approve it in your session, or `claude mcp reset-project-choices` and re-approve |\n| MCP server shows `✘ Failed to connect` | `claude mcp get filesystem` for the failure detail; make sure `npx` is on PATH and you have network on first run |\n| MCP tools not visible | `.mcp.json` is read at **session start** — restart Claude Code after editing it |\n| `spawn ... ENOENT` for MCP/hooks | The `command` isn't on PATH — use the full path (e.g. `.venv\\Scripts\\python.exe`) |\n| Hook errors mention a subdirectory | Hook commands use project-relative paths — launch Claude Code from the repo root |\n| `pr-guardian: command not found` | The console script is created by `pip install -e \".[dev]\"`; or run `python -m pr_guardian.cli` |\n| `python` opens the Microsoft Store | Use the full path to your Python, or `py -3 -m ...` |\n\n---\n\n## Further reading\n\n- [Low-level design (LLD)](docs/design.md) — this README is the *what/how*; the LLD is the *how it works*: data structures, control flow, the AI-layer contract, and the testing strategy\n- [Claude Code docs](https://docs.anthropic.com/en/docs/claude-code/overview) — CLAUDE.md, agents, hooks, slash commands, skills\n- [Claude Code MCP](https://code.claude.com/docs/en/mcp.md) — `.mcp.json`, approval flow, troubleshooting\n- [MCP: build a server](https://modelcontextprotocol.io/docs/2026-07-28/develop/build-server.md) — the official `MCPServer` walkthrough (a great next step: turn PR Guardian's engine into custom MCP tools)\n- [Keep a Changelog](https://keepachangelog.com/) — the release-notes format\n"}