npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

peer-ai

v1.0.0-next.19

Published

Keeps AI coding tools to a senior team's standard: planning, testing, security and compliance, with proof of every check

Readme

peer-ai

Keeps AI coding tools to a senior team's standard: planning, testing, security and compliance, with proof of every check.

This package is Peer AI's command-line tool and its MCP server, the connection AI tools use to follow Peer AI's way of working. It works with Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI and any tool that reads AGENTS.md. To learn what Peer AI does for a project, read the project's README.

Pre-release. Needs Node.js 24 or newer, on macOS, Linux or Windows.

Start

In your project's folder:

npx peer-ai init
npx peer-ai assess
npx peer-ai render

Then open the project in your AI tool and ask for work in plain words. In a Node project, you can pin the version instead, and your AI tools then start that copy:

npm install --save-dev peer-ai

Updating

In the project's folder, on a branch:

npx --prefer-online peer-ai@latest render

peer-ai doctor, and through it your AI tool at the start of each session, says when a newer release is out (RFC 0014). It moves every file it wrote to the new version, and says which version it moved from, with a link to what changed. Review the change, commit it and merge it. In a project with peer-ai in its package.json, update it there and install it, then run npx peer-ai render.

An update pull request

With "updates": { "pullRequest": true }, on GitHub Actions, render writes .github/workflows/peer-ai-update.yml (RFC 0014). Once a day, and on demand, it compares the version the project pins with npm's latest. When a newer one is out, it runs npx peer-ai@<latest> render on a branch, peer-ai/update-<version>, and opens a pull request, "Update Peer AI to ", with a link to what changed. It does nothing while one for that version is open.

  • It asks for contents: write and pull-requests: write, in its one job, and keeps no credentials on disk.
  • CI doesn't start on a pull request opened with the workflow's own token, which is GitHub's rule. Add a PEER_AI_UPDATE_TOKEN secret, a GitHub App's token or a fine-grained token that can write contents and pull requests, and CI runs by itself. Without one, the pull request says to close and reopen it, which starts CI.
  • A project with peer-ai in its package.json gets no workflow: Dependabot or Renovate update it there, with its lockfile. Run npx peer-ai render after merging one.

Updating while agents work

CI runs the new version as soon as the change merges, but an AI tool's MCP server keeps the version it started with, and an agent's branch keeps the files of the version it was cut from. So:

  1. Let running agents finish, or pause them at a commit.
  2. Update and merge, as above.
  3. Reconnect each AI tool to Peer AI, or restart it, right after the update merges, so its server and skills come from the new version. A tool still running the older version may not read a config written for the newer one; its tools then say to reconnect, naming the version. An agent working on a branch of its own merges the main branch first, so its files name the new version too.
  4. Resume. next_work tells any agent whose server is still on the old version, and peer-ai doctor says the same from a terminal (RFC 0011).

Commands

| Command | What it does | |---------|--------------| | peer-ai init | Sets up Peer AI in a repository: one config file, from what it detects | | peer-ai migrate | Moves a project from its copy of v0 onto Peer AI 1.0 | | peer-ai assess | Maps what the project has and what its stage still needs | | peer-ai render | Connects each AI tool: instructions, the MCP server and the skills | | peer-ai doctor | Checks the setup and says how to fix what isn't right | | peer-ai check | The CI gate: fails when work claims more than its record shows | | peer-ai check-report | Checks a review's report, as the record_review tool does | | peer-ai check-document | Checks a document against its skill's template | | peer-ai feedback | Lists, sends or drops the feedback drafts your AI tool wrote about Peer AI | | peer-ai ship | Moves a work item to ship, taking CI's verify when the config names its check, or says exactly what's missing | | peer-ai waive <id> <skill> --reason <why> --by <who> | Records a person's decision that a work item doesn't need a review it was asked for; peer-ai check lists every waiver (RFC 0016) | | peer-ai work show <id> [--full] | Shows a work item, open or closed; with --full, a closed item's full record, read from git (RFC 0017) | | peer-ai work move <id> <track> | Moves a work item to another track, as when its own is retired (RFC 0017) | | peer-ai tidy | Moves closed work items into the history, and removes reports of items that are gone | | peer-ai close-merged | Closes the open work items whose branches are already merged, saying how | | peer-ai mcp | Starts the MCP server that AI tools connect to |

peer-ai init

Sets up Peer AI in a repository by writing peer-ai.config.json.

npx peer-ai init

It reads the repository first and works out what it can:

| It finds | From | |----------|------| | The project's name and description | The project's own file, such as package.json, pyproject.toml, Cargo.toml, go.mod, composer.json, pubspec.yaml or settings.gradle, else the folder name | | Whether the project is new or existing | Code and project files at the root | | Each part and its stack | The repository root and every folder under apps/, packages/, services/ and libs/. It recognises JavaScript and TypeScript frameworks (including Express, NestJS and Fastify backends), Python, Flutter, Android, the JVM, .NET, Swift, Go, Rust, Ruby, PHP and Elixir, and names the backend framework where there is one. | | Infrastructure as code | Its files, wherever they are: Terraform or OpenTofu, Pulumi, AWS CDK, Helm, Kustomize, Serverless, AWS SAM, CloudFormation, Bicep and Ansible. Folders such as infra/, deploy/, k8s/ and helm/ are searched up to five levels deep, and there Docker and Kubernetes files count too. A docker-compose.yml at the root is local development, not infrastructure. | | Where each part deploys | A platform's config file in that part's folder: Vercel, Netlify, Fly, Render, Railway, Cloudflare Workers, Firebase, AWS Amplify, Expo EAS, Serverless, Heroku, Google App Engine, fastlane, or a Dockerfile for a container | | Existing CI | GitHub Actions, GitLab CI, Jenkins, Bitbucket Pipelines, Azure Pipelines, CircleCI, Buildkite, Drone, Travis, Cloud Build, Codemagic and Bitrise. Peer AI then extends that pipeline and never adds a second one. | | The AI tools already set up | CLAUDE.md, .cursor/, .codex/, .github/copilot-instructions.md, GEMINI.md | | The git host | The origin remote |

Then it asks five things: what you're building, whether the parts it found are right (or what kind of thing it is, if it found none), whether it's just you or a team, what stage the project is at, and which open findings in a review block a merge: critical only, or critical and high, suggested for a product in production (RFC 0015). It asks which AI tools you use only if it found none.

It takes up what assess suggests. Once it knows the parts, init works out what assess would suggest: the stack profiles that fit each part's stack, and the traits the code points to, such as money for a payment provider. It shows each one with why, all ticked, and adds them to standards.profiles and project.traits unless you untick them. For any you untick, it asks why, and records it in declined, so they aren't suggested again. --yes takes them all. peer-ai doctor warns about a suggestion the config has neither taken up nor declined (RFC 0011). Since an existing codebase starts at report, as below, taking up a profile doesn't turn its CI red.

For an existing codebase, it sets standards.enforcement to report, so Peer AI's enforcement reports what it finds without failing a build until the codebase catches up; a new project enforces from the start (see Adopting enforcement in stages).

It never overwrites an existing peer-ai.config.json, and it never assumes anything it didn't find. A project with nothing to detect gets a part of kind other until you decide. A project with no infrastructure or CI yet simply has none in its config; peer-ai assess records those as gaps to fill when the project's stage calls for them.

Options

| Option | What it does | |--------|--------------| | -y, --yes | Accept what it detects instead of asking. Needed when there is no terminal, for example when an AI agent runs it. | | --dry-run | Print the config instead of writing it | | --name <name> | The project's name | | --stage <stage> | prototype, mvp or production | | --team <team> | solo or team | | --tool <tool> | An AI tool you use; repeat it for several |

Exit codes

0 success, 1 refused (a config already exists) or cancelled, 2 a usage error.

peer-ai migrate

Moves a project from v0, when Peer AI was a playbook copied into a peer-ai/ folder, onto the package (RFC 0008).

In the project's folder:

  1. Commit or stash any work in progress. migrate won't start with uncommitted changes, so the move is a change of its own.
  2. Make a branch: git switch -c peer-ai-1.0
  3. See the plan, changing nothing: npx peer-ai migrate --dry-run
  4. Migrate: npx peer-ai migrate. It asks the same few questions as init, already filled in from what it found. Like init, it takes up the profiles and traits assess suggests unless you say no, and starts an existing codebase's enforcement at report.
  5. Review the change, and commit it on the branch. To undo it instead: git stash --include-untracked.
  6. Make the decisions on the same branch, before it merges. Your AI tool brings up each decision migrate left in docs/peer-ai-migration.md, through the work item migrate-v0. Go through them together, then delete the file. v0's instructions often held the project's own rules too, such as how work reaches the main branch, so this is where they come back; merged without them, the main branch would lose them.
  7. Verify migrate-v0, run the reviews it needs, and move it to ship, as for any work item. Then open the pull request: Peer AI's gate, which render just added, holds the branch to its work item.
  8. On GitHub, make peer-ai check a required check, so nothing merges without the gate.

It converts what it can read with certainty:

| From v0 | Into | |---------|------| | The Project settings table in the workflow driver | commands.verify, tracker, repo.branchNaming, repo.mergePolicy and design.reference | | phase-config.json | models, each skill's add-ons and notes, and each activity's notes. A phase that says a part is dormant marks it dormant. | | Markdown files in docs/standards/ | standards.documents, as standards or an addendum, each scoped to its part | | .peer-ai-state.json | A work item for each ticket in progress. The tracker keeps the rest. |

Then it deletes the peer-ai/ folder and the state file, takes v0's text out of CLAUDE.md, AGENTS.md and the other instruction files, maps the project and sets up the AI tools, as assess and render do.

Nothing is dropped silently. Whatever needs judgement, it copies word for word into docs/peer-ai-migration.md: the files the project edited in peer-ai/, the text it took out of the instruction files, the settings it couldn't place, and anything it left alone that still names v0. A work item, migrate-v0, on the migration's branch, points there, so your AI tool brings each decision up before the branch merges.

It tells the files the project changed from v0's own by their fingerprints: a list of every file in every v0 version, which ships with the package.

It never commits. It won't start with uncommitted changes, so the migration is a change of its own: review it, commit it on a branch, and open a pull request. git stash --include-untracked undoes it all. It deletes only files git can bring back, leaves files git ignores where they are, and refuses to write outside the project.

Options

The same as init. With --dry-run, it prints what it would convert, rewrite, delete and leave for a decision, and changes nothing.

Exit codes

0 success, 1 refused (a config already exists, there is no v0 copy, the project isn't in git or has uncommitted changes) or cancelled, 2 a usage error.

peer-ai assess

Maps what a project already has, and what its stage still needs. Run it on any project, at any point: a brief with no code, a prototype, or a product in production with no documents at all.

npx peer-ai assess

For each item on the project map it records one of four statuses, with the files that prove it:

| Status | Meaning | |--------|---------| | ✓ present | Found, with the evidence listed | | ◐ partial | Some of it is there, for example tests in two of three parts, or linting with no written standard | | ✗ missing | Not found | | – not applicable | This project can't have it, for example a design for a project with no user interface |

The items are the requirements, architecture, threat model, specs, API contract, data model, data inventory, DPIA, design, standards, CI, environments, tests, load testing, infrastructure, observability, SLOs, runbooks and docs.

Documents are a by-product, never an entry fee. When there is no architecture document, assess works the architecture out from the code and marks it inferred, for you to confirm. The same goes for anything it judged not applicable.

Then it ranks the gaps by the project's stage (the stage in peer-ai.config.json, or mvp when there is no config):

  • prototype: nothing is required.
  • mvp: requirements, API contract, CI, tests, threat model, data inventory and docs.
  • production: all of those, plus the architecture, specs, data model, DPIA, design, standards, environments, infrastructure, observability, SLOs, runbooks and load testing.

It also reports what the next stage will need, so nothing arrives as a surprise.

Documents that may no longer hold

A document counts as evidence once it's judged, not just because it exists (RFC 0018). Using git and the files, with no AI involved, assess flags a document, or a folder of them, that is:

  • stale: unchanged for 90 days, while its part has had 50 commits since, or a quarter of its part's files have changed. Its part is the track that holds it, or the whole project.
  • a duplicate: byte-for-byte the same as another document in the evidence. Only the first counts.
  • about something gone: it names, in a code span or a link, a path the project has deleted, or a part that's retired.

Each flagged document stays in the evidence, listed under flagged in the map with why. An item whose evidence is all flagged is partial, not present, so next_work offers its document skill to bring it up to date.

A document meant to stay as it was, such as a record of a decision, can be listed in docs.settled, as a file or a folder. It's never called stale or about something gone:

{ "docs": { "settled": ["docs/decisions/"] } }

Being stale and naming a deleted path both need the project's history, so in a shallow clone only duplicates are flagged. The CI gate that render sets up fetches the whole history. Since staleness depends on time, the map can fall out of date with no commit at all; peer-ai check then warns, and never fails.

Compliance signals

assess reads the schema and migrations for personal data (emails, phone numbers, dates of birth, addresses, national ID numbers and more) and card-related names, and the dependency manifests for payment providers. It reports them as things to check, not as findings, and suggests the rule packs to consider, such as PCI DSS or the data protection law where you operate.

Traits to consider

A trait says what the product is or does, and switches on the rules for it (see peer-ai-standards). assess suggests the traits the code points to, each with what it found, and leaves out any the config already declares or has declined. A person decides: add the ones that fit to project.traits, and list the rest in declined, with why. init and migrate take them up unless you say no (see peer-ai init).

| Trait | Suggested by | |-------|--------------| | money | A payment provider, or card-related names in the schema | | safety-critical | Names such as allergens, medication or dosage in the schema | | several-audiences | Two or more apps sharing a backend, or names such as tenant_id or organizationId in the schema | | offline | A service worker, or an offline or on-device database library such as Workbox, Dexie, WatermelonDB or sqflite | | real-time | A live-connection library such as Socket.IO, a WebSocket library, Pusher, Ably or SignalR | | uploads | An upload library such as Multer, python-multipart, Uppy or an image picker | | ai-features | An AI model SDK such as OpenAI's, Anthropic's, the Vercel AI SDK, LangChain or Gemini's |

Stack profiles to consider

A stack profile says how to follow the core rules in one stack, and which tool enforces each automatic rule (RFC 0006). assess suggests the most specific profile for each part's stack, such as react-native for a part tagged expo, which brings React and TypeScript with it. It leaves out profiles the config already lists or has declined. Add the ones that fit to standards.profiles, and list the rest in declined, with why.

A listed profile applies to every part that names no stack, so assess also suggests a stack for each track that has none, from what it detects.

What it reads

The files git tracks, plus new files git doesn't ignore, so .gitignore is respected. Outside a git repository it walks the folder and skips dependency and build folders such as node_modules/, .venv/ and dist/. A copy of the v0 playbook in peer-ai/ is left out, and the report says so.

It writes the result to .peer-ai/map.json, which agents read to know where the project stands. Commit it.

Options

| Option | What it does | |--------|--------------| | --target <stage> | Assess against a stage other than the project's own, for example --target production to see what launch needs | | --json | Print the project map as JSON instead of the report | | --dry-run | Print the report without writing .peer-ai/map.json |

Exit codes

0 success, 2 a usage error or an invalid peer-ai.config.json. Gaps are not errors: assess maps, and peer-ai check is the command that fails a build.

peer-ai render

Sets up each AI tool listed in tools in peer-ai.config.json, so every tool works the project the same way.

npx peer-ai render

| Tool | Instructions | MCP server registration | |------|--------------|-------------------------| | Claude Code | A block in CLAUDE.md, unless it imports AGENTS.md | .mcp.json | | Codex | A block in AGENTS.md | Codex keeps servers in your own config, so render prints the codex mcp add command to run once. Codex asks before run_verify runs the project's verify command; render prints the setting that allows it without asking, if you choose to. | | Cursor | .cursor/rules/peer-ai.mdc, a rule that always applies | .cursor/mcp.json | | GitHub Copilot | A block in .github/copilot-instructions.md | .vscode/mcp.json | | Gemini CLI | A block in GEMINI.md, unless it imports AGENTS.md | .gemini/settings.json |

AGENTS.md gets the block whenever a tool other than Claude Code is listed, when it already exists, or when CLAUDE.md imports it.

The CI gate

Render sets up peer-ai check in the project's CI, so no one has to remember to (RFC 0009):

  • On GitHub Actions, it writes .github/workflows/peer-ai.yml: one job, peer-ai check, that checks out the pull request's own commit with its history, installs Node 24 and runs the exact version of Peer AI render ran as, so it works with or without a package.json. Its actions are pinned to commits. Render keeps the file up to date while it's as render left it, and leaves it alone once someone changes it by hand; doctor then checks it still runs the gate. A version bump updates it.
  • It skips draft pull requests, and runs when one is marked ready for review (RFC 0021). A draft can't merge, so nothing gets through, and the gate's red on a pull request always means one that's meant to merge isn't ready. The instructions render writes say to open a pull request as a draft until its item reaches ship. To run the gate on drafts too, set "gates": { "drafts": "check" }.
  • On any other CI, it prints the step to add.
  • When a workflow of the project's own already runs peer-ai check, it adds nothing.

Make peer-ai check a required check in the repository's settings, so nothing merges without it. To run the gate some other way, set "delivery": { "gate": false }.

Letting CI's verify count

A project whose CI already runs its verify command on every pull request can say which check does it, so nobody runs a slow verify again on a laptop (RFC 0013):

"commands": { "verify": "make check", "verifyCheck": "ci / check" }

verifyCheck is the check's name as GitHub shows it on a pull request. With it set:

  • run_verify with from: "ci" reads that check's result on the item's latest commit that changed anything outside .peer-ai/, pushed, and records it with a link to the run. A commit that only records reviews or a verify leaves the code as CI tested it, so its result carries across.
  • Moving an item to ship, with advance_work_item or peer-ai ship, takes CI's result itself when the item's verify is missing or older than its latest commit, and says what's still missing: a review to run, or the check still running.
  • peer-ai check confirms it with GitHub, so a record claiming a CI run that didn't pass fails the gate. Render gives the gate's workflow checks: read and the run's token for that.

It needs GitHub, and gh signed in where the AI tool works.

Your CI can skip Peer AI's records. Since CI's result carries across commits that change only .peer-ai/ (#247), your own CI needn't run again for them. Keep the job running, so a required check still reports, and skip its work when the push changed nothing else:

- id: changes
  run: |
    before="${{ github.event.before }}"
    if [ -n "$before" ] && [ "$before" != "0000000000000000000000000000000000000000" ] \
      && git diff --quiet "$before" HEAD -- . ':(exclude).peer-ai'; then
      echo "code=false" >> "$GITHUB_OUTPUT"
    else
      echo "code=true" >> "$GITHUB_OUTPUT"
    fi
- if: steps.changes.outputs.code == 'true'
  run: make check

On a project of several parts, the code output of the workflow below says the same without a checkout. The checkout needs fetch-depth: 0, or enough history to reach the previous push. Avoid paths-ignore for this on a required check: GitHub leaves a check it skipped that way waiting, which blocks the merge. Leave Peer AI's own gate running on every push: the records are what it checks. The security pipeline render writes does this itself: each scan's job runs on every push, and skips its scan when the push changed only .peer-ai/ (RFC 0021). With verifyCheck, the instructions render writes say to push the change, let CI run, then record the reviews and the verify from CI together, in one push.

Running each check only for what changed

On GitHub Actions, a project of two parts or more gets .github/workflows/peer-ai-changes.yml (RFC 0022): a workflow your own workflows call first, so each job runs only for the changes it can apply to (DEL-13). It asks GitHub's compare API what the pull request or push changed, with the run's own read-only token and no checkout. Its outputs say:

  • One for each part, named by the part's id: true when a file in its folder changed, or in a part it uses. A file belongs to the part whose folder holds it most closely, as everywhere in Peer AI.
  • code: true when anything outside .peer-ai/ changed.
  • other: true when anything outside every part changed, such as the root's settings.

When it can't tell, on a schedule, a branch's first push, or when GitHub can't be asked, every output is true, so everything runs.

permissions:
  contents: read
jobs:
  changes:
    uses: ./.github/workflows/peer-ai-changes.yml
  api-tests:
    needs: changes
    if: needs.changes.outputs.api == 'true' || needs.changes.outputs.other == 'true'
    runs-on: ubuntu-latest
    steps: …

A job skipped by its if reports success, so a required check never waits; a workflow skipped by a paths filter leaves it waiting. Render keeps the file in step with the parts while it's as render left it, and never edits your own workflows. A part named code or other gets no output of its own. doctor warns about a part's jobs that run on every pull request, a deployment on pull requests, and runs left going after a newer push; Peer AI's own workflows cancel a pull request's run a newer push replaced.

A section for people in the README

With "docs": { "readme": true }, render keeps a section in the project's README.md, between <!-- peer-ai:readme:start --> and <!-- peer-ai:readme:end -->, for the people who work on it, including those who don't use an AI tool (RFC 0014).

  • "How we work: Peer AI" opens with three short lines: what Peer AI does here, that nobody needs to install it, and npx peer-ai doctor.
  • The details are folded into <details> sections, so readers scan the headings and open what they need:
    • the project's stage, and what it asks for;
    • what a pull request needs;
    • the checks that enforce the standards, with any rules deferred;
    • how updates work.
  • It's written from the config, so it stays true as the config changes, and nothing outside the markers is touched. Without a README.md, render starts one.
  • To stop render from keeping it, set docs.readme back to false. The section stays as last written, for the project to edit.

Instructions

The instructions are short: how to work through the MCP server, the project's parts, its commands, its compliance packs and its own rules, and the project's settings for models, skills and activities when it has any: the models to use, the add-ons, checklists and notes for each skill, and the files to read and notes for each activity. The server serves the detail when it's needed, rather than every rule on every turn.

Skills

Render writes Peer AI's skills where the listed tools read them, each named peer-ai-<skill>, such as peer-ai-security-review. The prefix means a Peer AI skill never replaces one of a tool's own, such as Claude Code's /code-review.

| Folder | Read by | Written when the config lists | |--------|---------|-------------------------------| | .claude/skills/ | Claude Code, Cursor, GitHub Copilot | Claude Code | | .agents/skills/ | Codex, Cursor, GitHub Copilot, Gemini CLI | Codex, Gemini CLI or another tool; or Cursor or Copilot without Claude Code |

  • They stay out of git. They're rebuilt from the installed version, so a version bump stays a one-line change. Render adds them to .gitignore in a marked block.
  • After cloning, run peer-ai render to write them. In a Node project, a prepare script can do it on install. peer-ai doctor warns when they're missing or out of date.
  • Only its own skills. Render replaces and removes only folders named peer-ai-…. A skill of your own sits beside them untouched.
  • Cloud agents start from a fresh clone, so render gives each one a setup step that writes the skills before it starts: peer-ai render --skills --quiet, which touches nothing committed.

| Tool | The setup step | |------|----------------| | Claude Code | A SessionStart hook in .claude/settings.json. It runs in cloud sessions and routines too, and keeps skills fresh on your machine after an upgrade. | | Cursor | Added to the start command in .cursor/environment.json | | GitHub Copilot | A step in .github/workflows/copilot-setup-steps.yml. An existing workflow is left to you, with the step to add. | | Codex | Codex cloud keeps its setup script in its own settings, so render prints the line to add there |

Each edit keeps everything else in the file, and updates only Peer AI's own command.

  • Committing them instead. Set "skills": { "commit": true } for a tool that can't run a setup step. Render then commits the skills, marks them as generated in .gitattributes so pull requests fold them away, and render --check checks them too.

What render changes, and what it leaves alone:

  • A block, not the file. It writes between <!-- peer-ai:start --> and <!-- peer-ai:end -->, and never touches anything outside them. A file without the block gets it at the end.
  • One server entry, not the config. It adds or updates the peer-ai entry and keeps every other server and setting. It refuses a file it can't read as plain JSON, such as one with comments, and prints the entry to add by hand.
  • The pinned version. When package.json has peer-ai in its dependencies, tools start that copy; otherwise they start this exact version with npx.
  • Nothing twice. A second run changes nothing. peer-ai doctor warns when these files or the skills no longer match the config.

Settings for the tools that enforce the stack profiles

  • ESLint reads Peer AI's settings from the peer-ai-eslint-config package, which your eslint.config.js spreads in. Render writes nothing for it.

  • Ruff reads settings from a file, so render writes .peer-ai/enforce/ruff.toml, with every Ruff rule of the project's profiles and its values. Your own Ruff settings extend it, such as extend = ".peer-ai/enforce/ruff.toml" under [tool.ruff] in pyproject.toml, directly or through a shared file that extends it. Add rules of your own with extend-select: a select replaces Peer AI's rules instead of adding to them, and doctor fails it, as it does an ignore that drops one of Peer AI's codes. Commit the file, so CI's Ruff uses it; render --check fails when it falls behind the config. Ruff has no warnings, so a rule that only reports for now is left out of the file, and its header lists it.

  • The TypeScript compiler reads each part's own tsconfig.json, which render never edits.

  • The pipeline's checks, for a project listing the github-actions profile, run from .github/workflows/peer-ai-security.yml, which render writes. Each tool is a release checked against its checksum, or an image pinned to its digest:

    • peer-ai / secrets: Gitleaks, on a pull request's commits and on the whole history every day. A secret found in old history that's already been replaced goes in .gitleaksignore, with why.
    • peer-ai / dependencies: OSV-Scanner, on every lockfile and manifest it can read, on every change and every day. It warns when it finds none.
    • peer-ai / workflows: zizmor, on the workflows and any actions in the repository.
    • peer-ai / code: Semgrep, with its security rules for the common languages pinned to a commit of semgrep/semgrep-rules. Those rules are under the Semgrep Rules License, not an open-source licence.
    • peer-ai / tls: SSLyze, against Mozilla's intermediate profile, every day, for each environment with a url.
    • peer-ai / running-app: OWASP ZAP's baseline scan, every day, only in environments marked "production": false; one not marked might be production, so it's never scanned. Accept a finding in .github/zap-rules.tsv, with the reason. The reports are kept with each run.

    Make each job a required check in your branch protection once it enforces: their names never change. A job the project's own workflows already run is left out, as below. The file's header records a hash of what render wrote: while it matches, render keeps the file up to date; once someone changes it by hand, render leaves it alone, and doctor checks it still has every job.

Adopting enforcement in stages

An existing codebase rarely passes every rule on its first day, so Peer AI's enforcement can arrive in stages (RFC 0011), with every decision in peer-ai.config.json:

"standards": {
  "profiles": ["github-actions", "python"],
  "enforcement": "report",
  "deferred": [
    { "rule": "GHA-03", "until": "2026-11-02", "reason": "Workflow checks after the launch.", "decidedBy": "Ada Obi" },
    { "rule": "GHA-05", "untilItem": "SHOP-41", "reason": "Fix the known findings first.", "decidedBy": "Ada Obi" }
  ],
  "coveredBy": [
    { "rule": "GHA-02", "by": ".github/workflows/ci.yml", "reason": "Trivy scans the dependencies and fails on critical findings." }
  ]
}
  • enforcement is report or enforce. In report, the tools run and report but never fail a build: each check in the security workflow runs with continue-on-error, so its job stays green on a pull request and warns about what it found, in the job's summary; ESLint runs Peer AI's rules as warnings, and Ruff's settings leave Peer AI's rules out. init and migrate write report for an existing codebase and enforce for a new one. A config without the setting enforces, as before. Move to enforce once the codebase passes; no date moves it for you.
  • deferred holds back one rule's enforcement until a date, or until a work item is done, with why and who decided. Reviews and standards_for_file still apply the rule, so new code follows it; only its enforcement reports. A job that checks several rules reports while any of them is deferred, since one run of the tool checks them all. When the date passes or the item is done, the rule enforces again at the next render. A deferral is not an exception: standards.exceptions sets a rule aside entirely, reviews included.
  • To make some checks block while others keep reporting, don't stay in report: set enforcement to enforce, and defer the rules that aren't ready, each until the work item that fixes them. Lint can then fail a build while, say, the security workflow's findings are worked through. In report, doctor says how many rules are warnings or left out, so its other warnings clearing doesn't read as enforcement.
  • A check the project already runs isn't added twice. When one of the project's own workflows runs gitleaks, osv-scanner, zizmor, Semgrep, SSLyze or ZAP, render leaves that job out of the security workflow. A tool in a commented-out line doesn't count. When the project covers a rule with a different tool, coveredBy says so, with the workflow that does it and why, and render leaves it out the same way.

Render says what it wrote: for the security workflow, each job with the rules it checks, which only report, and what's covered elsewhere and by what. The workflow's header says when its jobs only report. doctor lists the stage, each deferral with its reason and end, and each check covered elsewhere. It warns a week before a deferral ends, and again once it has.

Options

| Option | What it does | |--------|--------------| | --check | Change nothing, and fail when a committed file is out of date. For CI. It leaves the skills out, since CI never has them, unless the project commits them. | | --skills | Write only the skills, touching nothing committed. It's what each tool's setup step runs. | | --quiet | Print nothing unless something fails |

Exit codes

0 done or up to date, 1 a file was refused, or is out of date with --check, 2 a usage error or no valid peer-ai.config.json.

peer-ai doctor

Checks that Peer AI is set up correctly in a repository, and says how to fix what isn't. It only reads; it never changes a file.

You rarely need to run it yourself (RFC 0007): peer-ai check fails in CI on anything doctor fails on, and your AI tool hears about every problem it finds through next_work at the start of each session.

npx peer-ai doctor

| It checks | A problem looks like | |-----------|----------------------| | Node.js | A version older than the one Peer AI needs | | Updates | A newer release of Peer AI than the project uses, with where to read what changed and how to update. npm is asked at most once a day per machine, with the answer kept in your cache folder, never in the project; offline and in CI it says nothing. "updates": { "notify": false } turns it off (RFC 0014). A warning, which reaches the AI tool through next_work. | | Peer AI's version | The Peer AI running isn't the version the project uses: the exact version in package.json, the one installed, or the one render pinned. An AI tool whose server is older is told to reconnect, through next_work; a project behind the version run is told how to move to it. A warning. | | peer-ai.config.json | Missing, or not valid, with each error | | Tracks | A track whose folder has moved or gone, or a part of the repository no track covers. A track with no path is the repository root, so a monorepo needs a track for each part, or one whose folder holds several. A dormant track may not have a folder yet. | | Files the config names | A contract, design, standards document, data inventory, checklist, input or workflow named in standards.coveredBy that doesn't exist. URLs, glob patterns and places still to be made, such as docs.dir, are left alone. | | AI tools | A tool set up in the repository, such as a CLAUDE.md or .cursor/, that the config doesn't list | | What render writes | Instructions or MCP registrations that no longer match the config, or skills that are missing or out of date | | CI | A config that says there is no CI when the repository has a pipeline, which would lead Peer AI to add a second one | | The CI gate | A pipeline that doesn't run peer-ai check, or a gate workflow that's out of date or no longer runs it. Through next_work, the AI tool hears about it in every session. | | Where CI runs its checks | In the project's own GitHub Actions workflows, a deployment on pull requests, a workflow on pull requests that doesn't cancel the run a newer push replaced, or, in a project of several parts, a part's jobs on every pull request with no condition on what changed, each named with its workflow and jobs (RFC 0022, DEL-13). doctor reads what a job is for from its environment, steps, folder and name, and can be wrong: a workflow meant that way is listed in declined, { "workflow": ".github/workflows/deploy.yml", "reason": "…" }, and isn't warned about again. Warnings only. | | The record | The work item of the branch checked out is still at prepare while its branch has commits, or its verify or a review looked at an older commit with changes since (RFC 0010). A warning, which reaches the AI tool through next_work. | | The project map | Missing, not valid, or out of date. It runs a fresh assessment and lists every item whose status has changed since .peer-ai/map.json was written. | | Work items | A file in .peer-ai/work/ that isn't valid or isn't named after its id. An open item on a track that's retired or no longer in the config is a warning, with how to move or cancel it: such an item stays valid, so cancelling it never fails (RFC 0017). | | Git | A folder that isn't a git repository, or a .gitignore that hides Peer AI's files from the team and CI | | What blocks a merge | A project in production whose gates.blockOn still lets high findings ship (RFC 0015) | | Rules set aside or changed | Every entry in standards.exceptions and standards.overrides is listed, so nothing is switched off silently. It warns about an exception whose until date has passed, a rule id that isn't one of Peer AI's rules, a rule set aside twice, and an override for a rule with no value to change, or of the wrong type. | | Suggested profiles and traits | A stack profile or trait assess suggests that the config has neither taken up nor listed in declined, with what suggested it (RFC 0011) | | Tidy state | Closed work items still in .peer-ai/work/, or report folders of items that are gone, with peer-ai tidy to move them into the history (RFC 0017) | | Merged items | Open work items whose branches are already in the default branch, or gone, as git alone can tell, with peer-ai close-merged to close them (RFC 0013) | | A part with no stack | While profiles are listed, a part that names no stack gets every listed profile of each file's language. It's named with the stack detection finds for it (RFC 0012). | | Stack profiles | A listed profile Peer AI has no rules for yet | | The tools that enforce them | For each part, that the ESLint config nearest it spreads in peer-ai-eslint-config, that the Ruff settings nearest it extend .peer-ai/enforce/ruff.toml, and that its tsconfig files, including those a solution tsconfig references, set what the compiler rules need; and that the pipeline's workflow is there, as render wrote it, and up to date. A warning, and a failure at production unless enforcement only reports or the rule is deferred. It lists the enforcement stage, each deferral and when it ends, and each check covered elsewhere, and suggests report to an existing codebase that hasn't chosen a stage (RFC 0011). | | The v0 playbook | A copy left in peer-ai/, with how to remove it |

Every check reports, including the ones it had to skip (for example, the tracks can't be checked without a valid config), so a clean report means everything was looked at.

A failure (✗) means Peer AI can't work as intended until it's fixed. A warning (!) is something to tidy up.

Options

| Option | What it does | |--------|--------------| | --json | Print the checks as JSON |

Exit codes

0 nothing failed (warnings are allowed), 1 at least one check failed, 2 a usage error.

peer-ai check

The gate CI runs. It fails when the setup is broken, or when a work item claims more than its record shows.

npx peer-ai check

| It fails when | Why | |---------------|-----| | The config is missing or not valid | Nothing else can be checked (exit code 2) | | A track's folder doesn't exist | The config no longer describes the repository | | .peer-ai/map.json or a work item isn't valid, or a work item names a track the config doesn't have | State that agents read has to be trustworthy | | A work item at ship or done has no recorded verify, or its last verify failed | commands.verify runs before any work is called done. Without a verify command, only a recorded failure counts. | | The work item of the branch checked out is at ship, and its verify or a required review looked at an older commit with changes since | A verify and a review each record the commit they looked at (RFC 0010). At ship the verify must be on the branch's latest commit, or on one with no change since outside .peer-ai/. A review must be on a commit with no change since to the files the branch itself changes, so a merge from the base branch that brings in only other files keeps it (RFC 0013). A record from before records named their commit counts until the item next moves to ship. | | A work item at ship or done has a review whose latest result failed, or is incomplete | A review that didn't check every rule hasn't passed. A later passing review from the same skill replaces an earlier failure. At the prototype stage, an incomplete review is allowed; a failed one never is. | | A production project's work item at ship or done has a review with no report | Without a report, the result is only the agent's word. For an MVP this is a warning; for a prototype it's allowed. | | A work item at ship or done is missing a review it needs | When an item reaches verify, Peer AI works out the reviews it needs from the files it touched, such as a security review for code at MVP or production. Missing one fails in production, and at the MVP stage for the work item of the branch checked out or one moving to ship (RFC 0010); for an MVP item finished before, it's a warning. activities.verify.reviews in the config can require more, or skip one with a reason. | | On a pull request, the work item on its branch isn't at ship or done yet | A change merges only once it's verified and reviewed (RFC 0010). check reads the branch from the pull request on GitHub Actions, or from --branch. A branch with no work item, such as a dependency update, passes, and says so; at the prototype stage it's a warning. | | A gap work item is at done, but a fresh assessment still finds the gap | The work didn't fill it | | A work item at ship or done depends on an item that hasn't shipped | Changes land in the order they depend on (RFC 0005). Building before a dependency ships is fine. | | A work item depends on an item that doesn't exist, or items depend on each other in a loop | The plan can't be followed |

It also fails on anything peer-ai doctor fails on (RFC 0007), listed under their own heading, so a setup that stopped working never passes CI unnoticed: for example, a production project whose linter no longer enforces its stack profile. Doctor's warnings don't fail the build; check counts them in one line. The skills are left out, since CI never has them.

It warns, and still passes, when:

  • the project map is out of date, so it should be assessed again and committed
  • the stage needs something that is missing and no open gap work item covers it
  • an MVP or production project has no verify command
  • whole-project reviews leave a critical finding open, which fails at production, or a critical or high finding is in no work item's fixes (RFC 0015)
  • a work item at ship or done has a review with high findings left open below the blocking level: "SHOP-1 is at ship, and its security-review is pass, 7 high open" (RFC 0015)

Gaps are never failures. They become work items, so a project can adopt Peer AI at any point without its build going red.

A review's result is worked out from its report when it is recorded, so an open problem at or above the project's blocking level (gates.blockOn) makes the review fail, and the work item can't ship until the problem is fixed or a person accepts the risk.

In CI

render sets it up: see the CI gate. By hand, it's a step after the project's own checks that runs, with Node 24, npx -y peer-ai@<version> check.

On GitHub Actions, it also writes what it found to the job's summary, which shows on the pull request's checks: each problem with its fix, so nobody has to read the log (RFC 0013).

Options

| Option | What it does | |--------|--------------| | --json | Print the checks as JSON | | --branch <branch> | The branch a pull request is for, whose work item must be at ship. On GitHub Actions, check reads it from the pull request. |

Exit codes

0 passed (warnings are allowed), 1 failed, 2 a usage error or no valid peer-ai.config.json.

peer-ai check-report

Checks a review's report the way the record_review tool does: that it's valid, gives every rule its skill answers for a line, and claims the result its findings and coverage support. It records nothing. It's there for AI tools that work in a shell rather than through the MCP server, and for a person checking a report by hand.

npx peer-ai check-report .peer-ai/reports/project/security-review-20261001T0900Z.json

| Option | What it does | |--------|--------------| | --skill <skill> | The skill the report is for. By default, the one the report names. | | --work-item <id> | The work item it's for, when there is one | | --json | Print the result as JSON |

Exit codes: 0 when the report passes, 1 when it doesn't, and 2 without a valid config or a report path.

peer-ai check-document

Checks a document a Peer AI skill wrote, such as the requirements, the way the check_document tool does: every required part of the skill's template is there and filled in, no template text is left in, and every rule id it cites exists. It changes nothing. It's there for AI tools that work in a shell, and for CI.

npx peer-ai check-document docs/requirements.md --skill requirements-analysis

| Option | What it does | |--------|--------------| | --skill <skill> | The document skill that wrote it. Required. | | --template <name> | Which of the skill's templates it follows, when it has several. By default, the main one. | | --json | Print the result as JSON |

Exit codes: 0 when the document is ready, 1 when it isn't or can't be checked, and 2 without a path or a skill.

peer-ai feedback

When Peer AI gets something wrong in your project, such as a review that misses a problem or a check that blocks work by mistake, your AI tool drafts a report with the draft_feedback tool and keeps it in .peer-ai/feedback/, out of git. You decide what happens to each one (RFC 0007).

npx peer-ai feedback
npx peer-ai feedback send 2026-10-02-check-blocked-a-merge.md
npx peer-ai feedback drop 2026-10-02-check-blocked-a-merge.md
npx peer-ai feedback prune

| Command | What it does | |---------|--------------| | peer-ai feedback | Lists the drafts waiting, with each title, then the reports already sent, each with its issue's state: open, or closed and when. The states come from GitHub through gh, in one call. | | peer-ai feedback send <draft> | Opens the draft as an issue on Peer AI's repository, labelled feedback, under your own GitHub account through the GitHub CLI, gh. The draft moves to .peer-ai/feedback/sent/ with the issue's link. Without a signed-in gh, it prints a link to a new issue with the report filled in, for you to submit. | | peer-ai feedback drop <draft> | Deletes the draft | | peer-ai feedback prune [--yes] | Removes the sent reports whose issues are closed, after listing them and asking; --yes doesn't ask. Open ones stay, and the issues stay on GitHub (RFC 0014). |

Your AI tool asks you about each draft at a natural stopping point, and runs send or drop only after you answer. When a new draft looks like a report this project already sent, by the words their titles share, draft_feedback still writes it, and its reply names the sent issue and its state, so the person can drop a duplicate, or check whether a closed one is fixed in the version the project uses. Nothing is ever sent without a person's yes, and a report never holds your code: Peer AI refuses a draft with a block of code, anything that looks like a key or a token, or an email address.

Exit codes: 0 done, 1 a draft that doesn't exist, 2 a usage error.

peer-ai ship

Moves a work item to ship from a terminal, as advance_work_item does for an AI tool: the item on the branch checked out, or the one named (RFC 0013).

npx peer-ai ship
npx peer-ai ship SHOP-41

With commands.verifyCheck set, it takes CI's verify of the latest commit first (see Letting CI's verify count). When anything is still missing, it lists each with how to get it, and changes nothing. Then commit the item's record and push it: peer-ai check on the pull request passes for it.

Exit codes: 0 at ship, 1 when something's missing, 2 without an item to ship.

peer-ai tidy

Since RFC 0017, a work item that's done or cancelled leaves the tree in that same change: its file and its reports are removed, and it becomes one line in .peer-ai/history/<year>-<month>.jsonl, with how it closed, its verify and reviews, and the last commit that held its full file. Git keeps the rest. work_item and peer-ai work show still read a closed item by its id, and peer-ai work show <id> --full reads its full file back from git. Items that depend on it, and findings it fixed, still count it.

peer-ai tidy does the same for a project that closed items before that:

npx peer-ai tidy

It lists the closed items still in .peer-ai/work/, and the report folders of items that are gone, then asks before moving and removing them; --yes doesn't ask. Whole-project reports in .peer-ai/reports/project/ are kept. Commit the change on a branch. peer-ai doctor warns while there's anything to tidy.

Recording a review again also removes the report it replaces, so an item keeps one report per review.

Exit codes: 0 done or nothing to do, 1 when you said no, 2 without a terminal and without --yes.

peer-ai close-merged

Closes every open work item whose branch is already merged into the default branch, such as work merged before the ship gate existed, or while peer-ai check wasn't a required check (RFC 0013). It doesn't need each branch checked out and verified again: the code is already merged.

npx peer-ai close-merged

It lists the items and how each was found merged, then asks whether to close all of them, choose one by one, or close none. --yes closes them without asking, except those named with --skip <id>, which can be given more than once (RFC 0020). Each item moves to done and records how: "closed": { "by": "merge", "commit": "…", "pullRequest": 214, "at": "…" }. Each record is written where the merge is: a working copy that holds the merged work and isn't on the merged branch, the main checkout first, so it reaches the default branch with your next pull request rather than one of its own (RFC 0020). With no such working copy, pull the default branch first. next_work lists records waiting to be committed, as unlanded.

An item can stay open after its merge, such as one merged before ship at the owner's request, with device checks still owed. update_work_item with keepOpen, a reason and who decided, records it on the item as openAfterMerge. close-merged and peer-ai doctor leave it alone, and list it as kept open, with why. Moving the item on clears it.

A branch counts as merged when:

  • its last commit is in the default branch, after a merge commit or a fast-forward, or its only commits after that are Peer AI's own records;
  • the default branch holds every file it changed as the branch left them, as after a squash or rebase merge;
  • or GitHub says its pull request was merged, asked through a signed-in gh, which also covers a branch that's been deleted.

An item still at prepare is never closed this way: a merged branch of its name is another item's.

peer-ai check accepts an item closed this way without a verify and reviews, and lists it, so the record stays honest about what it holds. With peer-ai check required, nothing merges before its item is at ship, so this closes only work that merged around the gate. advance_work_item to done does the same for one item when its branch is merged. peer-ai doctor warns when open items look merged, checking with git alone.

Exit codes: 0 when nothing needed closing or everything closed, 1 when you said no or an item couldn't be saved, 2 without a terminal and without --yes.

peer-ai mcp

Starts the Peer AI MCP server over stdio. Any AI tool that supports MCP servers reaches the same project map, work items and gates through it, so a project behaves the same whichever tool a person uses.

The AI tool starts it, from the project's folder or one inside it. For example, in a project's .mcp.json for Claude Code:

{
  "mcpServers": {
    "peer-ai": { "command": "npx", "args": ["peer-ai", "mcp"] }
  }
}

peer-ai render writes this registration for each tool in the config.

| Tool | What it does | |------|--------------| | project_map | Each item on the project map with its evidence, what the stage still needs, compliance signals and traits to consider. It assesses afresh on every call, and says whether the committed map has fallen behind. It also gives each review's rough size over the whole project, reviewSizes: the files, lines and rules in its scope, as small, medium or large with the token range that means, which a whole-project review tells the person before it starts (RFC 0016). | | next_work | Any setup problem peer-ai doctor finds (setup), each with its fix, for the AI tool to fix or tell the person about before other work. Then the open work item for the current git branch, or the branch given by an agent working in a worktree of its own, in full, with where it stopped, its next action and the reviews it needs. Every open item in one line: its id, title, stage, branch, part, next action, and the items it's waiting for before it can ship (waitingFor), at most 50, with more saying how many weren't listed (RFC 0012). When nothing is open, the gaps the stage needs, with the Peer AI skill to use for each (useSkill). At a person's first session after the project's Peer AI version changes, whatChanged lists what changed, a line per change from the changelog that ships with the package, for the AI tool to tell them once (RFC 0014). Open critical findings from whole-project reviews, and the critical and high ones no work item lists in fixes, come as projectFindings (RFC 0015). A required review asked for by a weak trigger, a few changed lines in files the change didn't add and nothing about routes, access or sessions, is marked depth: light: a review of the changed lines only (RFC 0016). When the current item's branch adds a migration, migrationCollisions names each other open item whose branch adds one in the same folder, since whichever merges second needs its migration re-parented, then reviewed again; for Alembic migrations on the same parent revision, it's certain (RFC 0018). Closed items whose records this working copy holds but hasn't committed come as unlanded, to commit with the next pull request (RFC 0020). On GitHub, each open item's pull request checks come too, read once through gh and kept for two minutes: the current item's as pullRequest, and each summary's as ci, passing, pending, waiting (only Peer AI's gate is red, because the item is short of ship) or failing, with which. A failing check is the item's next action: "Fix CI: integration-tests, on 4f2a9c1." (RFC 0020). | | work_item | One work item in full, by its id, found on its own branch wherever that's checked out. For an item next_work lists in one line. | | standards_for_file | Peer AI's rules for a file, each by its id, title and severity, chosen by what the file is (a CI pipeline, build file, infrastructure, dependency manifest, migration, test, document, tool settings or source code), its language, and the part it belongs to; with the stack profiles, and the project's own standards documents and rules for that part. ruleIds returns the full text of the rules asked for (RFC 0012). A rule a tool checks says whether that tool enforces it for the file's part, as doctor finds it (enforced), and why not (notEnforced) (RFC 0019). Working on a branch in a worktree of its own, give its branch: the file is judged by that working copy's config, parts and lint settings (RFC 0020). | | create_work_item | Starts a feature, bug, refactor, migration, discovery, chore or gap at prepare. Its id comes from tracker.ticketPrefix (or ITEM) unless a tracker key is given, and its branch from repo.branchNaming. It can carry its plan (RFC 0005): a goal, acceptance criteria, the sources it implements, and the items it depends on. | | update_work_item | Records the next action and the activity and step where work stopped, so the next session resumes there. It also sets the item's goal, acceptance criteria, sources and dependencies. After qa-acceptance finds a criterion not met, the criteria change only with a reason and who decided (by), which the item records (RFC 0015). It can move the item to another track, any but a retired one (RFC 0017). With waive, it records a person's decision that the item doesn't need a review it was asked for, with why and who decided; at production, only a light review can be waived (RFC 0016). With keepOpen, it records a person's decision that the item stays open after its branch merged, with why and who decided, which close-merged and doctor respect until the item moves on (RFC 0020). | | run_verify | Runs commands.verify where the item's branch is checked out, and records the result with the commit it ran on and the end of its output. It refuses while that working copy has changes not yet committed, since a verify proves a commit. Only this tool records a verify, so a pass is proven rather than claimed. With from: "ci", it runs nothing: it takes the result of commands.verifyCheck, the CI check that runs the verify, on the item's latest commit, pushed, from GitHub through gh, and records it with a link to the run (RFC 0013). | | record_review | Records a review from its report: Peer AI checks the report and works out pass, fail or incomplete from it, and refuses a result the report doesn't support, or a report that leaves out any of the skill's rules. A review recorded without a report is marked unproven. It takes reports only from .peer-ai/reports/, records the commit the review looked at, and replaces an earlier review from the same skill. For a review of the whole project, leave out the work item: Peer AI checks the report the same way and gives its result, without recording it. The result is recorded and shown with how many findings it leaves open at each severity, such as "pass, 7 high open", so a pass is never read as all clear; a qa-acceptance review fails on any criterion that doesn't hold (RFC 0015). For a work item, the report answers for the rules that can apply to the files the change touched, which next_work gives with each review as rules; a whole-project review answers for all of the skill's rules (RFC 0016). A report says how it checked each automatic rule it passes, checkedBy: tool or reading: Peer AI refuses tool where the tool doesn't enforce the rule in the parts the change touched, and the result counts the automatic rules checked by reading only, such as "pass, 2 automatic rules checked by reading only", in next_work and peer-ai check too (RFC 0019). | | check_document | Checks a document a Peer AI skill wrote against the skill's template, and lists what to change: missing or empty parts, template text left in, and rule ids that don't exist. The skill fixes them and checks again, until the document is ready. An agent in a git worktree of its own gives its branch, so its own copy is checked. | | advance_work_item | Moves a work item to its next stage, back to an earlier one, or to cancelled. A move to ship or done passes the same gates as peer-ai check, and a refusal lists what to fix. An item whose branch is already merged moves to done saying so instead, as peer-ai close-merged does (RFC 0013). Moving to verify works out the reviews the change needs from the files it touched, and keeps them on the item. Moving to verify or ship repeats any migrationCollisions as a warning, never a refusal: the order of merging is a person's call (RFC 0018). Moving an item whose branch has merged to done writes its record where the merge is, not on the merged branch, and the reply says where, to commit with the next pull request (RFC 0020). | | draft_feedback | Drafts a report for Peer AI's maintainers when Peer AI itself gets something wrong, with Peer AI's version, the AI tool, the stage and the stack profiles added. It writes the draft to .peer-ai/feedback/ and refuses one holding code, a key or token, or an email address. The person decides whether it's sent: see peer-ai feedback. |

Every change to a work item is validated against its schema before it is written. A work item lives on its branch (RFC 0010): the tools read and write it, and verify it, in the working copy where that branch is checked out, the main one or any git worktree, so agents working in parallel worktrees never touch each other's items, and switching branches never rolls one back. Moving an item to build records the commit it starts from. run_verify runs the project's own command through the shell, exactly as a person would type it.