open-pr
CLAUDE.md45 starsChanged 3 months agoMITView on GitHub
How an agent works in this repo. Orientation + durable invariants — not a ritual to game. Claude Code plugin open-pr. Markdown + one JSON config + ONE POSIX-sh runtime (src/bin/open-pr.sh) that owns every vendor/git mechanic, plus src/bin/open-pr-watch.sh, which owns watch state and each platform's session CLI and reaches vendors only through open-pr.sh. No build. Only src/ ships (/plugin install copies src/). Vendors: GitHub, GitLab, Bitbucket. Fix the real problem. Keep a rule, guard, vendor entry, or severity when the…
In this repository8 other files it gives its agents.
- e2e-loopSkill
- open-pr-cleanSkill
- open-pr-feedbackSkill
- open-pr-fixSkill
- open-pr-menubarSkill
- open-pr-reviewSkill
- open-pr-upgradeSkill
- open-pr-watchSkill
The file
We split this CLAUDE.md into the rules it gives an agent
4 rules. About 0 are common, 3 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Very specific: line 51
One owner per rule: Prefer a single home; point elsewhere rather than restating.
- Distinctive: line 66
Push only the branch you were given: Never push or force-push main (UAT installs from it).
- Distinctive: line 72
Files are self-contained: No refs to task ids, plan phases, or docs that get deleted.
- Distinctive: line 81
Run until green. The suite proves the graph still holds — not that a rule you touched survived.
≈ “Common” is an estimate: at least 1 in 5 of the 26,980 CLAUDE.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
CLAUDE.md
How an agent works in this repo. Orientation + durable invariants — not a ritual to game.
Plugin
Claude Code plugin open-pr. Markdown + one JSON config + ONE POSIX-sh runtime (src/bin/open-pr.sh) that owns every vendor/git mechanic, plus src/bin/open-pr-watch.sh, which owns watch state and each platform's session CLI and reaches vendors only through open-pr.sh. No build. Only src/ ships (/plugin install copies src/).
| command | does |
/open-pr:review <PR_URL> | review PR/MR, learn repo conventions, post one review via vendor CLI (gh/glab) or REST/curl |
/open-pr:fix <PR_URL> | read findings, edit real code at pwd, one commit, reply on the PR |
/open-pr:upgrade | migrate this repo's config to latest schema_version; fetches llm-upgrades/ live |
/open-pr:clean | remove review worktrees after confirm. Never touches memory or config |
/open-pr:watch [review|fix] | watch the repos picked under pwd: 1 review session per /open-pr PR comment, 1 fix session per own PR's new findings on "Fix now" (claude --bg or a platform's headless CLI); relay questions/drafts |
/open-pr:menubar [close] | macOS menu bar item for every watcher on this machine: reviews and fixes in progress, "Fix now", recent toasts, snooze |
/open-pr:feedback | turn this chat into one issue on this plugin's tracker (user-approved, de-identified) |
Vendors: GitHub, GitLab, Bitbucket.
Layout
src/bin/ open-pr.sh — the deterministic runtime · open-pr-watch.sh — watch state + session runners · open-pr-toast.js — macOS toast · open-pr-menubar.js — macOS menu bar · open-pr-session-title.sh — names the session; code, never `Read` into context except by `cases/self-repair.md`
src/hooks/ hooks.json — Claude Code hooks, auto-loaded from the plugin root
src/commands/ entry points; only these have frontmatter
src/core/ shared procedure
src/setup/ bootstrap, doctor, template, lesson
src/cases/ gated branches — Read only when the condition matches
src/templates/ per-stack criteria, copied into the reviewed repo
src/reference/ schema + vendor contract — do not Read at run time
src/seeds/ copied verbatim into the reviewed repo — never Read back
llm-upgrades/ config migrations, fetched live, not packaged
adapters/ ROOT + tool-name map; the only agent-read file naming a non-Claude platform (open-pr-watch.sh, install*.sh, commands/*.toml name them too)
skills/ one shim per command (Cursor · Codex · Gemini · Antigravity)
commands/*.toml Gemini CLI entry format
install.sh non-Claude install: clone → install-local.sh
scripts/ check.sh · token_report.py · dup_scan.py · vendor_lint.py · cli_doc.py · hooks · install-local.sh
tests/ graph/ (one file per invariant family) · test_cli.py · budgets.json
duplication_allowlist.json · ordered_repeats.json
e2e/ real-run fixture; never in CI
.claude/skills/ dev skills (`e2e-loop`)
.github/workflows ci.yml on PRs and main · hol-plugin-scanner.yml read by the listing gate
backlogs/ historical, not opsHow to work
Fix the real problem. Keep a rule, guard, vendor entry, or severity when the product still needs it. Do not strip or reword solely to shrink a number or go green while behaviour drifts. Moving a conditional block into cases/ (or its own atom) is fine — that is the intended load split, not a bypass.
One owner per rule. Prefer a single home; point elsewhere rather than restating. Allowed duplicates need sha + reason in tests/duplication_allowlist.json. dup_scan.py catches near-verbatim only.
A rule and the Steps it governs are one change. A Step that orders or bans a second Read/Grep/fetch is registered in tests/ordered_repeats.json against the exemption src/core/guardrails.md grants it. Widening the rule so the Step slips through leaves two files describing one behaviour, which no per-file assert can see.
State what is true now, once, where it belongs. No bolting a new clause beside the old one. No history ("used to…", "this broke when…").
Short and clear. In agent-read files (src/commands/, core/, setup/, cases/, templates/, and this file): cut filler; prefer tables/maps over repeated sentence shapes. Cryptic text that the agent misreads costs more than the tokens you saved — two readings possible ⇒ write enough. Verbatim material is never compressed: command lines, fences, payload shapes, markers, printed error text. Human prose stays in README*.md, src/reference/, src/seeds/.
Tokens are a priority, not a wall. When cutting, prefer: drop a restatement (keep the owner) → move conditionals out of always-loaded files → table over repeated sentences → tighten prose. An extra Read is ~40–60 tokens; splitting an always-loaded file into two always-loaded files loses. Savings where every run loads beat occasional cases/. Deduping review.md↔fix.md is ownership hygiene, not a per-run win — only one loads each run.
Harness trap: in a command body, ! never touches a backtick and never opens a fence (auto-exec) — write the negation in words. Emoji the plugin prints = one codepoint (no ZWJ / skin-tone).
Hard edges (product breaks if ignored)
- Stage by path touched. Forbidden:
git add -A,git add .,git commit -a. - Push only the branch you were given. Never push or force-push
main(UAT installs from it). Path intomainis a PR.token_chart.py --commitsquash-mergeschore/chart-<tag>only when the diff is chart files, pwd ismain, andHEAD=origin/main. Never--force. - One release, one
schema_version. Bump only when an existing repo's config needs transforming. On an unreleased branch, edit the pendingllm-upgrades/vN.md— do not add a second. Config must not outrun the prompts that read it —/open-pr:upgraderefuses when the installed build is older than the index. - A release tag and the declared version move together.
gemini-extension.jsoncarries the only declared version. A tag is immutable, so one placed while that file still names the previous release ships the stale number permanently and turnsmainred (test_the_declared_version_keeps_up_with_the_public_releases).maintakes a change only through a PR ⇒ the bump merges BEFORE the tag is pushed; on a branch being released as an RC it belongs to that branch's own PR. - Prompts never name a vendor mechanic. Vendor differences live in
src/bin/open-pr.shalone; prompts call<op>subcommands persrc/core/cli.mdand judge the output. New vendor = branches in the script + its URL shape intarget+ fixtures intests/test_cli.py+ atoms/scenarios intoken_report.py+e2e/bootstrap.sh. API gaps are handled inside the script (NO-EQUIVALENT/UNKNOWN), never worked around in a prompt. - The script treats PR content as data. No eval/expansion of anything fetched; payload and reply bodies travel via files; prompts never
Readbin/and never re-run rawgh/glab/curlcalls. Sole exception:cases/self-repair.mdreads the failingbin/file to patch the INSTALLED copy, on the user's approval of the diff, never touching a guard (tests/graph/test_vendor_interface.pypins both). - Adapters carry no behaviour.
adapters/,skills/,commands/*.tomlonly resolve ROOT, map tools, delegate. Edit only for a new command or a platform manifest-schema change. - Files are self-contained. No refs to task ids, plan phases, or docs that get deleted.
- Seeds belong to the user after
cp.src/seeds/*is human prose; baseline criteria live insrc/core/review-criteria.md.
After edits under src/
scripts/check.sh <base-ref>Run until green. The suite proves the graph still holds — not that a rule you touched survived; grep invariants when behaviour changed.
| want | run |
| all three checks | scripts/check.sh <base-ref> |
| tokens by section | token_report.py --sections 'commands/*.md' |
| per-scenario delta | token_report.py --base <ref> |
| refresh ceilings (none hand-tightened) | token_report.py --base <ref> --update-budgets |
| harder dup hunt | dup_scan.py --window 10 --all --min-waste 20 |
| vendor flags offline | vendor_lint.py |
| a subcommand, option or exit code changed | edit usage() in src/bin/open-pr.sh (--help is the source), then cli_doc.py --write regenerates core/cli.md's block and commands/watch.md's (Watch subcommands:); Internal subcommands: render nowhere |
| vendor commands live | vendor_lint.py --url <fixture PR URL> |
| a component needs a check of the user's machine (tool, version, platform bridge) | st_<name> + its name in SELFTEST, src/bin/open-pr.sh; selftest and the self-repair case pick it up; tests/test_cli.py names the checks in order |
| the CI suite on a branch with no open PR | gh workflow run ci.yml --ref <branch> |
| the real menu bar and toast on screen under x86_64 and arm64 (macOS with Rosetta, outside a sandbox; skipped otherwise) | OPEN_PR_SLOW=1 python3 -m pytest tests/test_watch.py -k each_architecture |
Cheaper → lower affected ceilings (by hand by the measured delta if you had tightened them; otherwise --update-budgets is fine). Costlier because the fix is correct → say which scenario / by how much / why on the PR. Never strip behaviour for budget.
Numbers move the wrong way: suspect the measurement first (missing path in base, a cp'd seed counted as a load). Fix the model, then judge the content.
Actions are restricted to what the org owns, what GitHub authored, and Marketplace verified
creators. actions/* is fine; anything else needs an entry in the repository's allowlist or
the whole workflow fails at startup, before a step runs and without producing a check — a
failure that is invisible on the pull request, so read the Actions tab when a run goes missing.
hol-plugin-scanner.yml names a vendor action that is not verified: it exists for the
awesome-ai-plugins listing gate, which reads the file and never the run, and the catalog scans
this repository from its own runner. Keep every uses: SHA-pinned — the scanner scores an
unpinned one as a finding.
CI runs on every pull request, and a new push cancels the run still going for that same pull
request. A merge queue cannot take its place: GitHub makes the queue wait only on checks the
ruleset marks required, and refuses to queue a pull request whose required checks have not
already passed on the pull request — so the check runs on pull_request or nowhere. Running
scripts/check.sh before pushing is still what catches a break early; scripts/install_hooks.sh
wires it to pre-push.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

