Upstream Skill
Merge upstream template improvements into your branded fork while preserving your project's branding.
Usage
/upstream [command]
Commands:
- •
/upstreamor/upstream sync— Merge latest upstream changes - •
/upstream status— Show upstream remote state and pending changes - •
/upstream remote [url]— Add or update the upstream remote URL
Core Concept
Branded files (listed in .claude/brand.json) are owned by the fork — upstream changes to those files are ignored. The skill merges upstream using git merge --no-commit, then restores branded files to the fork's version with git checkout --ours.
Commands
/upstream or /upstream sync
Merge the latest upstream template changes, skipping branded files.
Step 1: Check for brand.json
Read .claude/brand.json. If it doesn't exist, warn the user:
Warning: .claude/brand.json not found — /brand hasn't been run. Upstream merge will proceed without branded-file protection. You may need to resolve conflicts manually in files that contain your project name.
Ask if they want to continue or run /brand first.
Step 2: Check upstream remote
git remote get-url upstream 2>&1
If no upstream remote exists, ask the user for the template repo URL and add it:
git remote add upstream <url>
Step 3: Fetch upstream
git fetch upstream 2>&1 | tail -n 5
Step 4: Preview changes
Show new upstream commits since last merge:
git log HEAD..upstream/main --oneline --no-decorate 2>&1 | head -20
If there are no new commits, report that the fork is up to date and stop.
Step 5: Categorize changed files
Get the list of files changed upstream:
git diff HEAD...upstream/main --name-only
Compare against brandedFiles from brand.json. Show two lists:
- •Branded (will be skipped): files in both the diff and
brandedFiles - •Clean (will be merged): files in the diff but not in
brandedFiles
Step 6: Confirm
Ask the user to confirm the merge.
Step 7: Merge with --no-commit
git merge upstream/main --no-commit --no-ff 2>&1
Step 8: Restore branded files
For each file in brand.json's brandedFiles array:
git checkout --ours -- <file>
Also restore lock files (these should be regenerated, not merged):
git checkout --ours -- backend/uv.lock 2>/dev/null git checkout --ours -- frontend/pnpm-lock.yaml 2>/dev/null
Stage the restored files:
git add <all restored files>
Step 9: Check for conflicts
git diff --name-only --diff-filter=U
If there are conflicts in non-branded files, show them to the user and help resolve them. These are real conflicts where both sides modified the same non-branded file.
Step 10: Regenerate lock files
cd backend && uv lock 2>&1 | tail -n 5
cd frontend && pnpm install 2>&1 | tail -n 5
Step 11: Show merged changes
Show what's actually being merged (the non-branded changes):
git diff --cached --stat
Step 12: Commit
Suggest a commit message and let the user confirm or edit:
Merge upstream template updates Merged upstream/main, preserving branded files.
git commit -m "<message>"
/upstream status
Show the state of the upstream remote.
Step 1: Check remote
git remote get-url upstream 2>&1
If no remote, tell the user to run /upstream remote <url> first.
Step 2: Fetch and compare
git fetch upstream 2>&1 | tail -n 5 git log HEAD..upstream/main --oneline --no-decorate 2>&1 | head -20
Step 3: Show summary
- •Upstream remote URL
- •Number of commits behind
upstream/main - •List of changed files, marked as branded or clean
/upstream remote [url]
Add or update the upstream remote.
If a URL is provided:
# Check if upstream remote already exists git remote get-url upstream 2>&1
If it exists, update it:
git remote set-url upstream <url>
If it doesn't exist, add it:
git remote add upstream <url>
Then verify:
git remote get-url upstream
If no URL is provided, show the current upstream remote URL.
Edge Cases
- •No brand.json: Proceed with a warning. All files will be merged normally (no branded-file protection). Conflicts are resolved manually.
- •Merge conflicts in non-branded files: These are real conflicts. Show them and help the user resolve each one.
- •Lock files: Always restore to the fork's version and regenerate rather than trying to merge.
- •Dirty working tree: Check
git status --shortbefore merging and warn if dirty.
Important Notes
- •Always protect the context window — use
| tail -n Nand| head -Non git commands that could produce large output. - •Never force-push or use destructive git operations.
- •The merge commit should clearly indicate it's an upstream sync.