git clone https://github.com/MetaMask/ocap-kernel
T=$(mktemp -d) && git clone --depth=1 https://github.com/MetaMask/ocap-kernel "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/pr" ~/.claude/skills/metamask-ocap-kernel-pr && rm -rf "$T"
.claude/skills/pr/SKILL.mdWhen asked to create a pull request, follow these steps:
Phase 1: Pre-flight checks
-
Run
. If any of the following conditions apply, stop and report the errors:git status- There are unstaged changes
- There are untracked files
- The current branch is the default branch (
)main
-
Check if this is a stacked PR:
- Run
to find the common ancestor with maingit merge-base main HEAD - Run
to see commits since diverging from maingit log --oneline <merge-base>..HEAD - Check if any parent commits are on another feature branch (not main)
- If so, run
to check if that branch has an open PRgh pr list --head <parent-branch> - If a parent branch has an open PR, this is a stacked PR
- Run
-
Run
to see the commit history.git log main..HEAD --oneline -
Get the diff for the review:
- If this is a stacked PR, run
to scope the diff to only this branch's changes.git diff <parent-branch>...HEAD - Otherwise, run
.git diff main...HEAD
- If this is a stacked PR, run
Phase 2: Automated PR review (parallel subagents)
MANDATORY — DO NOT SKIP. This phase must run before any PR is created, regardless of how "simple", "mechanical", or "well-tested" the changes appear. Subtle bugs (e.g., semantic mismatches in API migrations) hide in exactly the changes that seem safe to skip. The only exception is docs-only changes as described below.
Before creating the PR, analyze the diff to decide which review subagents to launch. Not every PR needs every reviewer.
Triage: classify the change
Categorize each changed file, then pick subagents based on which categories are present. A file belongs to exactly one category — evaluate in this order (first match wins):
- docs:
,.md
,.txt
,CHANGELOG
,LICENSE
,docs/.claude/ - ci:
,.github/workflows/
— these often contain shell scripts with non-trivial logic.github/actions/ - config:
(not.json
),package.json
,.yml
,.yaml
,.eslintrc*
,.prettierrc*
,tsconfig*
,Dockerfile
,.editorconfig
,.gitignore
,.gitattributes
,.nvmrc.yarnrc* - test: files matching
,*.test.ts
, or under*.spec.ts
directoriestest/ - code: everything else (
,.ts
,.js
,.mjs
,.cjs
, etc.)package.json
Then decide which subagents to launch:
- If only docs files changed: skip the entire review phase and go straight to Phase 3.
- Otherwise, select subagents based on which categories are present:
- ci present → launch Subagent 1 (Correctness) (review shell logic, conditional expressions, job dependency chains)
- config or test present → launch Subagent 2 (Style)
- test present → also launch Subagent 4 (Tests)
- code present → launch Subagent 1 (Correctness) and Subagent 2 (Style)
- code present → also launch Subagent 4 (Tests)
- code present and diff touches security-sensitive areas (network/HTTP, user input, auth, crypto,
/eval
, capability passing,Function
/SES) → also launch Subagent 3 (Security)harden()
Subagent 1: Correctness & Logic
Prompt the agent to:
- Review the diff for logical errors, off-by-one mistakes, race conditions, and incorrect assumptions
- Check that error handling is adequate at system boundaries
- Verify that new code paths are reachable and dead code hasn't been introduced
- Flag any behavior changes that aren't covered by tests
Subagent 2: Style & Conventions
Prompt the agent to:
- Check adherence to the project's CLAUDE.md conventions (TypeScript types over interfaces, no
, noany
, kebab-case files,enum
for runtime types, options bags for 3+ args,@metamask/superstruct
usage, etc.)harden() - Check test conventions (no "should",
for full objects,toStrictEqual
for parameterized tests, concise verb-form titles)it.each - Flag unnecessary complexity, over-engineering, or missing
callsharden()
Subagent 3: Security & Performance
Prompt the agent to:
- Look for OWASP top-10 vulnerabilities (injection, XSS, etc.)
- Check for capability leaks in the ocap model (unhardened objects, leaked references)
- Identify performance issues (unnecessary allocations in hot paths, missing early returns, O(n^2) patterns)
- Verify that lockdown/SES compatibility isn't broken (no ambient authority, no forbidden globals)
Subagent 4: Test Coverage
Prompt the agent to:
- Identify new or changed logic that lacks corresponding test coverage
- Check that edge cases and error paths are tested
- Verify tests are co-located correctly per project conventions
- Flag any test anti-patterns (global state, missing cleanup, overly broad mocks)
Phase 3: Review summary
If the review phase was skipped (docs-only), proceed directly to Phase 4.
Otherwise, after all launched subagents complete:
- Compile findings into a Review Summary with sections for each subagent that ran.
- Classify each finding as one of:
- blocker - Must fix before merging
- suggestion - Should consider fixing
- nit - Minor, optional improvement
- If there are blockers, present them to the user and ask whether to:
- Fix the blockers automatically, then re-review
- Proceed with PR creation anyway
- Abort
- If there are no blockers, briefly summarize the findings and proceed.
Phase 4: Create the PR
-
Run
to create a pull request. The PR body should include:gh pr create- A brief narrative description of the PR
- A summary of the changes (bullet points)
- A brief description of how the code is tested (narrative, not a checklist)
If this is a stacked PR, add
to create it as a draft PR.--draft -
Note the PR number from the created PR URL — it is needed for changelog entries. Proceed to Phase 5 before presenting results to the user.
Phase 5: Update changelogs
MANDATORY — DO NOT SKIP. Analyze the diff and determine whether any changes are consumer-facing (i.e., affect the behavior or API of a published or private package).
- If there are NO consumer-facing changes (e.g., docs-only, CI, tooling, skill definitions, dev scripts): add the
label to the PR viano-changelog
and skip the rest of this phase.gh pr edit <number> --add-label no-changelog - If there ARE consumer-facing changes: update changelogs as described below.
Read the instructions in
and follow them to the letter. In particular:docs/contributing/updating-changelogs.md
- Think from the consumer's perspective. A changelog is not a git history. For each affected package, ask: "What changed for someone who depends on this package?" Describe changes in natural language; do not simply reuse commit messages.
- Combine like changes. If multiple commits contribute to a single logical change within one package, write one changelog entry — not one per commit.
- Split disparate changes. If one commit touches unrelated concerns in a single package, write separate entries.
- Link the PR. Use the PR number from Phase 4 in each entry (e.g.
).([#123](https://github.com/.../pull/123))
Commit the changelog updates to the current branch with the message "docs: Update changelogs" and push.
Done
Present the PR URL and any relevant information to the user. If a review was performed, include the review summary.