Agent skill
upstream-pr
Load this skill whenever working in a fork of a third-party project.
Install this agent skill to your Project
npx add-skill https://github.com/akaihola/skills-akaihola/tree/main/upstream-pr
SKILL.md
Upstream PR Workflow
This skill manages the full lifecycle of contributing a fix from a fork back to an
upstream repository, following a draft-in-tree convention: a PULL_REQUEST_DRAFT.md
file lives in every commit on the PR branch and is git rm'd immediately before
submission.
The PULL_REQUEST_DRAFT.md Convention
Every commit on a PR branch must contain PULL_REQUEST_DRAFT.md at the repo root.
Format:
# PR Title Here (this line → `gh pr create --title`)
Everything below this line becomes the PR body (`--body`).
## Problem
…
## Solution
…
## Testing
…
- The first
# H1line is the PR title. - All remaining content is the PR body (GitHub Markdown).
- The file is committed so every intermediate state of the branch is self-documenting.
- Do NOT
.gitignoreit — it must be visible ingit logand reviewable. - Remove it with
git rmjust before creating the PR (see Submission step).
Remotes Convention
In a fork, always name remotes:
| Remote | Points to |
|---|---|
origin |
Your fork (read/write) |
upstream |
The original project |
If upstream is not configured:
git remote add upstream https://github.com/OWNER/REPO.git
git fetch upstream
The akaihola Working Branch (git-knit)
All unmerged feature branches must be stacked into a single working branch
called akaihola using git-knit. This gives a single integration branch that
combines every in-flight change on top of upstream/main.
Initialize (once per repo)
# akaihola = working branch, upstream/main = base, list any existing branches
git knit init akaihola upstream/main [fix/branch-a fix/branch-b ...]
If akaihola already exists in the remote, verify git knit status matches
what is currently checked out before touching it.
Day-to-day commands
git knit status # show base, working branch, and all knitted branches
git knit add fix/new-branch # add a newly-created feature branch
git knit remove fix/old-branch # drop a merged/abandoned branch
git knit rebuild # rebuild akaihola from scratch (after rebases, etc.)
git knit restack # restack feature branches with git-spice
Rules
- Every new feature/fix branch must be
git knit add-ed immediately after creation. - After rebasing any feature branch onto updated
upstream/main, rungit knit rebuildto regenerateakaihola. - Never commit directly to
akaihola— it is a derived branch. All real commits go to individualfix/*/feat/*/docs/*branches. - When a PR is merged upstream, run
git knit remove <branch>andgit knit rebuild.
Workflow
1. Identify the change
Determine what needs contributing. Common sources:
- A commit in your fork's
mainnot inupstream/main - A bug fix applied locally but never submitted
- An enhancement developed in a feature branch
Useful commands:
# Commits in fork's main not in upstream
git log --oneline upstream/main..main
# Diff a specific file between fork and upstream
git diff upstream/main..main -- path/to/file.go
# Check if content already merged upstream (empty = already there)
git cherry -v upstream/main <your-branch>
Always verify the change is not already in upstream before creating a PR branch.
Upstream may have merged the content under different commit SHAs. Use
git diff upstream/main...<your-branch> (three dots = content diff from merge base)
to confirm actual differences exist.
2. Fetch upstream
git fetch upstream
3. Create a clean branch from upstream/main
git checkout -b <branch-name> upstream/main
Branch naming convention:
fix/<short-description>for bug fixesfeat/<short-description>for new featureschore/<short-description>for non-functional changesdocs/<short-description>for documentation
4. Apply the change
Choose the cleanest approach:
a) Cherry-pick (when the commit applies cleanly):
git cherry-pick <commit-sha>
# Resolve any conflicts if needed
b) Apply a file diff (when cherry-pick would drag in unrelated changes):
git diff upstream/main..main -- path/to/file > /tmp/fix.patch
git apply /tmp/fix.patch
git add path/to/file
git commit -m "fix: description of the fix"
c) Implement fresh (when rewriting is cleaner than patching): Just make the changes and commit normally.
5. Add PULL_REQUEST_DRAFT.md to the commit
After the fix commit exists (or as part of it), add PULL_REQUEST_DRAFT.md:
cat > PULL_REQUEST_DRAFT.md << 'EOF'
# fix: concise imperative title matching upstream's commit style
## Problem
Describe what was broken and why it mattered.
## Solution
Explain what the fix does. Reference the functions/files changed.
## Testing
How to verify the fix works. Include commands if applicable.
EOF
git add PULL_REQUEST_DRAFT.md
git commit --amend --no-edit # or: git commit -m "..." if draft is a separate commit
For multi-commit PRs, include PULL_REQUEST_DRAFT.md in every commit
(use git commit --amend or update it at each step). The file should always
reflect the PR's current intended title and description.
6. Push the branch to origin
git push origin <branch-name>
Note: the agent cannot push to GitHub. Remind the user to run ghpp on atom
or use git push from a machine with push access.
7. Submit the PR (submission step)
When the branch is ready to submit, use the helper script:
# From the repo root, with the PR branch checked out:
bash /path/to/skills-akaihola/upstream-pr/scripts/submit-pr.sh [--upstream-repo OWNER/REPO]
The script:
- Reads
PULL_REQUEST_DRAFT.mdand extracts title + body - Shows a preview and asks for confirmation
- Runs
git rm PULL_REQUEST_DRAFT.md && git commit -m "chore: remove PR draft before submission" - Runs
git push origin <branch>(if needed) - Runs
gh pr create --repo OWNER/REPO --title "..." --body "..."
Manual equivalent (if not using the script):
TITLE=$(grep -m1 '^# ' PULL_REQUEST_DRAFT.md | sed 's/^# //')
BODY=$(tail -n +2 PULL_REQUEST_DRAFT.md | sed '1{/^$/d}')
git rm PULL_REQUEST_DRAFT.md
git commit -m "chore: remove PR draft before submission"
git push origin <branch>
gh pr create --repo OWNER/REPO --title "$TITLE" --body "$BODY"
Handling Conflicts
When cherry-picking produces conflicts:
- Inspect the conflict with
git diffand understand both sides. - Resolve by keeping the most correct version — usually upstream's recent refactors plus your new logic on top.
git addresolved files, thengit cherry-pick --continue.- Do not use
--strategy-option theirs/oursblindly — read the conflict.
Verifying the Branch is Clean
Before pushing, confirm the branch only contains what you intend:
# Should list only your PR commits
git log --oneline upstream/main..<branch>
# Should show only your intended file changes
git diff --stat upstream/main...<branch>
# PULL_REQUEST_DRAFT.md must be present
git show HEAD:PULL_REQUEST_DRAFT.md | head -3
Keeping Branches Updated
If upstream/main advances while your PR is under review:
git fetch upstream
git rebase upstream/main
# Update PULL_REQUEST_DRAFT.md if anything changed
git push --force-with-lease origin <branch>
Example: Full Single-Fix PR
cd ~/mitto
git fetch upstream
git checkout -b fix/my-bug-fix upstream/main
git cherry-pick abc1234
cat > PULL_REQUEST_DRAFT.md << 'EOF'
# fix(web): correct the thing that was broken
## Problem
Widget exploded when user did X.
## Solution
Guard against nil pointer in `handleFoo()`.
## Testing
`go test ./internal/web/...` passes. Manually verified: X no longer explodes.
EOF
git add PULL_REQUEST_DRAFT.md
git commit --amend --no-edit
git push origin fix/my-bug-fix
# Then ask the user to push with `ghpp` on atom, or run the submit script
Notes
- Always target
upstream/mainas the base, notorigin/mainormain. - Always verify the fix is not already upstream before creating a branch.
- If the upstream repo uses squash-merge, a single commit per PR is cleaner.
- Keep PR branches focused: one logical change per branch.
- Close the corresponding upstream issue in the PR body with
Fixes #N.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
youtube-to-markdown
Convert a YouTube video into clean, readable Markdown using its free auto-generated captions (no paid API needed). Use when the user asks to "convert YouTube video to markdown", "get transcript from YouTube URL", "summarise this video", or wants to turn YouTube subtitles/captions into readable text. Prefer this over youtube-transcription when the video already has auto-generated subtitles — it's free and faster. Accepts YouTube URLs.
brave-search
Search the web using Brave Search API. Use when the user asks to "search the web", "look up current information", "find news about", "research a topic online", "check prices online", or needs up-to-date facts that may not be in the model's training data. Requires BRAVE_SEARCH_API_KEY. Supports structured web results (pages, FAQs, news, videos) and an optional AI summarizer.
verkkokauppa
Search products on the Verkkokauppa.com Finnish webshop. This skill uses the Verkkokauppa search API directly, requiring no browser. Use when the user asks to "search Verkkokauppa", "find products on verkkokauppa.com", "verkkokauppa product search", "check Verkkokauppa prices", or mentions searching the Verkkokauppa store.
clasohlson
Search products on the Clas Ohlson Finland webshop (clasohlson.com/fi/). This skill uses the Voyado Elevate (Apptus eSales) search API directly, requiring no browser. Use when the user asks to "search Clas Ohlson", "find products on clasohlson.com", "clas ohlson product search", "check Clas Ohlson prices", or mentions searching the Finnish Clas Ohlson store.
bauhaus
Search products on the Bauhaus webshop (bauhaus.fi). This skill uses the Algolia search API with automatic key refresh. Use when the user asks to "search Bauhaus", "find products on bauhaus.fi", "bauhaus product search", "check Bauhaus prices", or mentions searching the Bauhaus store.
library
Didn't find tool you were looking for?