
Pr Review
- 1.6k installs
- 13.2k repo stars
- Updated April 18, 2026
- minimax-ai/skills
A structured PR review workflow that applies both automated hard rules and manual content guidelines to validate skill submissions.
About
This skill provides a two-phase PR review process for the MiniMax Skills repository. Phase 1 runs automated validation via a Python script that checks SKILL.md existence, YAML frontmatter syntax, required fields (name, description), name-to-directory matching, and absence of hardcoded secrets. Phase 2 applies soft content guidelines: skill scope overlap, description clarity, file size, API key handling via environment variables, script quality (shebang, requirements.txt, error handling), English language compliance, and README table sync. Developers use this when reviewing contributions, validating new skill submissions, or ensuring existing skills remain compliant with repository standards.
- Automated validation script checks SKILL.md structure, YAML parsing, required fields, and secret detection
- Two-phase review: hard structural rules (blockers) then soft content guidelines (flagged items)
- Validates name matches directory, API credentials via environment variables, script shebangs and error handling
- Ensures README.md and README_zh.md updated with new skills and Source column set to Community
- Checks PR title follows conventional commit format and enforces one-PR-one-purpose constraint
Pr Review by the numbers
- 1,574 all-time installs (skills.sh)
- +29 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #84 of 1,352 Code Review & Quality skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
pr-review capabilities & compatibility
- Capabilities
- validate skill.md structure and yaml frontmatter · check for required fields (name, description) an · detect hardcoded secrets in skill files · review skill scope for functional overlap with e · verify api key handling via environment variable · validate script quality (shebang, requirements.t · check readme table synchronization and source co
- Use cases
- code review · testing
- Platforms
- macOS · Windows · Linux · WSL
- Runs
- Runs locally
- Pricing
- Free
npx skills add https://github.com/minimax-ai/skills --skill pr-reviewAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.6k |
|---|---|
| repo stars | ★ 13.2k |
| Security audit | 3 / 3 scanners passed |
| Last updated | April 18, 2026 |
| Repository | minimax-ai/skills ↗ |
What it does
Validate pull requests to the MiniMax Skills repository against structural and content standards before merge.
Who is it for?
Maintainers and reviewers validating skill submissions; contributors ensuring their PRs pass validation before submission.
Skip if: General code review outside the MiniMax Skills repository; real-time linting during development (use pre-commit hooks instead).
When should I use this skill?
A pull request is opened or updated in the MiniMax Skills repository; contributor wants to self-check before submission.
What you get
Contributors receive clear feedback on compliance with hard blockers and soft guidelines; maintainers can merge with confidence that skills meet repository standards.
- Review comments
- Scope boundary notes
- Description improvement suggestions
By the numbers
- Two-phase review process: automated hard rules + manual soft guidelines
- 6 hard structural checks in validation script (SKILL.md, YAML, required fields, name match, secrets)
- 6 soft content guidelines (scope, description, file size, API handling, script quality, language)
Files
PR Review Skill
Review pull requests against repository standards. Two-phase process: automated validation, then manual content review.
Phase 1: Automated Validation (Hard Rules)
Run the validation script to check structural requirements:
python .claude/skills/pr-review/scripts/validate_skills.pyThe script checks:
SKILL.mdexists in every skill directory- YAML frontmatter is parseable
- Required fields present:
name,description namematches directory name- No hardcoded secrets detected
All ERROR-level checks must pass. WARNING-level items (missing license, metadata) should be flagged but are not blockers.
See references/structure-rules.md for the complete hard rules specification.
Phase 2: Content Review (Soft Guidelines)
After automated checks pass, review the PR against quality guidelines:
1. Skill scope — Does it overlap with existing skills? Is the boundary clear? 2. Description quality — Does the description include clear trigger conditions? 3. File size — Are reference docs reasonably sized for context window consumption? 4. API key handling — If external APIs are used, are credentials read from environment variables? 5. Script quality — Do scripts have shebang, requirements.txt, and error handling? 6. Language — Are SKILL.md and code written in English? 7. README sync — Are README.md and README_zh.md updated for new skills?
See references/quality-guidelines.md for soft guidelines details.
Review Checklist Summary
Must Pass (Blockers)
- [ ]
validate_skills.pyexits with code 0 - [ ] PR title follows conventional commit format
- [ ] One PR, one purpose
Should Pass (Flagged in Review)
- [ ] No functional overlap with existing skills
- [ ] Description includes trigger conditions
- [ ] Files are reasonably sized
- [ ] API keys via environment variables
- [ ] README tables updated for new skills (Source column set to
Community)
Quality Guidelines (Soft Review)
These guidelines are not enforced by automated tooling. Reviewers should check these during manual PR review and flag violations as suggestions.
1. Skill Scope — Avoid Overlap
Before approving a new skill, check existing skills for functional overlap.
- If the new skill's capability is a subset of an existing skill, suggest extending the existing one instead
- If there is partial overlap, the PR description must clearly explain the boundary
- Example: a voice synthesis skill should clarify how it differs from
frontend-dev's TTS capabilities
2. Description Quality
The description field in SKILL.md is what the agent uses to decide whether to activate the skill. A good description must include:
- What the skill does
- When to use it (trigger conditions)
- Keywords or phrases that should activate it
Bad: "A skill for making PDFs" Good: "Generate, fill, and reformat PDF documents. Use when the user asks to create, modify, or design any PDF file. Triggers: PDF, .pdf, document generation."
3. File Size Awareness
Skills are loaded into the agent's context window. Every token counts.
- Individual
.mdfiles should stay focused and concise - If a reference document exceeds ~500 lines, consider splitting it into parts
- Do not embed large data blobs (base64 images, full API responses) in Markdown
- Prefer linking to external resources over inlining lengthy content
4. Credential Handling
The validation script only blocks high-confidence secret patterns (OpenAI keys, AWS keys, JWT tokens). Reviewers should additionally check for:
- API keys or passwords assigned directly in code (e.g.,
api_key = "abc123...") - Credentials passed as plain string arguments instead of environment variable reads
- Example keys that look realistic enough to be mistaken for real ones
- Scripts that lack a clear error message when a required env var is missing
If a skill involves external APIs, verify that SKILL.md documents the required environment variables.
5. Script Quality
If the skill includes helper scripts in scripts/:
- Scripts should have a shebang line (
#!/usr/bin/env python3) - A
requirements.txtshould be present listing all dependencies if external libraries are needed. - Errors should produce clear messages, not raw tracebacks
6. Language
- SKILL.md content and code should be written in English
- Reference docs are recommended to be in English
7. README Sync
When a new skill is added, both README.md and README_zh.md should be updated with the new skill in the table. Community-submitted skills should set the Source column to Community.
Structure Rules (Hard Validation)
These rules are enforced by scripts/validate_skills.py. PRs that violate ERROR-level rules will not be merged.
Directory Structure
Every skill must follow this layout:
skills/<skill-name>/
├── SKILL.md # Required
├── references/ # Optional
│ └── *.md
└── scripts/ # Optional
├── *.py
└── requirements.txt # Required if scripts/ exists- Directory name must be lowercase
kebab-case(e.g.,gif-sticker-maker) SKILL.mdis the only required file
SKILL.md Frontmatter
The file must begin with a valid YAML frontmatter block enclosed by --- markers.
Required Fields (ERROR if missing)
| Field | Rule |
|---|---|
name | Must exist and exactly match the directory name |
description | Must exist and be non-empty |
Recommended Fields (WARNING if missing)
| Field | Rule |
|---|---|
license | Should be MIT or a license declaration |
metadata | Should include version, category, and optionally sources |
Secret Scanning
No file in the skill directory may contain hardcoded secrets. The following high-confidence patterns are scanned:
- OpenAI-style API keys:
sk-followed by 20+ alphanumeric characters - AWS Access Key IDs:
AKIAfollowed by 16 uppercase alphanumeric characters - Hardcoded Bearer tokens:
Bearerfollowed by 50+ characters (typical JWT length)
Other forms of hardcoded credentials (API key assignments, passwords, etc.) are not automatically blocked but should be flagged during manual review.
Validation Severity Levels
- ERROR — PR must not be merged. Must be fixed before approval.
- WARN — Reviewer should flag. Not a merge blocker but should be addressed.
#!/usr/bin/env python3
"""Validate skill directory structure and SKILL.md frontmatter.
Zero external dependencies — uses only Python standard library.
Exit code 0: all checks passed (warnings are OK).
Exit code 1: at least one ERROR found.
Usage:
python validate_skills.py # scan default path (skills/)
python validate_skills.py --path some/dir # scan specific directory
"""
import argparse
import os
import re
import sys
# ---------------------------------------------------------------------------
# Minimal frontmatter parser
# ---------------------------------------------------------------------------
def extract_frontmatter(text):
"""Extract YAML frontmatter string between --- markers. Returns None if not found."""
stripped = text.lstrip("\ufeff")
if not stripped.startswith("---"):
return None
end = stripped.find("---", 3)
if end == -1:
return None
return stripped[3:end]
def parse_frontmatter_fields(fm_text):
"""Parse top-level scalar fields from frontmatter text.
Returns dict of {field_name: value_string}. Nested keys under a mapping
are ignored — we only need top-level presence checks.
"""
fields = {}
lines = fm_text.splitlines()
i = 0
while i < len(lines):
line = lines[i]
if not line.strip() or line.strip().startswith("#"):
i += 1
continue
m = re.match(r"^([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*(.*)", line)
if m:
key = m.group(1)
rest = m.group(2).strip()
if rest in ("|", ">", "|+", "|-", ">+", ">-"):
block_lines = []
i += 1
while i < len(lines) and (lines[i].startswith(" ") or lines[i].startswith("\t") or lines[i].strip() == ""):
block_lines.append(lines[i])
i += 1
fields[key] = "\n".join(block_lines).strip()
continue
elif rest == "":
block_lines = []
i += 1
while i < len(lines) and (lines[i].startswith(" ") or lines[i].startswith("\t")):
block_lines.append(lines[i])
i += 1
fields[key] = "\n".join(block_lines).strip() if block_lines else ""
continue
else:
fields[key] = rest.strip("\"'")
i += 1
return fields
# ---------------------------------------------------------------------------
# Secret scanning
# ---------------------------------------------------------------------------
SECRET_PATTERNS = [
(r"sk-[a-zA-Z0-9]{20,}", "OpenAI-style API key"),
(r"AKIA[0-9A-Z]{16}", "AWS access key"),
(r"Bearer\s+[a-zA-Z0-9_\-\.]{50,}", "Hardcoded bearer token"),
]
SCAN_EXTENSIONS = {".md", ".py", ".sh", ".js", ".ts", ".json", ".yaml", ".yml", ".txt", ".toml", ".cfg", ".ini"}
def scan_secrets(filepath):
"""Scan a file for hardcoded secrets. Returns list of (line_no, pattern_desc, matched_text)."""
try:
with open(filepath, "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
except Exception:
return []
findings = []
for line_no, line in enumerate(content.splitlines(), 1):
for pattern, desc in SECRET_PATTERNS:
for match in re.finditer(pattern, line):
findings.append((line_no, desc, match.group(0)[:60]))
return findings
# ---------------------------------------------------------------------------
# Skill discovery and validation
# ---------------------------------------------------------------------------
def find_skill_dirs(base_path):
"""Find directories that contain a SKILL.md."""
skill_dirs = []
for root, dirs, files in os.walk(base_path):
dirs[:] = [d for d in dirs if not d.startswith(".")]
if "SKILL.md" in files:
skill_dirs.append(root)
return sorted(skill_dirs)
def validate_skill(skill_dir):
"""Validate a single skill directory. Returns (errors, warnings) lists."""
errors = []
warnings = []
dir_name = os.path.basename(skill_dir)
skill_md = os.path.join(skill_dir, "SKILL.md")
if not os.path.isfile(skill_md):
errors.append("SKILL.md not found")
return errors, warnings
with open(skill_md, "r", encoding="utf-8", errors="ignore") as f:
content = f.read()
fm_text = extract_frontmatter(content)
if fm_text is None:
errors.append("SKILL.md has no valid YAML frontmatter (missing --- markers)")
return errors, warnings
fields = parse_frontmatter_fields(fm_text)
name = fields.get("name", "").strip()
if not name:
errors.append("Missing required field: name")
elif name != dir_name:
errors.append(f"name '{name}' does not match directory name '{dir_name}'")
desc = fields.get("description", "").strip()
if not desc:
errors.append("Missing required field: description")
if "license" not in fields or not fields["license"].strip():
warnings.append("Missing recommended field: license")
if "metadata" not in fields or not fields["metadata"].strip():
warnings.append("Missing recommended field: metadata")
for root, dirs, files in os.walk(skill_dir):
dirs[:] = [d for d in dirs if not d.startswith(".")]
for fname in files:
_, ext = os.path.splitext(fname)
if ext not in SCAN_EXTENSIONS:
continue
fpath = os.path.join(root, fname)
for line_no, sdesc, matched in scan_secrets(fpath):
rel = os.path.relpath(fpath, skill_dir)
errors.append(f"Potential secret in {rel}:{line_no} ({sdesc}): {matched}...")
return errors, warnings
def main():
parser = argparse.ArgumentParser(description="Validate MiniMax Skills structure")
parser.add_argument("--path", default="skills", help="Directory to scan (default: skills/)")
args = parser.parse_args()
scan_path = os.path.abspath(args.path)
skill_dirs = find_skill_dirs(scan_path)
if not skill_dirs:
print("No skill directories found.")
sys.exit(0)
print(f"\nValidating {len(skill_dirs)} skill(s)...\n")
total_errors = 0
total_warnings = 0
for sd in skill_dirs:
rel = os.path.relpath(sd)
errors, warnings = validate_skill(sd)
if errors:
status = "FAIL"
elif warnings:
status = "WARN"
else:
status = "PASS"
print(f" [{status}] {rel}")
for msg in errors:
print(f" ERROR {msg}")
for msg in warnings:
print(f" WARN {msg}")
total_errors += len(errors)
total_warnings += len(warnings)
print()
if total_errors:
print(f" {total_errors} error(s), {total_warnings} warning(s)")
print(" Validation FAILED.\n")
sys.exit(1)
elif total_warnings:
print(f" 0 errors, {total_warnings} warning(s)")
print(" Validation PASSED.\n")
else:
print(" All checks passed.\n")
if __name__ == "__main__":
main()
Related skills
How it compares
Use pr-review for catalog SKILL.md governance; use code-review skills when the PR changes application source instead of agent skills.
FAQ
What do I do if validate_skills.py exits with a non-zero code?
Fix the ERROR-level issues (SKILL.md missing, unparseable YAML, missing name/description, name mismatch, hardcoded secrets). WARNING-level items (missing license, metadata) should be flagged but are not blockers.
Are soft content guidelines blockers or just recommendations?
Soft guidelines (scope overlap, description quality, file size, API key handling, script quality, English language, README sync) are flagged in review but not automated blockers; hard rules from validate_skills.py must pass.
How should I handle API credentials in a skill?
Read credentials from environment variables, never hardcode secrets. The validation script checks for hardcoded secrets and will flag them as errors.
Is Pr Review safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.