Submit PR
SkillAI & modelsSubmit a pull request following the repo's contribution guidelines. Reviews the diff, checks for common rejection reasons, and helps the user write their own PR description. The LLM reviews. the user writes. Use when implementation is complete and tests pass. Not for responding to review comments after the PR is open. Use oss-post-pr for that.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Submit PR skill
What this skill tells your AI
The instructions your AI receives, as published by chiruu12/oss-skills in skills/oss-submit-pr/SKILL.md and read by ahel’s review.
Get your PR right the first time. This skill checks your work against the repo's rules, catches common rejection reasons, and helps you write a PR description that maintainers actually want to read. You write the description. the LLM reviews it.
Purpose
A clean PR gets reviewed and merged. A sloppy PR gets ignored or closed. Most new contributors get rejected not because their code is bad, but because they didn't follow the process. wrong branch, missing tests, unclear description, scope creep. This skill catches all of that before you hit submit.
Prerequisites
- Implementation complete (from
oss-contribute) - Tests pass locally
- Lint/formatting passes locally
- User can explain what they changed and why (verified in
oss-contributestep 6)
Process
1. Re-read contribution requirements
Even if oss-prep-to-contribute already read these, read them again. specifically for PR submission rules:
# Fetch latest CONTRIBUTING.md
gh api repos/{owner}/{repo}/contents/CONTRIBUTING.md --jq '.content' | base64 -d 2>/dev/null
# Check for PR template - all standard locations
for path in \
".github/PULL_REQUEST_TEMPLATE.md" \
".github/pull_request_template.md" \
"PULL_REQUEST_TEMPLATE.md" \
"pull_request_template.md" \
"docs/PULL_REQUEST_TEMPLATE.md" \
"docs/pull_request_template.md"; do
if content=$(gh api "repos/{owner}/{repo}/contents/$path" --jq '.content' 2>/dev/null); then
printf '%s' "$content" | base64 -d 2>/dev/null
break
fi
done
# Check for multiple PR templates (directory-based)
gh api "repos/{owner}/{repo}/contents/.github/PULL_REQUEST_TEMPLATE" \
--jq '.[] | .name' 2>/dev/null
If a single template is found: use it. The PR description must follow its structure exactly.
If a template directory exists with multiple templates: present each template name to the user and ask which one matches their contribution type (bug fix, feature, docs, etc.). Fetch the selected template and use it.
If no template is found: no template required. follow the general PR description guidance below.
Extract PR-specific requirements:
- PR template (must follow if present. check ALL locations above)
- Branch naming convention
- Commit message format (conventional commits? sign-off required? DCO?)
- Squash policy (squash before merge? maintainer squashes?)
- Linked issue format ("Fixes #123" vs "Closes #123" vs "Resolves #123")
- Required reviewers or labels
- CI checks that must pass
2. Find the gates that are not in the docs
CONTRIBUTING.md describes the rules a human will judge the PR by. The rules a bot
enforces live in .github/workflows/, and they fail a PR that is otherwise fine,
often with an error that does not say what it wants.
# Scan every workflow for the gates below in one pass
for f in $(gh api repos/{owner}/{repo}/contents/.github/workflows \
--jq '.[] | select(.type == "file") | .name
| select(test("\\.ya?ml$"))'); do
hits=$(gh api "repos/{owner}/{repo}/contents/.github/workflows/$f" --jq '.content' \
| base64 -d 2>/dev/null \
| grep -oiE 'semantic-pull-request|semantic-pr|issue-link|signed-off-by|[-/]dco|cla-assistant|contributor-assistant|towncrier|changeset|commitlint' \
| sort -u | tr '\n' ' ')
[ -n "$hits" ] && echo "$f: $hits"
done
# Then read any workflow that matched, to see what it actually requires
gh api repos/{owner}/{repo}/contents/.github/workflows/{file} --jq '.content' | base64 -d
A hit is a lead, not a verdict. Read the workflow it names and find the condition it fails on.
Each of these rejects a correct patch, so find them before writing anything:
| Gate | What it demands | What to grep the workflows for |
|---|---|---|
| Semantic PR title | Title shaped fix: ... or feat: ... | semantic-pull-request, semantic-pr |
| Linked issue | The body must reference an issue | issue-link, a step named like "Validate PR to Issue link" |
| DCO | Every commit carries Signed-off-by | dco, signed-off-by |
| CLA | An agreement signed before review | cla-assistant, contributor-assistant |
| Changelog entry | A news fragment or CHANGELOG edit | towncrier, changeset, changelog |
| Commit lint | Commit messages match a convention | commitlint, conventional |
| Branch naming | The branch matches a pattern | a step reading github.head_ref |
Branch protection adds requirements that no file in the repo mentions:
gh api repos/{owner}/{repo}/rulesets --jq '.[] | "\(.name)\t\(.target)"' 2>/dev/null
Tell the user what each gate requires before they write a line of code. A DCO
gate means git commit -s from the first commit. Finding out afterwards means
rewriting every commit on the branch. A changelog gate means an extra file that
reviewers will ask for anyway.
3. Pre-flight checks
Run every check the CI will run. locally, before pushing:
# Rebase on latest upstream
git fetch upstream
git rebase upstream/main
# Run tests
# {repo-specific test command}
# Run linting/formatting
# {repo-specific lint command}
# Check the diff is focused
git diff upstream/main...HEAD --stat
Re-check that the issue is still the user's. Implementation takes days, and a
claim made on Monday can be overtaken by Thursday. Before pushing anything, run
the same checks oss-find-issue step 5 runs:
gh issue view {number} -R {owner}/{repo} --json state,assignees,labels,comments
gh api repos/{owner}/{repo}/issues/{number}/timeline --paginate \
--jq '.[] | select(.event == "cross-referenced") | .source.issue
| select(.pull_request != null)
| "\(.state)\t\(.repository.full_name)#\(.number)\t\(.user.login)"'
If somebody else opened a PR for this issue while the user was working, stop. Do not open a competing PR. Say so in a comment, offer to review theirs, and move on to the next issue. Losing a few days of work is cheaper than the reputation of someone who races other contributors.
4. Review the diff
Go through the entire diff and flag issues:
git diff upstream/main...HEAD
Check for:
| Check | What to look for |
|---|---|
| Scope creep | Changes to files unrelated to the issue |
| Debug leftovers | console.log, print(), debugger, TODO comments |
| Style drift | Naming that doesn't match repo conventions |
| Missing tests | Code changes without corresponding test changes |
| Commented-out code | Dead code that shouldn't be committed |
| Unrelated formatting | Whitespace-only changes to lines you didn't modify |
| Hardcoded values | Magic numbers, hardcoded strings that should be constants |
| Error handling | New code paths without error handling (if repo expects it) |
For each issue found, present it to the user with the exact location:
"Found a potential issue at
src/foo.ts:42: you left aconsole.logfrom debugging. Remove it before submitting."
Don't auto-fix. Tell the user what and where.
5. Verify commit conventions
# Check commit messages against repo conventions
git log upstream/main..HEAD --oneline
If the repo uses conventional commits and the user's messages don't conform, explain the format and ask them to amend. If sign-off is required:
# Check for sign-off
git log upstream/main..HEAD --format='%B' | grep -c 'Signed-off-by'
6. Thinking gate: user writes the PR description
The user writes the PR description, not the LLM.
Tell the user:
"Write your PR description. Start with one sentence: what does this PR do?
Then add:
- Link to the issue ('Fixes #{number}')
- Why this approach. remember the trade-offs from /oss-contribute? Mention the key one
- How you tested it. what did you run, what passed?
Keep it short. If the repo has a PR template, follow it. Write in your own words. I'll review it after."
Wait for the user to write it.
7. Review the PR description
Once the user has written their description, review it for conciseness and clarity:
- Does it link the issue? ("Fixes #{number}")
- Does it follow the repo's PR template structure? (If a template was found in step 1, every section from the template must be addressed)
- Is it short and direct? Maintainers review dozens of PRs. they skim
- Does it explain non-obvious decisions without over-explaining obvious ones?
- Does it mention how the change was tested?
Writing rules for PR descriptions:
- Lead with what changed, not why you're writing
- One sentence per point. No paragraphs where a bullet works
- No filler: "This PR addresses the issue where..." → "Fixes null check in auth handler"
- No AI jargon: "comprehensive", "robust", "leverages", "utilizing". Cut all of it
- No self-narration: "I noticed that..." / "After investigating...". Just state the facts
- Technical terms are fine. Buzzwords are not
- If the PR template asks for something, answer it. Don't add extra sections
Give specific feedback:
"Your description is good, but trim the first paragraph. the reviewer doesn't need the backstory. Lead with what changed."
Don't rewrite it. give feedback and let the user revise.
8. Submit
Once the description passes review:
# Push the branch
git push origin {branch-name}
# Create the PR
gh pr create \
--repo {owner}/{repo} \
--title "{title following repo convention}" \
--body "$(cat <<'EOF'
{user's PR description}
EOF
)"
9. Post-submission verification
# Check CI status
gh pr checks {pr-number} -R {owner}/{repo} --watch
If CI fails:
- Explain WHAT failed (test name, lint rule, build error)
- Point to the relevant code
- Don't fix it. tell the user what needs to change
Common rejection reasons (educate the user)
Present these before submission as a final checklist:
- Scope creep: PR touches files unrelated to the issue
- No tests: code changes without test changes in a repo that expects tests
- CI failure: tests or lint fail (never submit with red CI)
- Poor description: maintainer can't understand what the PR does from the description alone
- Wrong base branch: PR targets wrong branch (check repo conventions)
- Style violations: code doesn't match repo's formatting/naming conventions
- Breaking changes without discussion: changes public API without prior maintainer approval
Related Skills
- Previous step: ←
oss-contribute: the implementation work - Next step: →
oss-post-pr: handle review feedback after submission - If CI fails: Fix locally and push again (don't invoke another skill, just fix and push)
Common Rationalizations
| Shortcut | Why It Fails |
|---|---|
| "CI will catch any issues, I don't need to run checks locally" | CI failures are public. Every maintainer sees your red check. Running locally first is basic professionalism. and saves a round-trip of push-wait-fix-push. |
| "The code speaks for itself, I don't need a detailed description" | Maintainers review 10+ PRs a week. They skim descriptions first to decide priority. No description = no context = bottom of the queue. |
| "Let me just submit and iterate based on feedback" | First impressions matter. A sloppy first submission signals carelessness. Maintainers are less likely to invest review time in a PR that wasn't polished before submission. |
| "I'll write the description later, let me just get the PR up" | The description IS the PR for the reviewer. They read it before the code. A PR without a description is a PR without context. it gets deprioritized or closed. |
| "The diff is small, I don't need to review it" | Small diffs still contain debug leftovers, commented-out code, unrelated formatting changes. A 5-line diff with a console.log gets the same rejection as a 500-line mess. |
Red Flags
- Diff touches files unrelated to the issue. scope creep that will trigger reviewer questions
- PR description is longer than 3 paragraphs. over-explaining signals uncertainty about the approach
- User can't summarize what the PR does in one sentence. the change isn't focused enough
- CI has been failing for multiple pushes. stop pushing and debug locally
Verification Checklist
- Workflow gates identified (semantic title, DCO, linked issue, changelog) (step 2)
- Issue re-checked: still open, still unassigned, no competing PR opened while the user was implementing (step 3)
- All local tests pass (including new tests)
- Lint/formatting passes locally
- Diff only touches files relevant to the issue (no scope creep)
- No debug leftovers (console.log, print, debugger, TODO)
- Commit messages follow repo convention
- PR description links the issue (Fixes #{number})
- PR description follows repo template (if one exists)
- PR description written by user, reviewed by LLM
- CI passes after submission
Anti-patterns
- DO NOT write the PR description for the user. review and give feedback on theirs
- DO NOT auto-fix diff issues. tell the user what and where, they fix it
- DO NOT open a PR against an issue somebody else claimed while the user was working. stand down and take the next one
- DO NOT submit with failing CI. ever
- DO NOT skip the pre-flight checks. "it works on my machine" is not enough
- DO NOT include "AI-generated" boilerplate in the PR unless the repo's CODE_OF_CONDUCT requires disclosure
Signals
- GitHub stars
- 63
- Forks
- 6
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
oss-submit-pr- Source
- github.com/chiruu12/oss-skills