Frappe Review
Triage Frappe/ERPNext changes before they ship. This skill gathers the diff and tooling output, loads the relevant reference rules, then hands off to the frappe-fullstack:frappe-reviewer agent for the actual line-by-line review.
Two modes
Mode A — Local diff (default)
When the user asks to review without naming a target, review the working tree:
git -C ${user_config.bench_path} diff HEAD --stat
git -C ${user_config.bench_path} diff HEAD
Override only when explicit:
| User says |
Use |
| "review my last commit" |
git show HEAD |
| "review the branch" |
git diff $(git merge-base HEAD main)...HEAD |
"review path/to/file.py" |
git diff HEAD -- <path> (and read the full file if context is needed) |
Mode B — GitHub PR
When the user pastes a GitHub PR URL (https://github.com/{owner}/{repo}/pull/{n}) or says "review PR #N":
gh pr view <url-or-number> --json number,title,body,author,baseRefName,headRefName,headRefOid,files
gh pr diff <url-or-number>
# For files where the diff alone is ambiguous:
gh pr view <url-or-number> --json files -q '.files[].path' | while read -r p; do
gh api "repos/{owner}/{repo}/contents/$p?ref=<headRefOid>" -H "Accept: application/vnd.github.raw"
done
Authentication: gh uses the user's existing gh auth login credentials, or GH_TOKEN / GITHUB_TOKEN from env. Do not prompt the user for tokens.
Posting back to GitHub is opt-in. Do NOT post the review as a PR comment unless the user explicitly says "post the review", "comment on the PR", or similar. By default, surface the review in the chat only. When the user does ask to post:
gh pr comment <url-or-number> --body-file <(printf '%s' "<review markdown>")
Workflow
Frame the diff
Mode A: git diff HEAD --stat. Mode B: gh pr view --json files.
If empty, ask the user to point to what they want reviewed.
Categorize touched files:
| Pattern |
Domain |
Reference to read |
*.py (controllers, APIs, hooks, patches) |
Frappe Python |
references/frappe-python.md |
*.json inside a doctype/ path |
DocType schema |
references/doctype-json.md |
*.js, *.jsx, *.ts, *.tsx, *.vue |
Frontend |
references/frontend.md |
*.html (Jinja) |
Templates |
references/frappe-python.md (Jinja section) |
hooks.py, patches/, fixtures/ |
Frappe infra |
references/frappe-python.md |
*.css, *.scss |
Style |
inline rules in references/frontend.md |
Build / config (pyproject.toml, package.json, tsconfig.json, lockfiles) |
Skip unless obviously broken |
— |
Always apply references/security.md to every file regardless of type.
Cheap tooling first (skip whatever isn't installed; never block on tooling)
# Python — only on changed .py files
files=$(git diff HEAD --name-only --diff-filter=AM | grep '\.py$')
[ -n "$files" ] && echo "$files" | xargs -r ruff check 2>/dev/null
[ -n "$files" ] && echo "$files" | xargs -r ruff format --check 2>/dev/null
# JS/TS — only when the touched app has its own package.json / lint config
git diff HEAD --name-only --diff-filter=AM | grep -E '\.(js|jsx|ts|tsx|vue)$'
Capture findings — the reviewer agent should not re-flag what tooling already caught.
Note migration / fixture risk
git diff HEAD --name-only | grep -E '(doctype/.*\.json|patches\.txt|fixtures/|hooks\.py)$'
Any hit means the reviewer must check for a corresponding patch or after_migrate step.
Hand off to the reviewer agent
Invoke frappe-fullstack:frappe-reviewer with:
- The full unified diff (
git diff HEAD or gh pr diff)
- Mode (A: local diff / B: PR
<url>)
- The list of touched files grouped by category and the reference files that apply
- Any
ruff / eslint findings already known (so the agent ignores them)
- The bench root and default site from
${user_config.bench_path} and ${user_config.default_site} for cross-file lookups
The agent reads the relevant reference files itself — do not copy rule text into the prompt.
Surface the report
The agent returns a single structured report (severity buckets + verdict + What's Done Well + file-by-file table). Surface it verbatim. Do not summarize or rewrite — the user needs the citations intact.
What this skill does NOT do
- Does not apply fixes. Both the skill and the agent are read-only by tool config.
- Does not run the test suite. If the reviewer flags missing tests, invoke
/frappe-test separately.
- Does not commit, push, or open PRs. Use
/frappe-github after fixes.
- Does not post to GitHub by default. Posting requires an explicit user request.
1---2name: frappe-review3description: Review Frappe/ERPNext code changes for framework idioms, security, permission correctness, and performance. Use when the user says "review", "review my changes", "review this PR", "code review", "check this PR", or pastes a github.com/*/pull/* URL — even with no other context. Also when reviewing a specific file, controller, API, DocType JSON, client script, or ERPNext customization.4---56# Frappe Review78Triage Frappe/ERPNext changes before they ship. This skill gathers the diff and tooling output, loads the relevant reference rules, then hands off to the `frappe-fullstack:frappe-reviewer` agent for the actual line-by-line review.910## Two modes1112### Mode A — Local diff (default)1314When the user asks to review without naming a target, review the working tree:1516```bash17git -C ${user_config.bench_path} diff HEAD --stat18git -C ${user_config.bench_path} diff HEAD19```2021Override only when explicit:2223| User says | Use |24|-----------|-----|25| "review my last commit" | `git show HEAD` |26| "review the branch" | `git diff $(git merge-base HEAD main)...HEAD` |27| "review `path/to/file.py`" | `git diff HEAD -- <path>` (and read the full file if context is needed) |2829### Mode B — GitHub PR3031When the user pastes a GitHub PR URL (`https://github.com/{owner}/{repo}/pull/{n}`) or says "review PR #N":3233```bash34gh pr view <url-or-number> --json number,title,body,author,baseRefName,headRefName,headRefOid,files35gh pr diff <url-or-number>36# For files where the diff alone is ambiguous:37gh pr view <url-or-number> --json files -q '.files[].path' | while read -r p; do38 gh api "repos/{owner}/{repo}/contents/$p?ref=<headRefOid>" -H "Accept: application/vnd.github.raw"39done40```4142Authentication: `gh` uses the user's existing `gh auth login` credentials, or `GH_TOKEN` / `GITHUB_TOKEN` from env. Do not prompt the user for tokens.4344**Posting back to GitHub is opt-in.** Do NOT post the review as a PR comment unless the user explicitly says "post the review", "comment on the PR", or similar. By default, surface the review in the chat only. When the user does ask to post:4546```bash47gh pr comment <url-or-number> --body-file <(printf '%s' "<review markdown>")48```4950## Workflow51521. **Frame the diff**53 - Mode A: `git diff HEAD --stat`. Mode B: `gh pr view --json files`.54 - If empty, ask the user to point to what they want reviewed.55 - Categorize touched files:5657 | Pattern | Domain | Reference to read |58 |---------|--------|-------------------|59 | `*.py` (controllers, APIs, hooks, patches) | Frappe Python | `references/frappe-python.md` |60 | `*.json` inside a `doctype/` path | DocType schema | `references/doctype-json.md` |61 | `*.js`, `*.jsx`, `*.ts`, `*.tsx`, `*.vue` | Frontend | `references/frontend.md` |62 | `*.html` (Jinja) | Templates | `references/frappe-python.md` (Jinja section) |63 | `hooks.py`, `patches/`, `fixtures/` | Frappe infra | `references/frappe-python.md` |64 | `*.css`, `*.scss` | Style | inline rules in `references/frontend.md` |65 | Build / config (`pyproject.toml`, `package.json`, `tsconfig.json`, lockfiles) | Skip unless obviously broken | — |6667 - **Always** apply `references/security.md` to every file regardless of type.68692. **Cheap tooling first** (skip whatever isn't installed; never block on tooling)70 ```bash71 # Python — only on changed .py files72 files=$(git diff HEAD --name-only --diff-filter=AM | grep '\.py$')73 [ -n "$files" ] && echo "$files" | xargs -r ruff check 2>/dev/null74 [ -n "$files" ] && echo "$files" | xargs -r ruff format --check 2>/dev/null7576 # JS/TS — only when the touched app has its own package.json / lint config77 git diff HEAD --name-only --diff-filter=AM | grep -E '\.(js|jsx|ts|tsx|vue)$'78 ```79 Capture findings — the reviewer agent should not re-flag what tooling already caught.80813. **Note migration / fixture risk**82 ```bash83 git diff HEAD --name-only | grep -E '(doctype/.*\.json|patches\.txt|fixtures/|hooks\.py)$'84 ```85 Any hit means the reviewer must check for a corresponding patch or `after_migrate` step.86874. **Hand off to the reviewer agent**8889 Invoke `frappe-fullstack:frappe-reviewer` with:90 - The full unified diff (`git diff HEAD` or `gh pr diff`)91 - Mode (A: local diff / B: PR `<url>`)92 - The list of touched files grouped by category and the reference files that apply93 - Any `ruff` / `eslint` findings already known (so the agent ignores them)94 - The bench root and default site from `${user_config.bench_path}` and `${user_config.default_site}` for cross-file lookups9596 The agent reads the relevant reference files itself — do not copy rule text into the prompt.97985. **Surface the report**99100 The agent returns a single structured report (severity buckets + verdict + What's Done Well + file-by-file table). Surface it verbatim. Do not summarize or rewrite — the user needs the citations intact.101102## What this skill does NOT do103104- Does not apply fixes. Both the skill and the agent are read-only by tool config.105- Does not run the test suite. If the reviewer flags missing tests, invoke `/frappe-test` separately.106- Does not commit, push, or open PRs. Use `/frappe-github` after fixes.107- Does not post to GitHub by default. Posting requires an explicit user request.