jwx-companion-bulk
Apply a uniform operation across jwx companion modules (github.com/jwx-go/*).
Handles cloning, branching, applying changes, verifying, committing, and reporting.
Arguments
/jwx-companion-bulk <instructions...>
$INSTRUCTIONS (required) — what to do across companion modules. Free-form text.
Flags (parsed from instructions)
--modules=<name,name,...> — target only these modules (comma-separated names)
--ref-module=<name> — use this module as the reference/template for file-copy operations
--pr — push branches and create PRs (off by default; commits locally only)
--dry-run — show what would change without modifying anything
If instructions are ambiguous, ask the user before proceeding.
1. Read Config
- Read
companions.yaml from the project root.
- Parse the
modules list. Each entry has: name, repo, branch.
- If
--modules= was provided, filter to only those names. Error if a name is not found.
2. Ensure Clones
For each module in the (filtered) list:
If $PROJECT/.companions/repo/<name>/ does not exist:
cd $PROJECT
git clone <repo> .companions/repo/<name>
If it already exists, update it:
cd $PROJECT/.companions/repo/<name>
git fetch origin
Determine the default branch for each module:
Checkout the default branch:
cd $PROJECT/.companions/repo/<name>
git checkout <default-branch>
cd $PROJECT/.companions/repo/<name>
git pull --ff-only
3. Pre-flight Checks
Run these on ALL targeted modules BEFORE modifying ANY:
Clean working tree: git status --porcelain must produce empty output.
If any module is dirty, report which ones and STOP.
Remote reachable (only if --pr): git ls-remote origin HEAD must succeed.
gh auth (only if --pr): gh auth status must succeed.
If pre-flight fails, report the failures and stop. Do not partially proceed.
4. Determine Execution Strategy
Decide whether this is a mechanical or creative operation:
- Mechanical (same change replicated): dependency bumps, file sync/copy,
adding identical files, updating CI workflows, version string changes.
- Creative (independent work per module): lint-fix, refactor, bug fixes,
anything where changes differ per module.
Heuristics:
- Keywords "fix", "refactor", "lint" suggest creative.
- Keywords "update", "sync", "add", "copy", "bump" suggest mechanical.
When unsure, ask the user: "Same mechanical change per module, or independent work per module?"
Mechanical: Prototype then Replicate
- Pick first module from list (or
--ref-module if specified).
- Create a feature branch from the module's default branch:
cd $PROJECT/.companions/repo/<name>
git checkout -b <branch-name> <default-branch>
Use ordinary branch naming: <category>-<short-description> (e.g. chore-bump-jwx-dep).
- Apply instructions to this module.
- Verify (if module has
go.mod):cd $PROJECT/.companions/repo/<name>
go build ./...
cd $PROJECT/.companions/repo/<name>
golangci-lint run ./...
- Record exactly what changed: files modified/added/deleted, nature of change.
- For each remaining module:
a. Create feature branch (same name).
b. Replicate the change, adapting module-specific values (module name in
import paths, go.mod module path, etc.).
c. Verify (go build + golangci-lint if has go.mod).
d. If verification fails, revert (
git checkout .), delete the branch,
record failure, continue to next module.
Creative: Parallel Subagents
- Spawn one Agent per module, all in a single parallel block.
- Each agent receives:
- Module path:
$PROJECT/.companions/repo/<name>
- Default branch name
- The instructions
- Directions to: create a feature branch, do the work, verify, commit.
- Subagents do NOT have Skill tool access. Give them explicit instructions.
- Wait for all agents, collect results.
5. Commit
For each module where changes were made and verification passed:
- Stage relevant files:
cd $PROJECT/.companions/repo/<name>
git add <files>
- Commit following standard commit message rules.
6. PR (only with --pr)
For each module where changes were committed:
- Push the feature branch:
cd $PROJECT/.companions/repo/<name>
git push -u origin <branch-name>
- Create PR:
cd $PROJECT/.companions/repo/<name>
gh pr create --title "<title>" --body "<body>"
Target the module's default branch.
- Record PR URL.
7. Report
Always end with a report:
## Companion Module Bulk Operation Report
**Operation**: <summary of instructions>
**Date**: YYYY-MM-DD
**Modules targeted**: N
**Succeeded**: X | **Skipped**: Y | **Failed**: Z
| Module | Branch | Status | PR | Notes |
|--------|--------|--------|----|-------|
| ... | ... | success/skipped/failed | URL or — | ... |
### Files Changed
- <list of files modified across modules>
### Errors (if any)
- **<module>**: <error description>
Adaptation Rules
When replicating changes across modules, adapt these patterns:
| Pattern |
Adaptation |
Module name in go.mod |
Read actual module path from the target's go.mod |
| Module name in CI YAML |
Package-specific test paths |
| Import paths |
Adjust jwx-go/<proto> to jwx-go/<target> |
| Default branch |
Use branch from companions.yaml for each module |
Modules without go.mod (benchmarks) |
Skip Go-specific steps (build, lint, dep update) |
Error Handling
| Error |
Response |
| Dirty working tree |
STOP entirely (pre-flight) |
go build fails after change |
Revert, record failure, continue others |
golangci-lint fails after change |
Revert, record failure, continue others |
| Module not applicable (e.g. no go.mod for dep update) |
Skip, report "not applicable" |
| PR creation fails |
Report failure, branch still pushed |
| Git push fails |
Report, do not retry, continue others |
| File already matches desired state |
Report "already up to date", skip |
Hard Rules
- NEVER commit directly to default branch — always create a feature branch.
- NEVER force-push.
- NEVER proceed on a module with dirty working tree.
- ALWAYS run pre-flight on ALL modules before modifying ANY.
- ALWAYS verify
go build ./... and golangci-lint run ./... before committing (for modules with go.mod).
- ALWAYS report per-module results even on partial failure.
- ALWAYS
cd into $PROJECT/.companions/repo/<name> before running ANY command (git, go, golangci-lint) for that module. NEVER use git -C, --git-dir, or --work-tree instead — they don't apply to non-git tools, and the shell's working directory stays in the parent jwx repo so its git context leaks through.
- NEVER use compound commands (
&&, ||, ;) in Bash calls.
- PRs are OFF by default. Only push/create PRs when
--pr is specified.
Source: lestrrat-go/jwx — distributed by TomeVault.
1---2name: lestrrat-go-jwx-jwx3description: jwx-companion-bulk4---56# jwx-companion-bulk78Apply a uniform operation across jwx companion modules (github.com/jwx-go/*).9Handles cloning, branching, applying changes, verifying, committing, and reporting.1011## Arguments1213`/jwx-companion-bulk <instructions...>`1415- `$INSTRUCTIONS` (required) — what to do across companion modules. Free-form text.1617### Flags (parsed from instructions)1819- `--modules=<name,name,...>` — target only these modules (comma-separated names)20- `--ref-module=<name>` — use this module as the reference/template for file-copy operations21- `--pr` — push branches and create PRs (off by default; commits locally only)22- `--dry-run` — show what would change without modifying anything2324If instructions are ambiguous, ask the user before proceeding.2526## 1. Read Config27281. Read `companions.yaml` from the project root.292. Parse the `modules` list. Each entry has: `name`, `repo`, `branch`.303. If `--modules=` was provided, filter to only those names. Error if a name is not found.3132## 2. Ensure Clones3334For each module in the (filtered) list:35361. If `$PROJECT/.companions/repo/<name>/` does not exist:37 ```38 cd $PROJECT39 git clone <repo> .companions/repo/<name>40 ```41422. If it already exists, update it:43 ```44 cd $PROJECT/.companions/repo/<name>45 git fetch origin46 ```47483. Determine the default branch for each module:49 - If `branch` is set in the config, use that.50 - Otherwise, read `origin/HEAD`:51 ```52 cd $PROJECT/.companions/repo/<name>53 git symbolic-ref refs/remotes/origin/HEAD54 ```55 This returns e.g. `refs/remotes/origin/develop/v4` — strip the prefix.56 - If `origin/HEAD` is not set, query GitHub:57 ```58 gh repo view <org>/<name> --json defaultBranchRef --jq .defaultBranchRef.name59 ```60614. Checkout the default branch:62 ```63 cd $PROJECT/.companions/repo/<name>64 git checkout <default-branch>65 ```66 ```67 cd $PROJECT/.companions/repo/<name>68 git pull --ff-only69 ```7071## 3. Pre-flight Checks7273Run these on ALL targeted modules BEFORE modifying ANY:74751. **Clean working tree**: `git status --porcelain` must produce empty output.76 If any module is dirty, report which ones and STOP.77782. **Remote reachable** (only if `--pr`): `git ls-remote origin HEAD` must succeed.79803. **gh auth** (only if `--pr`): `gh auth status` must succeed.8182If pre-flight fails, report the failures and stop. Do not partially proceed.8384## 4. Determine Execution Strategy8586Decide whether this is a **mechanical** or **creative** operation:8788- **Mechanical** (same change replicated): dependency bumps, file sync/copy,89 adding identical files, updating CI workflows, version string changes.90- **Creative** (independent work per module): lint-fix, refactor, bug fixes,91 anything where changes differ per module.9293Heuristics:94- Keywords "fix", "refactor", "lint" suggest creative.95- Keywords "update", "sync", "add", "copy", "bump" suggest mechanical.9697When unsure, ask the user: "Same mechanical change per module, or independent work per module?"9899### Mechanical: Prototype then Replicate1001011. Pick first module from list (or `--ref-module` if specified).1022. Create a feature branch from the module's default branch:103 ```104 cd $PROJECT/.companions/repo/<name>105 git checkout -b <branch-name> <default-branch>106 ```107 Use ordinary branch naming: `<category>-<short-description>` (e.g. `chore-bump-jwx-dep`).1083. Apply instructions to this module.1094. Verify (if module has `go.mod`):110 ```111 cd $PROJECT/.companions/repo/<name>112 go build ./...113 ```114 ```115 cd $PROJECT/.companions/repo/<name>116 golangci-lint run ./...117 ```1185. Record exactly what changed: files modified/added/deleted, nature of change.1196. For each remaining module:120 a. Create feature branch (same name).121 b. Replicate the change, adapting module-specific values (module name in122 import paths, go.mod module path, etc.).123 c. Verify (go build + golangci-lint if has go.mod).124 d. If verification fails, revert (`git checkout .`), delete the branch,125 record failure, continue to next module.126127### Creative: Parallel Subagents1281291. Spawn one Agent per module, all in a single parallel block.1302. Each agent receives:131 - Module path: `$PROJECT/.companions/repo/<name>`132 - Default branch name133 - The instructions134 - Directions to: create a feature branch, do the work, verify, commit.1353. Subagents do NOT have Skill tool access. Give them explicit instructions.1364. Wait for all agents, collect results.137138## 5. Commit139140For each module where changes were made and verification passed:1411421. Stage relevant files:143 ```144 cd $PROJECT/.companions/repo/<name>145 git add <files>146 ```1472. Commit following standard commit message rules.148149## 6. PR (only with `--pr`)150151For each module where changes were committed:1521531. Push the feature branch:154 ```155 cd $PROJECT/.companions/repo/<name>156 git push -u origin <branch-name>157 ```1582. Create PR:159 ```160 cd $PROJECT/.companions/repo/<name>161 gh pr create --title "<title>" --body "<body>"162 ```163 Target the module's default branch.1643. Record PR URL.165166## 7. Report167168Always end with a report:169170```171## Companion Module Bulk Operation Report172173**Operation**: <summary of instructions>174**Date**: YYYY-MM-DD175**Modules targeted**: N176**Succeeded**: X | **Skipped**: Y | **Failed**: Z177178| Module | Branch | Status | PR | Notes |179|--------|--------|--------|----|-------|180| ... | ... | success/skipped/failed | URL or — | ... |181182### Files Changed183- <list of files modified across modules>184185### Errors (if any)186- **<module>**: <error description>187```188189## Adaptation Rules190191When replicating changes across modules, adapt these patterns:192193| Pattern | Adaptation |194|---------|-----------|195| Module name in `go.mod` | Read actual module path from the target's `go.mod` |196| Module name in CI YAML | Package-specific test paths |197| Import paths | Adjust `jwx-go/<proto>` to `jwx-go/<target>` |198| Default branch | Use `branch` from `companions.yaml` for each module |199| Modules without `go.mod` (benchmarks) | Skip Go-specific steps (build, lint, dep update) |200201## Error Handling202203| Error | Response |204|-------|----------|205| Dirty working tree | STOP entirely (pre-flight) |206| `go build` fails after change | Revert, record failure, continue others |207| `golangci-lint` fails after change | Revert, record failure, continue others |208| Module not applicable (e.g. no go.mod for dep update) | Skip, report "not applicable" |209| PR creation fails | Report failure, branch still pushed |210| Git push fails | Report, do not retry, continue others |211| File already matches desired state | Report "already up to date", skip |212213## Hard Rules214215- NEVER commit directly to default branch — always create a feature branch.216- NEVER force-push.217- NEVER proceed on a module with dirty working tree.218- ALWAYS run pre-flight on ALL modules before modifying ANY.219- ALWAYS verify `go build ./...` and `golangci-lint run ./...` before committing (for modules with go.mod).220- ALWAYS report per-module results even on partial failure.221- ALWAYS `cd` into `$PROJECT/.companions/repo/<name>` before running ANY command (git, go, golangci-lint) for that module. NEVER use `git -C`, `--git-dir`, or `--work-tree` instead — they don't apply to non-git tools, and the shell's working directory stays in the parent jwx repo so its git context leaks through.222- NEVER use compound commands (`&&`, `||`, `;`) in Bash calls.223- PRs are OFF by default. Only push/create PRs when `--pr` is specified.224225---226> Source: [lestrrat-go/jwx](https://github.com/lestrrat-go/jwx) — distributed by [TomeVault](https://tomevault.io).227<!-- tomevault:4.0:skill_md:2026-06-27 -->