upstream-patches — Claude Code skill: what it does, how to install
Manages Terraform provider submodule patches using ./scripts/upstream.sh. Useful for provider upgrades, resolving patch conflicts, and rebasing.
npx skills add pulumi/agent-skills --skill upstream-patches -a claude-codeWhat upstream-patches does
This skill guides the agent through modifying code inside the upstream/ git submodule and updating files in patches/. It locates the target patch using rg or grep, enters checkout mode with ./scripts/upstream.sh checkout, and amends the owning commit directly instead of generating new patch files.
Direct changes inside upstream/ get wiped during upgrade-provider runs because the automation resets submodule status. Every edit must follow the strict checkout and check_in cycle. If an operation gets interrupted, running ./scripts/upstream.sh init -f discards all in-flight resolutions and untracked files, so routine recovery relies on finishing git am steps manually instead.
What it helps with
- locate the patch file and commit responsible for specific lines
- amend an existing patch without creating extra patch files
- strip unwanted file changes or hunks from an active patch
- rebase provider patches onto a newer upstream git commit
Example prompts for the agent
- Find which patch touches
resource_server.goand amend it with the fix - Rebase our provider patches onto upstream commit
a1b2c3d - Remove
patches/0002-fix-timeout.patchand run./scripts/upstream.sh check_in
How to install upstream-patches
1Skills CLI (Vercel)
npx skills add pulumi/agent-skills --skill upstream-patches -a claude-code2Manually: put the files in place
~/.claude/skills/upstream-patches/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/upstream-patches/
1Skills CLI (Vercel)
npx skills add pulumi/agent-skills --skill upstream-patches -a codex2Manually: put the files in place
.agents/skills/upstream-patches/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add pulumi/agent-skills --skill upstream-patches -a cursor2Manually: put the files in place
.cursor/skills/upstream-patches/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install pulumi/agent-skills upstream-patches2Manually: put the files in place
.github/skills/upstream-patches/SKILL.md1Skills CLI (Vercel)
npx skills add pulumi/agent-skills --skill upstream-patches -a gemini-cli2Platform CLI
gemini skills install https://github.com/pulumi/agent-skills --path package-maintenance/skills/upstream-patchesManually: put the files in place
.devin/skills/upstream-patches/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add pulumi/agent-skills --skill upstream-patches -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about upstream-patches
How to install upstream-patches in Claude Code?
Run npx skills add pulumi/agent-skills --skill upstream-patches -a claude-code.
What does the upstream-patches skill do?
It provides step-by-step procedures for managing Terraform provider submodule patches via ./scripts/upstream.sh. The agent avoids dirty submodule states and updates existing patches cleanly during provider upgrades.
Why avoid editing files directly in the upstream directory?
Edits made outside the ./scripts/upstream.sh checkout workflow are ephemeral. The upgrade-provider tool resets the submodule, which immediately destroys uncommitted or non-checked-in file edits.
Source text
SKILL.md · Apache-2.0
---
name: upstream-patches
description: Create, amend, remove, and rebase patches for Terraform provider submodules using `./scripts/upstream.sh`. Use when `upgrade-provider` or manual patch work needs owning-patch lookup, patch conflict fixes, patch/hunk removal, or upstream rebase.
---
# Upstream Patches
`upstream/` is a git submodule pointing to the upstream Terraform provider. `patches/` contains patch files applied on top of it. Use `./scripts/upstream.sh` to manage patch state.
## Default Behavior
- If fixing a regression introduced by an existing patch, amend the owning patch commit.
- Do not create a new patch unless the user explicitly asks.
## Commands Reference
| Command | Description |
|---------|-------------|
| `./scripts/upstream.sh init` | Initialize upstream and apply patches to working directory |
| `./scripts/upstream.sh init -f` | Destructively discard checkout/rebase state and re-initialize upstream |
| `./scripts/upstream.sh checkout` | Create branch with patches as commits for editing |
| `./scripts/upstream.sh rebase -i` | Interactively edit patch commits |
| `./scripts/upstream.sh rebase -o <commit>` | Rebase patches onto a new upstream commit |
| `./scripts/upstream.sh check_in` | Write commits back to patches and exit checkout mode |
## Guardrails
- Never commit directly to `upstream/` without `checkout/check_in`.
- Direct edits under `upstream/` outside checkout are ephemeral during `upgrade-provider`; the tool resets submodule state.
- Do not hand-edit `patches/*.patch` unless intentionally doing raw patch surgery.
- Prefer non-interactive rewrite flow over interactive rebase for agents.
## Find Owning Patch First
Before editing patch content, identify the owning patch/commit.
```bash
./scripts/upstream.sh checkout
# Find candidate patch files by touched file path or unique hunk text
rg -n "path/to/file|unique_symbol" patches/*.patch
# Optional: inspect candidate patch header/hunks
sed -n '1,120p' patches/00NN-Example.patch
# Map patch file to commit in upstream checkout branch
patch=patches/00NN-Example.patch
subject=$(sed -n 's/^Subject: \[PATCH\] //p' "$patch" | head -n1)
cd upstream
git log --oneline pulumi/patch-checkout --grep "$subject"
# If needed, disambiguate by touched path
git log --oneline pulumi/patch-checkout -- path/to/file
cd ..
```
If `rg` is unavailable, use `grep -En` for the patch search. Set `target_sha` to the owning commit and edit that commit, not `HEAD`.
## Amend Existing Patch (Preferred, Non-Interactive)
```bash
./scripts/upstream.sh checkout
cd upstream
target_sha=<owning-commit-sha>
base_sha=$(git rev-parse "${target_sha}^")
tmp_branch="rewrite-${target_sha:0:8}"
# Rebuild history from parent of target commit
git checkout -b "$tmp_branch" "$base_sha"
git cherry-pick "$target_sha"
# Apply fix and amend target commit
# ...edit files...
git add <files>
git commit --amend --no-edit
# Replay remaining commits
git cherry-pick "${target_sha}..pulumi/patch-checkout"
# If cherry-pick conflicts occur:
# resolve files
# git add <resolved files>
# git cherry-pick --continue
# Move checkout branch to rewritten history
git branch -f pulumi/patch-checkout HEAD
git checkout pulumi/patch-checkout
git branch -D "$tmp_branch"
cd ..
```
Interactive fallback:
```bash
./scripts/upstream.sh checkout
./scripts/upstream.sh rebase -i
# mark target commit as edit, amend, then continue
```
## Remove Entire Patch
Use when a patch should be deleted completely.
```bash
rm patches/00NN-Description.patch
./scripts/upstream.sh checkout
./scripts/upstream.sh check_in
```
## Remove Part of a Patch
Use when only selected hunks/files should be removed from an existing patch.
1. Find owning patch/commit (`target_sha`) and use the amend workflow above.
2. Revert only unwanted changes from the target commit, then amend.
Example during amend step:
```bash
cd upstream
# Restore specific docs-only files from parent of amended commit
git checkout HEAD^ -- path/to/docs-only-file path/to/another-doc-file
git add path/to/docs-only-file path/to/another-doc-file
git commit --amend --no-edit
cd ..
```
## Create New Patch (Only If Requested)
```bash
./scripts/upstream.sh checkout
cd upstream
# ...make changes...
git add <files>
git commit -m "Describe new patch"
cd ..
./scripts/upstream.sh check_in
```
## Rebasing Patches to a New Upstream Version
```bash
./scripts/upstream.sh checkout
# Rebase onto the new upstream commit
./scripts/upstream.sh rebase -o <new_commit_sha>
# Resolve any conflicts that arise
# Write updated patch files
./scripts/upstream.sh check_in
```
## Verification Checklist
Before `check_in`:
- Confirm expected patch count change (`0` by default; `-1` for full patch removal).
- Confirm whether target patch should remain present (default yes) or be removed (explicit deletion case).
- Confirm you are editing the owning commit, not adding a new commit by accident.
After `check_in`:
- Verify patch count matches expectation.
- Verify target patch number/purpose is still present when expected.
- Verify no unexpected new `00NN-*.patch` was introduced.
## Interrupted Checkout or Rebase
Preserve work by default. Inspect `git -C upstream status`, complete the active `git am`/rebase, verify that every patch was applied, and run `./scripts/upstream.sh check_in` before rerunning automation. An interrupted checkout invokes `git am` separately for each patch, so later patch files may not have been reached.
Use `./scripts/upstream.sh init -f` only when intentionally discarding all interrupted work. It can remove conflict resolution, patch commits, operation metadata, and untracked files; it is not routine recovery for a stuck checkout.
© pulumi · Apache-2.0 · pulumi/agent-skills