skills/code-review/SKILL.md
--- name: code-review description: CodeRabbit-style PR review. Reads a GitHub PR, produces a walkthrough plus inline findings tagged by severity (critical / major / minor / question / praise) in a kind-but-direct voice. Default mode writes a local markdown report under `.code-review/`; `--post` publishes the review to GitHub as RoBot-branded inline comments via one atomic API call. Use when user wants to review a PR, run a code review, give feedback on a teammate's branch, or get a second-opinio
npx skillsauth add RonanCodes/ronan-skills skills/code-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
CodeRabbit-style PR reviewer with two output modes: local markdown report (default) or GitHub review with inline comments (with --post). Every public comment is prefixed **🤖 RoBot review** so it's obvious the source is automation.
Spec: [[coderabbit-style-pr-review]] in llm-wiki-skill-lab/wiki/patterns/. Read reference.md next to this SKILL.md for the full severity taxonomy, comment templates, anti-patterns, and gh api JSON shapes.
/ro:code-review # interactive: picks open PR for current repo
/ro:code-review 171 # review PR #171 in current repo, local report only
/ro:code-review 171 --post # local report AND post to GitHub
/ro:code-review --post-only 171 # post to GitHub, skip local report
/ro:code-review owner/repo#171 # cross-repo
/ro:code-review https://github.com/... # paste a PR URL
/ro:code-review 171 --poem # include a poem in the walkthrough (default off)
/ro:code-review 171 --assertive # include minor/nitpick findings (default: critical + major + question only)
/ro:code-review 171 --profile strict # strict = REQUEST_CHANGES even for major; chill = APPROVE if no critical
/ro:code-review 171 --worktree # check the PR out in a sibling git worktree so it can run side-by-side with main
/ro:code-review --worktree-cleanup 171 # remove the worktree after review
| Mode | Trigger | What happens |
|------|---------|--------------|
| local (default) | no flag | Writes ./.code-review/PR-<n>-<slug>.md. Nothing touches GitHub. |
| post | --post | Writes the local report AND posts to GitHub. |
| post-only | --post-only | Posts to GitHub. No local report. |
Always default to local. The user must opt in to GitHub. Confirm before posting if you got here through /ro:code-review <N> --post without seeing the report first.
# If argument is a number, use current repo
gh pr view <N> --json number,title,body,author,headRefName,headRefOid,baseRefName,changedFiles,additions,deletions,url,state,isDraft
# If URL, parse owner/repo/number from it
# If --repo passed, use that
PR_HEAD_SHA=$(gh pr view <N> --json headRefOid -q .headRefOid)
PR_URL=$(gh pr view <N> --json url -q .url)
Refuse if state != OPEN (unless --allow-closed). Warn if isDraft = true.
# Full unified diff (for finding lines)
gh pr diff <N> > /tmp/pr-<N>.diff
# Changed files for per-file review
gh pr view <N> --json files -q '.files[].path' > /tmp/pr-<N>.files
If the diff exceeds ~80k tokens, summarise per-file and warn that depth will be lower.
Two strategies depending on whether you want side-by-side dev:
Default — checkout in place:
gh pr checkout <N> # fetches and switches to the branch
# After review:
git checkout - # back to whatever the user was on
This lets you Read files at the PR head for context beyond the diff hunks. Fast and ephemeral. Don't run tests or builds; only read.
With --worktree — reusable sibling worktree:
Use the helper script — it handles worktree creation, .dev.vars copy, dependency install, and D1 migration apply in one shot. It is REUSABLE: one worktree directory called <repo>-code-review that you switch between PRs as you review them.
# First time / new PR (creates worktree if missing, switches it if present)
"${CLAUDE_PLUGIN_ROOT:-$HOME/Dev/ronan-skills}/skills/code-review/scripts/setup-pr-worktree.sh" 171
# Switch the same worktree to a different PR (no fresh pnpm install)
"${CLAUDE_PLUGIN_ROOT:-$HOME/Dev/ronan-skills}/skills/code-review/scripts/setup-pr-worktree.sh" --switch 195
# Status / cleanup
"${CLAUDE_PLUGIN_ROOT:-$HOME/Dev/ronan-skills}/skills/code-review/scripts/setup-pr-worktree.sh" --status
"${CLAUDE_PLUGIN_ROOT:-$HOME/Dev/ronan-skills}/skills/code-review/scripts/setup-pr-worktree.sh" --cleanup
Per-worktree state that's automatically isolated by cwd: .wrangler/state/ (local D1 SQLite, KV, R2), node_modules/, .dev.vars, .code-review/. State that is shared (which is the point of worktrees): .git/objects/, git config, remote refs.
See WORKTREE.md next to this SKILL.md for the full side-by-side recipe + troubleshooting.
When to use --worktree:
When the user wants to run BOTH apps simultaneously (e.g., for visual diffing the PR against main):
| Concern | Default | What to do |
|---------|---------|------------|
| Port | Most stacks hardcode --port 3000 in dev script | Override on the PR worktree: pnpm dev -- --port 3001 or npx vite dev --port 3001 |
| D1 / local SQLite | .wrangler/state/v3/d1/<id>.sqlite lives per cwd | Naturally isolated by worktree. Run migrations once per worktree. |
| KV / R2 (Cloudflare) | Same as D1 — per cwd in .wrangler/state/ | Naturally isolated. |
| .dev.vars / .env | Gitignored, won't follow the worktree | Copy from main worktree once. Edit if any value is port-specific. |
| Clerk auth callbacks | Dev keys whitelist exact redirect URIs | Add the second port (e.g., http://localhost:3001) to Clerk's allowed origins/redirect URLs once; both ports then work simultaneously. |
| External webhooks (Stripe, Resend, Nango) | Tunnels resolve to one URL | Only one worktree can claim the public webhook URL at a time. Not a blocker for visual review or static-flow testing. |
| Third-party APIs in mutate mode | Shared upstream | Read-only inspection is fine. Both worktrees writing to the same upstream (e.g., Shopify dev store, Nango sandbox) can race. Use the PR worktree for read-only flows during comparison. |
| Browser | One profile = one cookie jar | Open the PR worktree in an incognito window or a separate Chrome profile if the auth cookies collide. |
Quick recipe:
# Terminal 1 (main checkout)
cd ~/Dev/projects/<repo>
pnpm dev # runs on :3000
# Terminal 2 (PR worktree)
cd ~/Dev/projects/<repo>-pr-<N>
pnpm dev -- --port 3001 # runs on :3001
Both Cloudflare-Workers / TanStack-Start / Vite apps can run at once. The thing that breaks is anything that wants exclusive global state: a single webhook tunnel URL, a single browser cookie for the same domain, or an external sandbox in write mode.
If the user is mainly screenshotting and comparing layouts, the side-by-side setup is genuinely free. If they need full mutation flows, pick one worktree at a time.
In this order:
--assertive.Skip anything a linter handles (formatting, import order, missing semicolons).
Use the 5-level taxonomy (full table in reference.md):
| Level | Emoji | When | GH event implication |
|-------|-------|------|----------------------|
| critical | ⚠️ | Bug, security, broken contract. Must fix before merge. | Triggers REQUEST_CHANGES |
| major | 🛠️ | Real design/quality concern. Address or push back. | COMMENT (or REQUEST_CHANGES with --profile strict) |
| minor | 🧹 | Polish, naming. Author may ignore. | COMMENT. Suppressed unless --assertive. |
| question | ❓ | "Is this intentional?" — clarification. | COMMENT |
| praise | ✨ | Sincere recognition. Sparingly. | COMMENT |
Cap on nitpicks per review: 5. Drop the rest.
Markdown. Always include these sections, in this order:
**🤖 RoBot review** — kind, direct, opinionated.
## Walkthrough
<one paragraph: intent of the PR, not file enumeration>
## Changes
| File | Change |
|------|--------|
| ... | ... |
## Estimated review effort
<1-5> / 5
## Findings
- 🔴 Critical: <N>
- 🟠 Major: <N>
- 🟡 Minor: <N> (suppressed; use --assertive to surface)
- 🔵 Questions: <N>
- 🟢 Praise: <N>
## Sequence diagram
<mermaid, only when the PR touches multi-component interactions>
## Out of scope
<observations the reviewer noticed but didn't flag inline because they're outside the diff>
## Poem ← only if --poem
> <four-line rabbit-style verse about the PR>
Wrap the entire walkthrough body with HTML comment markers so re-runs can find-and-replace:
<!-- robot-review:start sha=<HEAD_SHA> -->
...content...
<!-- robot-review:end -->
Each finding follows the CodeRabbit anatomy:
**🤖 RoBot review** — _⚠️ Critical (blocking)_
**<one-line subject>**
<one paragraph: WHY this matters>
```suggestion
<exact replacement for the lines this comment targets>
<!-- robot-review:inline -->
Substitutions per severity:
- critical → `_⚠️ Critical (blocking)_`
- major → `_🛠️ Major suggestion_`
- minor → `_🧹 Nitpick (non-blocking)_`
- question → `_❓ Question_`
- praise → `_✨ Praise_`
Only include the ` ```suggestion ` block when the fix is a concrete replacement for the targeted lines. If the fix needs broader context, put a ` ```diff ` block instead (illustrative only, not committable).
### 8. Validate before emitting
For each inline finding, verify:
1. The `path` exists in the PR's changed files.
2. The `line` is in the diff hunk (`RIGHT` side for added/context, `LEFT` for removed).
3. Multi-line: `start_line <= line`, both with `side` set.
Drop any finding that fails validation. Move it to the **Out of scope** section of the walkthrough instead.
### 9. Local report (default)
Write to `./.code-review/PR-<N>-<slug>.md`. Add `.code-review/` to `.gitignore` if absent (or `~/.gitignore_global` if the repo's `.gitignore` is locked).
Format: see `reference.md` § Local report.
### 10. Post to GitHub (only when --post or --post-only)
Build `/tmp/robot-review-<N>.json`:
```json
{
"commit_id": "<PR_HEAD_SHA>",
"event": "COMMENT",
"body": "<walkthrough markdown>",
"comments": [
{ "path": "...", "line": 42, "side": "RIGHT", "body": "..." },
{ "path": "...", "start_line": 60, "start_side": "RIGHT", "line": 64, "side": "RIGHT", "body": "..." }
]
}
event selection:
REQUEST_CHANGES--profile strict AND has major → REQUEST_CHANGES--profile chill AND no critical → APPROVECOMMENTPost atomically:
gh api repos/<OWNER>/<REPO>/pulls/<N>/reviews \
--method POST \
--input /tmp/robot-review-<N>.json
If the POST returns 422, the most likely cause is a stale commit_id or a line not in the diff. Re-fetch headRefOid, re-validate lines, retry once, then surface the error to the user with the offending finding.
Print:
COMMENT / REQUEST_CHANGES / APPROVE).When --post is run a second time on the same PR:
<!-- robot-review:start).gh api .../reviews/<id>/dismissals).This keeps the PR clean across re-runs without manual cleanup.
Full list in reference.md. Five worst:
path:line against the parsed diff before emitting.--assertive.testing
--- name: linear-pipeline description: The Fable orchestrator for a single dispatched Linear ticket. Holds almost no context itself; it receives `--issue <ID> --detached`, decides the stage sequence, and fans out a sub-agent per stage, passing forward only each stage's artifact (never re-derived, never inlined into its own context). Step zero, before any planning or stage routing, is a boundary triage against `canon/security-boundary.md` (#199): a match tags Ronan Connolly and stops the run, no
development
--- name: in-your-face description: Capture a chat-only answer into a durable artifact (markdown + HTML, PDF when cheap) and launch it automatically so the user cannot miss it. Use when user says "in your face", "don't let me lose this", "save that answer", "make that durable", or right after answering a substantive side question (a recipe, comparison, how-to, or generated prompt) that would otherwise die with the context. category: workflow argument-hint: [--no-open] [--vault <short>] [hint of
tools
One-shot headless OpenAI Codex CLI calls for background/admin AI tasks — summaries, classification, extraction, admin glue. The default engine for anything that runs AI constantly in the background (daemon-driven, per-event), because it bills the flat ChatGPT subscription instead of Claude usage or per-token API spend, and it keeps working while Claude is rate-limited. NEVER for coding — coding stays Claude. Use when a skill or daemon needs a cheap always-on AI call, when the user says "use codex", "ask codex", "codex as backup", or when building a background summarizer/classifier into a listener or loop. Reads auth from ~/.codex/auth.json (ChatGPT account, no API key).
research
Turn a warranty rejection, repair quote, or RMA email into a cited decision brief — legal read (NL/EU consumer law), is the part user-serviceable, live part and new-unit prices, repair-vs-DIY-vs-new economics, before-you-send-it checklist, deadlines. Use when the user pastes or screenshots a repair quote, warranty rejection, "not covered" email, onderzoekskosten fee, or asks "should I repair or replace this".