skills/code-review/SKILL.md
Paranoid architect review of code changes for bugs, security, missing tests, and undocumented assumptions. Works on local git diffs OR a GitHub pull request (e.g. `owner/repo N`). For PRs, can post findings as line-level review comments.
npx skillsauth add nearai/ironclaw 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.
You are reviewing this change as a paranoid architect. Your job is to find every bug, vulnerability, race condition, edge case, and undocumented assumption before it ships. Assume adversarial users, concurrent access, and Murphy's law.
You handle two input shapes:
owner/repo N, owner/repo#N, or a github.com/.../pull/N URL. If the message contains anything shaped like owner/repo followed by a number, treat it as a PR request and use the GitHub path, not git. Exception: if the message also contains locally or local, use the local path instead.Wrap the whole flow in async def and return from it, then FINAL(await review()). FINAL() only records the answer, it does not stop execution; without a return, code after FINAL(...) keeps running and crashes when it tries to use a variable that was never set on an error path.
async def review():
pr_url = f"https://api.github.com/repos/{owner}/{repo}/pulls/{number}"
files_url = f"{pr_url}/files?per_page=100"
# Sequential awaits instead of asyncio.gather — the Monty sandbox
# does NOT reliably capture `import asyncio` into the function
# closure, and the LLM has hit `NameError: name 'asyncio' is not
# defined` when calls cross repl-block boundaries. Three serial
# GETs against api.github.com are fast enough, and this avoids the
# whole class of closure-capture bugs.
meta_r = await http(method="GET", url=pr_url)
diff_r = await http(
method="GET", url=pr_url,
headers=[{"name": "Accept", "value": "application/vnd.github.v3.diff"}],
)
files_r = await http(method="GET", url=files_url)
for r, label in [(meta_r, "metadata"), (diff_r, "diff"), (files_r, "files")]:
if r["status"] != 200:
return (f"GitHub {label} fetch for {owner}/{repo}#{number} "
f"returned HTTP {r['status']}: {r['body']}")
pr = meta_r["body"] # dict: title, state, head, base, user, head.sha, ...
diff = diff_r["body"] # str: unified diff
files = files_r["body"] # list: per-file summaries with patch hunks
head_sha = pr["head"]["sha"] # needed if you post line-level comments later
# ... build the review ...
return body
FINAL(await review())
Do NOT wrap body with .get("body", body) or isinstance(..., str) normalization. On a 2xx, meta_r["body"] is the parsed JSON; on the diff request it is a string. If status is not 2xx, return fast — silently falling through produces empty reviews where every field is "unknown".
Run shell with git diff (unstaged), git diff --cached (staged), or git diff HEAD~1 (last commit). For local reviews, skip the GitHub posting steps entirely and present findings in the chat.
For each file in the diff, read the entire current file, not just the hunks. You need surrounding context to catch:
Fetch file contents via GitHub's raw media type so you get the text directly — the default /contents/ response is base64-encoded and Monty's CodeAct sandbox does not ship the base64 module (so import base64 raises ModuleNotFoundError). Use the application/vnd.github.raw Accept header and read body as a plain string:
r = await http(
method="GET",
url=f"https://api.github.com/repos/{owner}/{repo}/contents/{urllib.parse.quote(path, safe='')}?ref={head_sha}",
headers=[{"name": "Accept", "value": "application/vnd.github.raw"}],
)
if r["status"] != 200:
# Missing-on-head usually means the PR deleted the file; fall back to
# `base=pr['base']['sha']` or skip.
continue
file_text = r["body"] # plain str, no base64
If the PR touches more than 20 files, prioritize: service logic > routes/handlers > models/types > tests > docs.
Walk the changes through each lens. For every finding, capture: file, line range, severity, category, concrete description, and a suggested fix.
None/null, zero-length collectionsi64::MAX, negative when expecting positive)? propagation make sense?The review must:
Review of {owner}/{repo}#{number}: {pr["title"]} (or Review of local changes for the local path)path:line from the diff, never a generic "looks good"| Severity | Meaning | |----------|---------| | Critical | Security vulnerability, data loss, or financial exploit | | High | Bug that will cause incorrect behavior in production | | Medium | Robustness issue, missing validation, incomplete error handling | | Low | Style, naming, documentation, minor improvement | | Nit | Optional, take-it-or-leave-it |
Render findings as a table:
| # | Severity | Category | File:Line | Finding | Suggested fix | |---|----------|----------|-----------|---------|---------------|
Then ask the user which findings to post as PR comments. Default: all Critical, High, and Medium. Skip this prompt for the local path.
Use the same async def + FINAL(await ...) pattern. Line-level review comments require commit_id (the head SHA you captured in step 1) and the line number on the post-image side of the diff (side: "RIGHT"). For findings spanning multiple files or architectural critiques, post a single PR-level issue comment instead.
async def post():
# Line-level comment on a specific file:line
r = await http(
method="POST",
url=f"https://api.github.com/repos/{owner}/{repo}/pulls/{number}/comments",
body={
"body": "**High** — `state.store` accessed directly, bypassing dispatch. See `.claude/rules/tools.md`.",
"commit_id": head_sha,
"path": "src/channels/web/handlers/foo.rs",
"start_line": 140,
"start_side": "RIGHT",
"line": 142,
"side": "RIGHT",
},
)
if r["status"] not in (200, 201):
return f"Posting line comment failed: HTTP {r['status']}: {r['body']}"
# Architectural / multi-file finding as a PR-level comment
r2 = await http(
method="POST",
url=f"https://api.github.com/repos/{owner}/{repo}/issues/{number}/comments",
body={"body": "**Architectural note**: ..."},
)
if r2["status"] not in (200, 201):
return f"Posting PR comment failed: HTTP {r2['status']}: {r2['body']}"
return f"Posted {len(line_findings)} line comments and {len(pr_findings)} PR comments."
FINAL(await post())
Format every comment as: bold severity tag, one-line summary, detailed explanation, concrete fix (with code if useful).
development
Linear issue tracker API integration. Covers first-use identity bootstrap (viewer + teams cached), raw GraphQL for list/search/create/update, and the rules for handling "my issues" / "assigned to me" requests.
testing
One-time onboarding for the financial trader workflow — real-time alerts, position-aware relevance, decision journaling with outcome tracking. After successful setup this skill is excluded from selection until the marker file is deleted.
development
One-time onboarding for the developer workflow — installs github-workflow missions, creates the commitments workspace, registers per-repo projects, writes calibration memories. After successful setup this skill is excluded from selection until the marker file is deleted.
devops
One-time onboarding for the content creator workflow — content pipeline stages, trend expiration, cross-platform cascades, heavy idea parking. After successful setup this skill is excluded from selection until the marker file is deleted.