Merge all features
Skill AravindS-Wick/aravindhan-skills/skills/merge-all-features
End-to-end multi-repo feature shipping. Use whenever the user invokes "/merge-all-features" or asks to commit, push, and raise PRs across one or many repos at once. Splits a target folder into independent repos, groups uncommitted changes feature-by-feature, runs ESLint + Jest gates before every commit, commits in dependency order with clean messages (NO co-author trailers), pushes, opens PRs with full descriptions (purpose, file changes, work done, use cases, splatter zone / blast radius, new imports, feature flags, required reviewers, test + lint results), then self-reviews and posts the review on the PR with required actions. Works on a single repo, a folder of repos, or the current directory if it is itself a repo. Spawns parallel subagents (one per repo) on cheap/default models so independent repos progress concurrently. If one repo is blocked, surfaces the blocker to the user in **bold** and keeps going on the others.From its SKILL.md
npx -y skills add AravindS-Wick/aravindhan-skills --skill merge-all-featuresAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
16.5 KB, ~4.0k tokens by cl100k_base, as published. Nobody here has run it
/merge-all-features
Ship feature work across one or many repositories with full automation: detect repos, group changes by feature, gate (lint + test), commit cleanly, push, open detailed PRs, self-review, and report. Independent repos run in parallel. Blocked repos do not stall the rest.
This skill is invoked by the slash command /merge-all-features or by any request matching its description. The orchestrator (you, Claude, in the main thread) is responsible for coordination, the final summary, and any user-facing decisions. Per-repo work is delegated to subagents using cheap/default models.
The hard rules (non-negotiable)
These exist because they protect the user from the most expensive mistakes β broken main branches, unreviewed merges, attribution mistakes, and silent failures.
-
No co-author / co-owner trailers. Commit messages must NOT contain
Co-Authored-By:,Co-Authored:,Signed-off-by: Claude, "π€ Generated with", "Generated by Claude", or any equivalent attribution line. Usegit commit -m "<message>"with a clean body. If you suspect any template might inject these, runscripts/strip_trailers.sh <commit-msg-file>before committing. This rule applies to PR descriptions and review comments too. -
Always stash-backup before any commit or merge. Run
scripts/stash_backup.sh <repo> <feature-name>as the very first action for each feature, before staging or gating. The script creates a named stash (backup/<feature>/<timestamp>), then immediately pops it to restore the working tree β the backup ref stays in the stash list. If the backup fails (e.g. no commits yet), warn the user but continue β do NOT block on stash failure. -
Gates are blocking. ESLint and Jest run before every commit. If either fails, attempt auto-fix once (
eslint --fix), rerun, and if it still fails, STOP that repo β do NOT commit broken code. Mark the repo as blocked, report it, move on. -
One feature per commit by default. Only lump features into a single commit/PR when the user has explicitly said "these can be pushed and lumped together" (or equivalent). Otherwise: one feature β one commit β one PR.
-
Correct order matters. Commit in dependency order: config/types β core libs β consumers β tests/docs. If feature B imports from feature A, A commits first.
-
Blocked β stopped. When a repo is blocked, alert the user in bold with the repo name and reason. Then keep going β other repos in the run continue in parallel. Never abandon the whole run for a single repo's blocker.
-
Detect, don't assume. The target may be a single repo (
.gitat root), a folder of repos (multiple subdirs with.git), or.itself. Detect viascripts/detect_repos.shbefore doing anything else.
High-level workflow
1. RESOLVE TARGET β which folder, what repos live in it
2. SCOPE PER REPO β uncommitted changes grouped into features
3. CONFIRM PLAN β show the user the per-repo feature plan, get OK
4. SPAWN SUBAGENTS β one per repo, parallel, cheap model
5. EACH SUBAGENT runs: stash-backup β branch β gate β commit β push β PR β self-review β post
6. AGGREGATE REPORT β collected status per repo, blockers in bold
The orchestrator handles 1β4 and 6. The subagent prompt (defined below) handles 5.
Step 1 β Resolve target
Default target is the user's current working directory unless they specified a path. Run:
bash scripts/detect_repos.sh "$TARGET_DIR"
It prints one absolute repo path per line. Three cases:
- 0 repos β tell the user, stop. Don't initialise anything without their say-so.
- 1 repo β single-repo flow; still uses the same subagent path for consistency.
- N repos β multi-repo flow; N subagents in parallel.
Step 2 β Scope changes per repo
For each repo, gather:
cd "$repo" && git status --porcelain=v1 -uall
cd "$repo" && git diff --stat HEAD
cd "$repo" && git log -1 --format=%H 2>/dev/null # is there even a HEAD?
Then group changes into features. A "feature" is a coherent set of file changes that belong together by intent β not by directory. Heuristics (apply in order):
- Explicit hints from the user's message (e.g., "the auth changes and the schema changes").
- File path clusters β files under the same module path (
src/auth/*,src/payments/*) usually go together. - Diff inspection β read the actual diff hunks. If function
foocalls a new functionbarand both are in the diff, they're one feature. - Test pairing β a source file and its
__tests__/.test.ts/.spec.tsbelong to the same feature. - Config separation β
package.json,tsconfig.json, lockfiles, and CI configs get their own feature unless they're clearly part of one feature's setup.
Each feature gets:
name: short kebab-case (e.g.,add-jwt-refresh)files: list of changed pathssummary: one sentenceorder: integer, dependency order (lower commits first)imports_introduced: new imports anywhere in the diffflags_introduced: any feature flags / env vars addedsplatter_zone: what else in the repo could be affected (callers of changed functions, anything importing the changed files)
Reference references/feature-grouping.md for the grouping rubric in detail.
Step 3 β Confirm the plan with the user
Before spawning any subagents, show the user a compact plan:
Repo: web-app (3 features)
1. add-jwt-refresh β src/auth/*.ts (5 files) [order: 1]
2. fix-payment-rounding β src/payments/total.ts (1 file) [order: 2]
3. update-readme β README.md (1 file) [order: 3]
Repo: mobile-app (1 feature)
1. wire-auth-refresh β src/screens/Login.tsx (2 files) [order: 1]
Lump together? (default: no, one PR per feature)
Wait for confirmation. If the user says "lump features 1 and 2 in web-app", merge those into one feature for that repo and re-show. Only proceed once they approve.
Step 4 β Spawn subagents in parallel
For each repo, spawn one subagent in the SAME turn (parallel). Subagents use the cheapest available model β they don't need deep reasoning, just careful execution of the per-repo recipe.
Subagent prompt template:
You are a per-repo execution agent for /merge-all-features. Use the cheapest available model. Do NOT add co-author trailers, signoffs, or "Generated with" lines to any commit or PR.
Repo: <absolute path>
Base branch: <main / master / detected>
Features (in commit order):
<JSON list with name, files, summary, order, imports_introduced, flags_introduced, splatter_zone>
For EACH feature, in order, do:
1. Stash backup FIRST: `bash <skill-path>/scripts/stash_backup.sh "<repo>" "<feature-name>"`
If it prints STASH_SKIP or warns (no HEAD yet), log the warning and continue β do NOT block.
2. Stage exactly that feature's files: `git add <files>` (no `git add .`)
3. Run gates from the orchestrator's skill scripts:
bash <skill-path>/scripts/run_gates.sh "<repo>" "<files>"
If exit 0 β continue. If exit non-zero β stop this repo, write blocker reason to <workspace>/<repo-name>/BLOCKED.md, exit 0 from the agent (do NOT crash the orchestrator).
4. Create branch: feat/<feature-name> off latest base branch (rebase if needed).
5. Commit: `git commit -m "<type>(<scope>): <summary>"` β clean message, no trailers.
6. Push: `git push -u origin feat/<feature-name>`
7. Detect host: orchestrator passes HOST=github|gitlab based on remote URL.
8. Build PR body from template at <skill-path>/references/pr-description-template.md, filled with feature data.
9. Open PR:
- github β `gh pr create --title "<title>" --body-file <body-path> --base <base>`
- gitlab β `glab mr create --title "<title>" --description "$(cat <body-path>)" --target-branch <base>`
10. Self-review using <skill-path>/references/pr-review-checklist.md against the diff. Produce two artifacts:
- REVIEW.md (the review itself)
- REQUIRED_ACTIONS.md (concrete TODOs)
11. Post review:
- github β `gh pr review <pr> --comment --body-file REVIEW.md`
then `gh pr comment <pr> --body-file REQUIRED_ACTIONS.md`
- gitlab β `glab mr note <mr> --message "$(cat REVIEW.md)"` and another for required actions.
12. Write SUCCESS.md with: PR URL, commit SHA, branch name, stash ref, gate results, review summary.
Output: write all artifacts to <workspace>/<repo-name>/feature-<N>/ as you go. Final line of your response: either "OK <repo-name>" or "BLOCKED <repo-name>: <reason>".
Spawn ALL subagents in one turn. Do not await one before launching the next.
Step 5 β Per-repo execution (what the subagent does)
This is what each subagent runs. The orchestrator doesn't run these directly; they're documented here so the subagent prompt above has a reference.
5a. Stash backup (always first)
bash "$SKILL_PATH/scripts/stash_backup.sh" "$repo" "$FEATURE_NAME"
# Output: STASH_OK backup/<feature>/<timestamp> β log the ref in SUCCESS.md
# STASH_SKIP β log "nothing to stash", continue
# Any error β warn user, continue (not a blocker)
To recover from a stash backup later:
git stash list | grep "backup/<feature-name>"
git stash apply stash@{N} # N = the matching stash index
5b. Branch setup
cd "$repo"
git fetch origin
BASE=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
git checkout -b "feat/$FEATURE_NAME" "origin/$BASE"
5c. Stage exact files for this feature
git add -- "${FEATURE_FILES[@]}"
git status --porcelain # verify nothing extra got staged
5d. Run gates (blocking)
bash "$SKILL_PATH/scripts/run_gates.sh" "$repo" "${FEATURE_FILES[@]}"
The script runs ESLint (only on staged JS/TS files) and Jest (related tests via --findRelatedTests). It exits 0 on green, non-zero on failure. On failure, the subagent attempts eslint --fix once, re-runs, and if still red, writes BLOCKED.md with the failing output and exits.
5e. Commit (clean message, no trailers)
COMMIT_MSG="$(printf '%s(%s): %s' "$TYPE" "$SCOPE" "$SUMMARY")"
git commit -m "$COMMIT_MSG"
# Verify no trailers leaked in:
bash "$SKILL_PATH/scripts/strip_trailers.sh" HEAD
Conventional commit types: feat, fix, chore, refactor, docs, test, perf, build, ci. The scope is the feature's primary module.
5f. Push
git push -u origin "feat/$FEATURE_NAME"
If push is rejected (non-fast-forward, protected branch, etc.) β BLOCKED.
5g. Build PR body
Use references/pr-description-template.md. Fill placeholders with feature data:
{{PURPOSE}}β what this feature is for, in plain language{{FILE_CHANGES}}β bulleted list of changed files with a one-line "why" each{{WORK_DONE}}β what kind of work (refactor / new module / bug fix / config / etc.){{USE_CASES}}β when/how someone would use this{{SPLATTER_ZONE}}β blast radius: callers, importers, downstream effects{{NEW_IMPORTS}}β any new packages or internal modules pulled in{{FEATURE_FLAGS}}β flags/env vars introduced to gate this{{REQUIRED_REVIEWERS}}β codeowners / domain experts; pull from CODEOWNERS if present{{TEST_RESULTS}}β output ofjest --listTests+ pass/fail summary{{LINT_RESULTS}}β "clean" or the leftover warnings
5g. Open PR
Detect host once per repo:
REMOTE=$(git remote get-url origin)
case "$REMOTE" in
*github.com*) HOST=github ;;
*gitlab.com*|*gitlab.*) HOST=gitlab ;;
*) HOST=unknown ;;
esac
If HOST=unknown, push the branch and surface a manual-PR-needed note (not a blocker for the rest of the run).
5h. Self-review and post
See references/pr-review-checklist.md for the checklist. Produce REVIEW.md (findings, severity tagged) and REQUIRED_ACTIONS.md (numbered list of concrete fixes). Post both to the PR.
Step 6 β Aggregate and report
Once all subagents finish, build the final report:
β
web-app
- add-jwt-refresh: merged-ready, PR #142, review posted (2 required actions)
- fix-payment-rounding: merged-ready, PR #143, review posted (0 required actions)
- update-readme: merged-ready, PR #144, review posted (0 required actions)
**π« BLOCKED: payments-svc**
- reason: jest failure in src/totals.test.ts β calculateTax expected 110, got 99
- 3 features queued; none committed
- action needed: fix the failing test or update the expected value
β
mobile-app
- wire-auth-refresh: merged-ready, PR #58, review posted (1 required action)
Blocked repos are reported in bold with the repo name and reason. The orchestrator does NOT abandon the run when one repo blocks β by Step 6, all other repos have already completed in parallel.
If multiple repos were touched and any are blocked, the orchestrator also checks: "are there other repos in this folder that weren't part of this run but have uncommitted changes?" If yes, mention them at the bottom β the user may want a follow-up run.
Edge cases to handle gracefully
- Detached HEAD or rebase in progress β BLOCKED, surface the git state to the user.
- No remote β push step is skipped, PR step is skipped, report says "local commit only".
- Protected base branch / push rejected β BLOCKED with the exact rejection message.
- No ESLint config in repo β skip lint gate, note in PR body "no ESLint config detected".
- No Jest in repo β skip Jest gate, note in PR body "no Jest detected". (Future: pluggable test runners.)
- Binary files or generated files staged β flag in plan step; ask user to confirm before committing.
.env, secrets, credentials staged β HARD STOP for that repo, blocker, do not push.- Existing PR on the same branch β update the PR (push to the existing branch) rather than opening a duplicate.
- No CODEOWNERS β leave
{{REQUIRED_REVIEWERS}}as "none auto-detected; add reviewers manually".
Reference files
references/pr-description-template.mdβ the exact PR body structurereferences/pr-review-checklist.mdβ what to check during self-reviewreferences/feature-grouping.mdβ the rubric for grouping uncommitted changes
Scripts
scripts/stash_backup.shβ create named stash backup before any commit; pops immediately to restore working tree; warns but never blocksscripts/detect_repos.shβ find git repos in a folder, or treat the folder as a reposcripts/run_gates.shβ run ESLint + Jest on staged files, exit non-zero on failurescripts/strip_trailers.shβ verify a commit has no co-author / signoff trailersscripts/group_features.pyβ heuristic grouping of uncommitted changes into featuresscripts/make_pr_body.pyβ assemble the PR description from template + feature data
Recovering from a stash backup
If a commit or merge goes wrong, recover with:
git stash list | grep "backup/" # find your backup
git stash apply stash@{N} # restore it (N = index from list)
A note on tone in user-facing output
- Blockers in bold. Don't bury them.
- One line per PR in the summary β the user wants to scan, not read.
- Don't claim a PR is "ready to merge" unless the gates passed and the self-review found no high-severity issues.
- If a self-review finds something serious (security, broken interface, missing tests for new branching logic), flag it as
severity: highin REQUIRED_ACTIONS.md and mention it in the summary line for that PR.
What ships with it: 12 files
31.6 KB alongside SKILL.md, 7 of them executable
assets/
- example_asset.txt865 B
references/
- api_reference.md969 B
- feature-grouping.md3.9 KB
- pr-description-template.md3.8 KB
- pr-review-checklist.md4.5 KB
scripts/
- detect_repos.shruns185 B
- example.pyruns595 B
- group_features.pyruns8.6 KB
- make_pr_body.pyruns3.0 KB
- run_gates.shruns2.7 KB
- stash_backup.shruns865 B
- strip_trailers.shruns1.8 KB