Borrowing it
Nothing to install: this file belongs to guimatheus92/pr-review. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/guimatheus92/pr-review/main/AGENTS.mdgit clone --depth 1 https://github.com/guimatheus92/pr-reviewWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/instructions/guimatheus92/pr-review/agents-md)<a href="https://agentmods.dev/instructions/guimatheus92/pr-review/agents-md"><img src="https://agentmods.dev/badge/instructions/guimatheus92/pr-review/agents-md/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/instructions/guimatheus92/pr-review/agents-md"><img src="https://agentmods.dev/badge/instructions/guimatheus92/pr-review/agents-md.svg" alt="Reviewed on agentmods" width="80" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.12863 | $0.12863 |
| Opus 5.5 | $0.05145 | $0.05145 |
| Sonnet 5.5 | $0.02573 | $0.02573 |
| Haiku 4.5 | $0.01286 | $0.01286 |
Grade A, and why
pr-review AGENTS.md scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 6d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Runs shell commandslowCapability
Expected in a hook, worth knowing in a rule or an instructions file.
- **No window, no orphan.** *(INV-HYG-04)* Every `node:child_process` call in `src/` passes `windowsHide: true`, and none passes `detached` (it voids `windowsHide` on win32) except the `--detach` launcher. A detached run How it starts
The opening of the file, as written. The whole thing — 135 lines — stays where its author put it; the contents beside it link to each section on GitHub.
pr-review
Generic, plugin-based PR review tool for GitHub, Azure DevOps, and GitLab, packaged as a plugin for Copilot CLI or Claude Code. Orchestrates parallel review passes — each one a skill applied by a generic agent — in a single agent session via the task tool (Copilot) / Task tool (Claude Code), retains every deduplicated finding locally, and posts every publication-eligible finding as a resolvable inline review thread (all findings by default).
Build & test
npm run build # tsc + esbuild → dist/cli.cjs
npm run test # node scripts/test.mjs → node --test over tests/**/*.test.ts (990 tests, ~15s — on Windows run it from Git Bash: PowerShell resolves `bash` to WSL and fails `tests/command-finder.test.ts`)
npm run test:mod # claude plugin test mods/live → the live mod's 35 kit tests, offline, ~8 s (needs Claude Code >= 2.1.287 on PATH)
npm run validate:mod # claude plugin validate → the module's hooks:/calls: lines; the calls line is its read-only contract
npm run build:watch # tsc watch (re-run `npm run bundle` for esbuild)
The bundle at dist/cli.cjs is the single-file distribution artifact. The slash command (commands/pr-review.md) finds it via $CLAUDE_PLUGIN_ROOT/dist/cli.cjs under Claude Code (falling back to ~/.copilot/installed-plugins/), locates the checkout whose git origin matches the PR URL (current dir, its subdirectories, then its siblings; a primary worktree beats a linked one), prints a project-skill count that approximates the loader's rule, and runs node "$CLI" review $ARGUMENTS.
Architecture
Two-layer model: slash command → Node CLI → single agent session (Copilot CLI or Claude Code) dispatching review passes as generic agents (subagent_type/agent_type general-purpose) via task() / Task().
src/cli.ts— commander entry, subcommand routingsrc/commands/review.ts— gather → selection → planned delivery → complete-only dedupe/post. Schema-v1--resumevalidates HMAC authority, PR identity, execution-mode transition, and hashes before targeted recovery (a live PR must still be open only to publish); legacy consolidated output keeps replay support, while legacy Phase 1 is diagnostic-only.src/commands/status.ts/src/commands/detach.ts— authenticated live/recoverable/terminal status plus detached execution. Exit 21 means targeted recovery is possible; exit 22 is terminal.src/dispatch/single-session.ts— materializes context/pass/companion files and an immutable plan, emits deterministic named dispatch-only task calls, adopts uniquely identified missing Copilot sidecars, promotes attempt outputs, performs one automatic selective recovery, assembles Phase 1/final output in Node, and runs a direct conditional verifier.src/dispatch/delivery.ts/src/dispatch/runtime-events.ts/src/util/atomic-json.ts/src/util/control-auth.ts/src/util/finalization-lease.ts— strictFinding[]delivery, bounded top-level Copilot JSONL parsing, missing-only create-once adoption, atomic create-only canonicals, authenticated started/completed/spawn-rejected attempt lifecycles, requested/resolved model and composed runtime-error evidence, attempt ceilings, digests, non-mutating control reads, Windows transaction-safe state, HMAC authority, and one recoverer/finalizer/poster per run.src/dispatch/runtime.ts— runtime selection (resolveRuntime, runtimeSpawnArgs, taskCall, normalizeModel);--runtime copilot|claude|auto(default auto: probes PATH, copilot first). Planned sessions add the materialized run dir while denying posting paths. Copilot removes shell aliases from the visible tool surface, requests non-streaming JSON output, and runs withCOPILOT_PLUGIN_DIR_ONLY=true(1is ignored by Copilot CLI 1.0.84-3); Claude keeps its explicit tool allowlist. MCP is denied at the PROCESS level, not only the tool level — denying themcp__*tools alone still lets every server boot (acmd.exe+conhost+npx+nodeeach on win32, every console window leaking) only to be unreachable.MCP_PROCESS_DENIAL: Record<Runtime, string>holds the per-runtime switch, so a new runtime fails to compile until it declares one. The two are NOT symmetric: claude's--strict-mcp-configis categorical (every config source ignored, and no--mcp-configis passed, so the run-dir.mcp.jsonis inventory/provenance only — no runtime loads it); copilot's--disable-builtin-mcpscovers built-ins and is completed one name at a time by--disable-mcp-server, so its reach is bounded bydiscoverMcpCapabilities.src/util/progress.ts/src/util/posted-marker.ts— the phase/heartbeat feed and posting idempotency guard. Schema-v1 decisions use authenticated authority;posted.markerin the run dir is diagnostic only.mods/live/hooks/register.js— the Claude Code mod (hooks module), declared by thehooksfield of.claude-plugin/plugin.jsonand deliberately NOT a roothooks/dir:claude plugin test <dir>takes the mod's folder and runs every*.test.tsbeneath it, so the repo root would drag the node:test suite in (observed: 60+the file did not load). Copilot's rootplugin.jsonnever names it, and Claude Code older than 2.1.287 ignores it. It is a READER of the run dir —progress.ndjson,reviewer-progress.ndjson(the per-reviewer timeline; the mod is its first reader in production),dispatch-plan.json,delivery-state.json,passes.json,error.txt— ticked once a second (the band redraws every tick) and re-read every second tick, each file only on a size/stamp change, neverstatus(which reaps). A run that died without a terminal phase (error.txt, newer than the last progress line) settles asfailedwith thepr-review status <id>hint; a file that exists but cannot be read is named on the band, never mistaken for a--context-onlypreview. It attaches only to a validated id (one path segment: no separator,.., leading./-or control character — an Azure DevOps id may hold a space) that exists under the runs root: the banner a--detachlaunch prints at the start of stdout (past thekey: valuelines the launch block prints first — the model composes that block fromcommands/pr-review.md, so their names, order and count vary: a live session addedcli: …, and a preamble pinned to two names missed the launch), a--resume <id>typed into the Bash tool, astatus <id>poll when nothing live is attached, or/pr-review-live— never adir:line or anything inside a foreground summary, because finding bodies are model output about PR content (a forgeddir:would have pointed$.fs.statat a UNC path). The slash command sendsnode "$CLI" review … --detachwith$CLIunexpanded, so the launch is keyed on the banner, not on the command text;mods/live/tests/live.test.tsruns that literal block, andtests/mod-surface.test.tspins it tocommands/pr-review.mdand the banner tosrc/cli.ts. The run dir is written by the CLI under the user's own account and is writable by the reviewer session itself, so the mod shows what it finds there and decides nothing from it —statusand the summary stay the authoritative readings. It draws the boxed band above the prompt (title and status, a bar with one stretch of cells per reviewer coloured by state, its legend, the counts, the sources — the PR label shortens below 96 and 64 columns, and under 7 rows of room the legend and the sources go), thepr-review-livepane (reviewers grouped under their source, one row each: state, time, short name, match kind) and the spinner suffix, registers/pr-review-live [run-id | off], strips control and Unicode format characters from every name and detail it shows, logs its own failures to the debug file only ($.ui.log … { to: 'debug' }), and stays inert whensession.startsaysisInteractive: false, because pr-review's ownclaude -previewer sessions load the user's plugins (only Copilot is isolated, INV-CTX-06). Its surface is pinned read-only bytests/mod-surface.test.ts, which also refuses a rewritten or mutated Bash event in the observer, any$alias, and a forbidden call on any receiver.src/dispatch/codex.ts— optional read-only Codex sibling; strict attempt-scopedFinding[]output and crash-safe attempt accounting (opt out:--no-codex)src/dispatch/line-snap.ts— snaps finding line numbers to the nearest valid diff line before postingsrc/dispatch/lockfile-digest.ts— the only code that knows thepackage-lock.jsonformat: reduces the two sides gather read (viaPrProvider.readFileAt) to aLockfileDigestand renders## Lockfile Digest; pure, never fetches (INV-FETCH-04's exception)src/dispatch/call-sites.ts— the## Call sitessection: names the declarations a diff touches and finds their references with one read-onlygit grepat the PR head (else local HEAD, named as such), bounded, never fetching (INV-CTX-07)src/providers/github.ts/azuredevops.ts/gitlab.ts— PR data fetchers + comment posters (GitHub inline comments go out as one review batch — ONE attempt,runPostowns retry because only it can reconcile — with per-comment fallback; GitLab posts per-discussion via plain fetch). Each one delivers a COMPLETE file list or says so: GitHub carries the PR'schanged_filesasPrMetadata.changedFileCount(itspulls/:n/filesstops at 3000 entries silently) and fetches no whole-PR text diff (pulls.getwith the diff media type 406s above 300 files, so it is unusable exactly on the PRs that would need it); Azure DevOps pages iteration changes to completion ($top=2000,nextSkip, a cursor that does not advance throws), drops folder entries before they can count toward the file guard, and synthesizes each patch from two whole-filegetItemcalls — which is why it, alone of the three, honours the content-narrowingoptsoffetchChangedFiles; GitLab mapschanges_count("N+"=changedFileListTruncated, because/diffsserves exactly the capped set)src/dispatch/parsers.ts— JSON / bracketed-markdown / section-header output parserssrc/dedupe.ts— Jaccard token similarity, strict/loose/off modessrc/config.ts— 5-level config merge (flags > env > repo yaml > global yaml > defaults)src/util/retry.ts— retry/backoff helper for transient posting errorssrc/packs/sync.ts/load.ts— skill packs: clone/pull configured git repos into~/.pr-review/packs/<name>/(fail-soft; >30 days withoutpacks syncwarns on every review) and load their skill files perinclude/excludeglobssrc/stack/linguist.ts/manifests.ts/detect.ts— stack detection: GitHub Linguistlanguages.yml(auto-downloaded to~/.pr-review/cache/, refreshed onpacks sync) tags changed files by language; dependency names parsed from manifests only when cwd's git origin is the PR's repo (identity viasrc/providers/identity.ts, so legacy*.visualstudio.comremotes match canonicaldev.azure.com); beyond the shallow root scan, changed manifests and manifests beside/above changed files are read, so a deeply nested project contributes its own dependencies; evidence stays categorized (canonical Linguist languages, ecosystems, full dependency names, dependency tokens, dependency groups) rather than collapsing into one tag bagsrc/dispatch/pass-select.ts— pass selection: project skills (repo/configured/forced) become shared CONTEXT in every pass (skills-project.md, never pass slots) — every match injects, no numeric cap, bodies inlined whole (no byte truncation); passes are ranked by EVIDENCE TIER — specific path glob > manifest-backed dependency/framework token > language-consistent type/manifest glob > exact stack tag (capMAX_STACK_PASSES=6) — plus EVERY baseline, which is contractual and rides on top of the total pass ceiling. A product guide cannot qualify from a bare language or a generic manifest alone, and product identity tokens must co-occur in ONE dependency group. Up to two installed-plugin passes may be admitted from repository/path/topic evidence. With no pack passes, project skills become the passes; overflow + unmatched + index-mode packs get materialized bodies referenced by digest-boundskills-index.mdshards.src/commands/packs.ts—packs list/packs sync/packs add/packs suggestsubcommandssrc/plugins/loader.ts— discovers skills from standard paths (.claude/skills,.claude/rules,.copilot/skills,.github/skills,.github/instructions,.agents/skills, plus the~/mirrors) and from configured dirs. Follows directory links (symlinks and NTFS junctions) ONE hop, in every discovery and configured dir: a link the PR added or changed (its path, or any parent of it, is in the diff) is refused BEFORE anything behind it is read and named as degraded coverage; a link met inside a linked directory is not followed. Under askillsroot a subdirectory is a skill only through<dir>/SKILL.md— a SKILL.md-less subdirectory is skipped (stderr warning when it holds.mdfiles), flat.mdfiles at the root are still skills, aREADME.mddirectory entry is never a skill;rules/andinstructions/roots recurse as before. Applies rule trust before same-name dedupe, and folds semantically identical mirrors silently while still warning on divergent same-name rules. It is the only walker for repo, personal and configured dirs (packs and installed plugins have their own):walkSkillDirs/loadFromDirinsrc/plugins/builtin.tswere removed because a second walker meant a second link policysrc/plugins/trust.ts— a rule file added or modified by the PR under review is UNTRUSTED input: it is dropped from both authoritative context and the on-demand index, and named as degraded coverage. Checks lexical AND real paths, so a changed later mirror cannot evict its unchanged counterpart; comparisons fold letter case and Unicode (NFC) on EVERY platform — win32-only folding let a PR committing.Agents/skillsbypass a macOS reviewer. Trust is by authorship, not location: content whose real path is outside the checkout is trusted when the PR did not author the link that reaches it AND the file is committed and clean in its home git repository (git ls-files+git status; aSKILL.mdalso needs its whole directory clean) — the same gate applies to every rule outside the checkout (linked, configured or personal), and a repository git cannot read is skipped, never trusted — on Windowsgit checkoutof a PR branch writes THROUGH an NTFS junction into the shared directory, so a planted file would otherwise become a trusted rule for every sibling repo's review. Untracked or modified files there are skipped and named; a directory under no git repository at all is trusted as the reviewer's local configuration (one stderr note per directory reached through a link). Nothing depends on one company's layout: any link, any discovery root, any OS, git or not. In-repo--skillfiles stay scoped and must live inside the checkout;--force-skillis the explicit overridesrc/plugins/installed.ts— host-agnostic discovery of installed plugins from their manifests, in BOTH runtimes: Copilot CLI (~/.copilot/installed-plugins/<marketplace>/<plugin>/) and Claude Code (~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/, whose generic discovery path is read frominstalled_plugins.jsonbecause several versions can sit side by side). It validates active roots selected by the runtime (Copilot'sconfig.jsonis JSONC; Claude'splugin list --jsonsupplies the enabledinstallPath, scoped to the reviewed directory bygovernsCwdincompanions.ts, whose manifest identity must match — the version is recorded, never adjudicated). Skills are namespaced<plugin>/<skill>; declared paths and symlinks are constrained to the plugin root. Also builds the MCP capability inventory (capabilities.json) from trusted repo config, user config, and plugin manifestssrc/providers/identity.ts— canonical checkout/PR identity:canonicalPrAuthoritynormalizes legacy<org>.visualstudio.com, encoded HTTPS paths, andssh.dev.azure.com:v3/<org>/<project>/<repo>onto one authority, including the ADO project so a same-name repo in another project can't supply manifests or rulessrc/util/git.ts—gitTopLevel(); the pipeline resolves the checkout root once so a run from a subdirectory still finds repo config and rules.gitOut()/gitZ()run read-only git and THROW on failure (a failed read is never an empty result); rule provenance and the gather's truncated-list completion both go through themsrc/plugins/companions.ts— detects installed companion plugins (pr-review-toolkit, code-review); copilot viacopilot plugin list, claude viaclaude plugin list --json, which supplies each entry's enabled status, exactinstallPath, and scope. That list is not cwd-filtered — run from one checkout it still reports every project-scoped install on the machine — sogovernsCwddrops entries whoseprojectPathis not the directory under review (containment,foldPath-folded: pr-review may run from a subdirectory, and the same project appeared twice differing only by drive-letter case). Reading the list as already-scoped turned an unrelated project's installs intoconflicting active installationsand silently dropped all 7 dispatches — and so did two records of the SAME project on different versions (Claude Code writes one per spelling,C:\…andc:\…, and updates only one of them), for 36 reviews in a week (#54). There is no conflict gate any more: every enabled record governing the directory under review becomes a root, the version string is never compared, andagreedDefinitionis the integrity check — it compares the whole definition FILE (frontmatter and CRLF normalized, before any criteria extraction), so identical files across roots dispatch and divergent files drop THAT companion only, naming every root with a digest. A record whoseinstallPathhas no manifest naming the plugin is named in the Degraded block and ignored while a sibling root dispatches. Each runtime has its own registry — installing under one leaves the other empty, and--runtime autoprobes copilot first, so the machine that has them under Claude Code only still dispatches zero companions. Detection failure isunknown, never "not installed";companionReviewerNames()is the single source of up to 7 planned identities. Supplied active roots are constrained to each plugin, every root must provide agreeing definitions, and an unterminated header or shell/network/acquisition/fan-out/posting directive fails closed. Frontmatter is stripped lexically because its metadata is not execution authority — and so is a## When to invokesection, which addresses the HOST that dispatches the agent, not the agent: the officialcode-reviewer.mdsays "Spawn this agent on the freshly written files" there, and scanning it as criteria refused the companion over prose describing its own call sites. Removed, not exempted, so nothing inside it reaches the dispatched agent either. A companion that cannot be materialized is degraded coverage, never fatal —materializeCompanionBriefsreturns failures instead of throwing, andrunReviewdrops that id frominstalledCompanionsBEFORE the planned roster is fixed (planning it and not dispatching it is what INV-DEL-01 reads as missing output, which would turn the degradation back into an exit 2). One bad plugin.mdused to abort a run holding nine healthy passes and five working companions. Onecompanion-brief-*.mdper identity is hash-bound into the plan. Every companion runs asgeneral-purpose;code-reviewkeeps only its materialized-diff criteria, never its nativegh/posting workflow — and those criteria have TWO marketplace wordings (CODE_REVIEW_SHAPES): theclaude-code-pluginsHIGH SIGNALblock, and theclaude-plugins-official0–100 rubric with its 80 cutoff, which is what Claude Code's default marketplace and a teamenabledPluginslist install (all 14 cached official versions). Matching only the first refused every official install for a month;tests/fixtures/code-review-command/holds both real files byte for byte, and a body matching neither is refused naming both. The Degraded line states the cost (0 of 7 companion reviewers dispatched,N reviewer(s) lost).formatWarningtakes the runtime because the install command is not portable: slash commands under claude,copilot plugin …shell commands under copilot (it has no/plugin), from marketplaceanthropics/claude-code— the largeranthropics/claude-plugins-officialcarries the same plugins but Copilot'smarketplace.jsonschema rejects it
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 6d ago Changed · +297 tokens per session 6413204a44ef
- 8d ago Changed · +6 lines · +1,290 tokens per session d50cc8a77a94
- 10d ago Changed · +2 lines · +427 tokens per session 6e01dab835d5
- 25d ago Changed · +1 lines · +671 tokens per session 7d84f4778154
- 1mo ago Changed · +1 lines · +292 tokens per session 653d2cce1372
- 1mo ago Changed · +1 lines · +639 tokens per session b90e6f072095
- 1mo ago Changed · +282 tokens per session 030a04ff05b8
- 1mo ago Changed · +22 lines · +2,203 tokens per session 44efa77f448c
- 1mo ago Changed · +1 lines · +870 tokens per session b15d862e5fae
- 1mo ago First seen · 101 lines · 5,892 tokens per session scan A d97666e1a4ea
pr-review AGENTS.md is an instructions file published in the GitHub repository guimatheus92/pr-review (3 stars, last pushed 6d ago), licensed MIT. It adds 12,863 tokens to every session, about $0.0515 per session on Opus 5.5. A static security scan graded it A with 1 finding (runs shell commands). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other instructions, from other repositories
vscode buildNext.instructions.md
Working notes and architecture documentation for the new esbuild-based build system in build/next. Use when making changes to the new build pipeline (transpile/bundle commands, NLS plugin, source-map handling, resource copying, or self-hosting watch tasks).
next.js AGENTS.md
AGENTS.md instructions for vercel/next.js, covering next.js development guide, codebase structure, monorepo overview, core package: packages/next and other important packages.
vscode oss-third-party-notices.instructions.md
Instructions for microsoft/vscode, covering vs code oss third-party-notices pipeline, architecture, pipeline flow in ci, cache eligibility and rollout and applying the notice (cutover).
langchain AGENTS.md
AGENTS.md instructions for langchain-ai/langchain, covering global development guidelines for the langchain monorepo, corridor security analysis, project architecture and context, monorepo structure and development tools & commands.
deepseek-harness AGENTS.md
AGENTS.md instructions for deepseek-ai/deepseek-harness, covering agents.md, pre-stable apis and released session data, repository layout, commands and host sandbox failures.
vscode copilot-instructions.md
Copilot instructions for microsoft/vscode, covering vs code copilot instructions, project overview, root folders, core architecture (src/ folder) and built-in extensions (extensions/ folder).