Finishing a Development Branch
obra/superpowers
Walks the last step of a branch: confirm tests pass, detect the git environment, ask how to integrate, carry out your choice and clean up the worktree.
Merges a source branch into the current branch across ToolJet's root repo and its server/ee and frontend/ee submodules, handling conflicts and submodule order.
The automated check flagged lines worth reading first. See the safety section below.
$ npx skills add ToolJet/ToolJet --skill merge -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ToolJet/ToolJet merge --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/ToolJet/ToolJet.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/merge .claude/skills/merge && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "merge" agent skill from https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/merge into .claude/skills/merge/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merge", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/mergeType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add ToolJet/ToolJet --skill merge -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ToolJet/ToolJet merge --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ToolJet/ToolJet.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/merge .agents/skills/merge && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "merge" agent skill from https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/merge into .agents/skills/merge/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merge", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ToolJet/ToolJet --skill merge -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ToolJet/ToolJet merge --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ToolJet/ToolJet.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/merge .cursor/skills/merge && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "merge" agent skill from https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/merge into .cursor/skills/merge/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merge", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/ToolJet/ToolJet.git --path .agents/skills/merge--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add ToolJet/ToolJet --skill merge -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ToolJet/ToolJet merge --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ToolJet/ToolJet.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/merge .gemini/skills/merge && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "merge" agent skill from https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/merge into .gemini/skills/merge/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merge", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install ToolJet/ToolJet mergeInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add ToolJet/ToolJet --skill merge -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ToolJet/ToolJet.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/merge .github/skills/merge && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "merge" agent skill from https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/merge into .github/skills/merge/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merge", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ToolJet/ToolJet --skill merge -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ToolJet/ToolJet merge --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ToolJet/ToolJet.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/merge .opencode/skills/merge && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "merge" agent skill from https://github.com/ToolJet/ToolJet/tree/main/.agents/skills/merge into .opencode/skills/merge/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "merge", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
mergeMerges a source branch into the current branch across ToolJet's root repo and its server/ee and frontend/ee submodules, handling conflicts and submodule order.
The skill parses a /merge command: with no argument it merges the branch's base, read from the open PR's base ref or else the remote's default branch; with an argument it treats the whole input as the source branch name, and asks the user when the context points at an unclear release line. It warns that the Bash tool runs in zsh via eval, so for loops break with a 'git: command not found' error and must be avoided in favor of separate per-repo commands, and that coreutils need full paths.
Phase 1 runs a single analysis script that checks each repo's status against the source branch. Phase 2 either reports that everything is already up to date, or processes server/ee, then frontend/ee, then the root in that order, one separate Bash call per not-up-to-date repo: a fast-forward pull when the current branch is the source branch, or a stash, merge and stash-pop sequence when the repo is dirty. It also flags a known gotcha where an untracked file inside a submodule makes the merge commit's lint-staged hook fail, requiring the file to be moved aside, committed around, and restored.
2 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 1786038. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
gitghFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use git and gh, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
ToolJet Multi-Repo Merge loads about 2.1k tokens when it runs. Until then it costs about 63 tokens; SKILL.md has 721 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found patterns that need a careful read before installing.
5. **Do NOT ask for confirmation** — merges are reversible with `git merge --abort`.Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from ToolJet/ToolJet at commit 1786038, republished under its AGPL-3.0 licence (© ToolJet). 721 words, ~2,140 tokens.
.claude/skills/merge/SKILL.md (or your agent's skills folder).Merge a source branch into the current branch across all repos (root + submodules).
User input: $ARGUMENTS
Usage:
/merge # merge the branch's base (open PR base, else main)
/merge main # merge main into current branch
/merge feature/foo # merge feature/foo into current branchParse the input:
With no source given, merge the branch's base:
gh pr view --json baseRefName);main, read from git ls-remote --symref origin HEAD, because a local origin/HEAD goes stale.If the context points at a release line (e.g. an lts-* backport) or is unclear, ask the user.
Gotcha: a merge commit runs the pre-commit hook on every incoming file. An untracked file inside a submodule (e.g. a stray lock file in server/ee) makes lint-staged fail with "Unstaged changes could not be restored". Move such files aside, commit, then put them back.
IMPORTANT: The Bash tool executes in zsh via
eval. Two known constraints:
forloops causegit: command not found— never use loops. Use inline per-repo commands instead.- Always use full paths for coreutils:
/usr/bin/head,/usr/bin/sed,/usr/bin/find.
Run the following script. Replace <source> with the parsed source branch name.
SOURCE="<source>"
ROOT=$(git rev-parse --show-toplevel)
SEE="$ROOT/server/ee"
FEE="$ROOT/frontend/ee"
# Fetch source branch in all repos (sequential — loops are broken in this env)
git -C "$ROOT" fetch origin "$SOURCE" 2>/dev/null
[ -f "$SEE/.git" ] && git -C "$SEE" fetch origin "$SOURCE" 2>/dev/null
[ -f "$FEE/.git" ] && git -C "$FEE" fetch origin "$SOURCE" 2>/dev/null
echo "SOURCE: $SOURCE"
echo "ROOT: $ROOT"
# --- ROOT ---
echo "=ROOT="
echo "branch=$(git -C "$ROOT" rev-parse --abbrev-ref HEAD 2>/dev/null)"
echo "dirty=$(git -C "$ROOT" status --porcelain 2>/dev/null | /usr/bin/head -1)"
_src=$(git -C "$ROOT" ls-remote --heads origin "$SOURCE" 2>/dev/null | /usr/bin/head -1)
if [ -n "$_src" ]; then
echo "source_exists=YES"
git -C "$ROOT" merge-base --is-ancestor "origin/$SOURCE" HEAD 2>/dev/null && echo "up_to_date=YES" || echo "up_to_date=NO"
echo "behind=$(git -C "$ROOT" rev-list HEAD..origin/$SOURCE --count 2>/dev/null)"
else
echo "source_exists=NO"
echo "up_to_date=N/A"
echo "behind=0"
fi
# --- SERVER_EE ---
echo "=SERVER_EE="
if [ -f "$SEE/.git" ]; then
echo "branch=$(git -C "$SEE" rev-parse --abbrev-ref HEAD 2>/dev/null)"
echo "dirty=$(git -C "$SEE" status --porcelain 2>/dev/null | /usr/bin/head -1)"
_src=$(git -C "$SEE" ls-remote --heads origin "$SOURCE" 2>/dev/null | /usr/bin/head -1)
if [ -n "$_src" ]; then
echo "source_exists=YES"
git -C "$SEE" merge-base --is-ancestor "origin/$SOURCE" HEAD 2>/dev/null && echo "up_to_date=YES" || echo "up_to_date=NO"
echo "behind=$(git -C "$SEE" rev-list HEAD..origin/$SOURCE --count 2>/dev/null)"
else
echo "source_exists=NO"
echo "up_to_date=N/A"
echo "behind=0"
fi
else
echo "present=NO"
fi
# --- FRONTEND_EE ---
echo "=FRONTEND_EE="
if [ -f "$FEE/.git" ]; then
echo "branch=$(git -C "$FEE" rev-parse --abbrev-ref HEAD 2>/dev/null)"
echo "dirty=$(git -C "$FEE" status --porcelain 2>/dev/null | /usr/bin/head -1)"
_src=$(git -C "$FEE" ls-remote --heads origin "$SOURCE" 2>/dev/null | /usr/bin/head -1)
if [ -n "$_src" ]; then
echo "source_exists=YES"
git -C "$FEE" merge-base --is-ancestor "origin/$SOURCE" HEAD 2>/dev/null && echo "up_to_date=YES" || echo "up_to_date=NO"
echo "behind=$(git -C "$FEE" rev-list HEAD..origin/$SOURCE --count 2>/dev/null)"
else
echo "source_exists=NO"
echo "up_to_date=N/A"
echo "behind=0"
fi
else
echo "present=NO"
fiParse the output before proceeding to Phase 2.
Print a summary and stop:
All repos are up to date with `<source>`.
| Repo | Branch | Status |
|---|---|---|
| server/ee | <branch> | up to date |
| frontend/ee | <branch> | up to date |
| root | <branch> | up to date |For each repo that is NOT up to date and where source branch EXISTS on remote, run a separate Bash call per repo (do not combine into one script with loops).
git -C <path> pull --ff-only origin <source>git -C <path> stash push -m "merge-auto-stash-$(date +%Y%m%d-%H%M%S)" && git -C <path> merge origin/<source> --no-edit && git -C <path> stash popIf the merge step fails (conflicts): run git -C <path> diff --name-only --diff-filter=U to list conflicted files. Do NOT pop stash. Note as conflicted and continue to the next repo.
git -C <path> merge origin/<source> --no-editIf conflicts, same handling as above.
⚠ <repo>: source branch `<source>` not found on remote — skippingRoot's merge of a submodule pointer can fail with Failed to merge submodule <path> (commits not present). This means the pinned commit is not in the local submodule clone.
Root's gitlink is the authority, not the submodule's own branch. Root main frequently pins submodule commits that are not reachable from the submodule's main — release commits pushed as pointers without a branch. Merging the submodule's origin/main instead produces a pointer that does not match what root wants.
Resolve it:
git -C <root> ls-tree origin/<source> <submodule path>git -C <submodule> fetch origin <sha>origin/<source>): git -C <submodule> merge <sha> --no-editgit -C <submodule> checkout --detach <sha>git -C <root> add <submodule path>Verify before committing — git -C <root> submodule status must show no + or - prefix, meaning each gitlink matches its checked-out HEAD.
Print a summary table:
## Merge Summary
Source: `<source>`
| Repo | Branch | Behind | Result |
|---|---|---|---|
| server/ee | <branch> | <n> commits | ✓ merged / ✓ up to date / ⚠ skipped / ✗ conflicts |
| frontend/ee | <branch> | <n> commits | ✓ merged / ✓ up to date / ⚠ skipped / ✗ conflicts |
| root | <branch> | <n> commits | ✓ merged / ✓ up to date / ⚠ skipped / ✗ conflicts |List conflicted files per repo, then offer to resolve them one at a time:
git -C <path> add -A && git -C <path> commit --no-editgit -C <path> stash popPrint: All merges completed cleanly.
merge-auto-stash-<timestamp>) for easy identification.git merge --abort.git -C <path> — never cd <path> && git.commit — commit across root + submodulescreate-pr — push and open PRs across root + submodules© ToolJet, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/merge of ToolJet/ToolJet.
Open the folder on GitHubat commit 1786038
ToolJet Multi-Repo Merge next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| ToolJet Multi-Repo Merge this skillToolJet/ToolJet | 41k | — | ~2.1k | Automated safety check: Warn | AGPL-3.0 | |
| Finishing a Development Branchobra/superpowers | 296k | 5 repos | ~1.9k | Automated safety check: Pass | MIT | |
| Code Design Rationale Investigatorcursor/plugins | 10k | 9 repos | ~2.6k | Automated safety check: Pass | None | |
| Contributor-First PR MergeHKUDS/OpenHarness | 16k | 1 repos | ~847 | Automated safety check: Pass | MIT | |
| Migrate Internal Package into GhostTryGhost/Ghost | 55k | — | ~3.8k | Automated safety check: Pass | MIT | |
| Create Pull Requestcline/cline | 70k | 1 repos | ~1.6k | Automated safety check: Pass | Apache-2.0 |
obra/superpowers
Walks the last step of a branch: confirm tests pass, detect the git environment, ask how to integrate, carry out your choice and clean up the worktree.
cursor/plugins
Digs into why code is shaped the way it is by checking git history, pull requests and connected tools in parallel, then reporting a cited read on the tradeoffs.
HKUDS/OpenHarness
Merges external GitHub pull requests while keeping the original author credited, and fixes conflicts after the merge instead of rewriting the contribution.
TryGhost/Ghost
Moves a package from another TryGhost repository into Ghost as an internal workspace package while keeping its Git history, with checkpoints for the steps that need an administrator.
cline/cline
Opens a GitHub pull request from your current branch with the gh CLI, after reviewing the commits and diff and gathering the details the PR needs.
tailcallhq/forgecode
Resolves Git merge conflicts with a plan-first workflow that keeps both sides' intent, regenerates lock files and backs up deleted-but-modified files.
ToolJet/ToolJet
Turns an API description, such as an OpenAPI file or a Postman collection, into a connector plugin for ToolJet's marketplace and checks it with the repo's validator.
ToolJet/ToolJet
Commits changes across ToolJet's root repo and its server/ee and frontend/ee submodules, writing messages from the diffs and updating submodule pointers in order.
ToolJet/ToolJet
Opens a pull request for the current ToolJet branch, pushing the root repo and the ee submodules, creating submodule PRs first and then the main PR with a generated description.
ToolJet/ToolJet
Reviews a ToolJet pull request of any size and writes a findings report for you to read first, scaling the process to the diff and posting to GitHub only on request.
ToolJet/ToolJet
Cuts a ToolJet release branch, bumps the version and moves feature PRs onto it, or adds more PRs to a release that already exists.
ToolJet/ToolJet
Decides where a new agent skill belongs in the ToolJet repo, public root or private ee submodule, then wires the symlinks so it loads in Claude Code, Cursor and Codex.
Works with
Categories
Merges a source branch into the current branch across ToolJet's root repo and its server/ee and frontend/ee submodules, handling conflicts and submodule order. The skill parses a /merge command: with no argument it merges the branch's base, read from the open PR's base ref or else the remote's default branch; with an argument it treats the whole input as the source branch name, and asks the user when the context points at an unclear release line. It warns that the Bash tool runs in zsh via eval, so for loops break with a 'git: command not found' error and must be avoided in favor of separate per-repo commands, and that coreutils need full paths.
ToolJet Multi-Repo Merge fits situations like: merging a feature branch into the current branch across ToolJet's submodules; syncing the current branch with main across root, server/ee and frontend/ee; resolving a lint-staged failure caused by an untracked file inside a submodule during a merge.
Run `npx skills add ToolJet/ToolJet --skill merge -a claude-code`. Or copy the skill folder (.agents/skills/merge in ToolJet/ToolJet) into .claude/skills/merge in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ToolJet/ToolJet --skill merge -a codex`. Or copy the skill folder (.agents/skills/merge in ToolJet/ToolJet) into .agents/skills/merge in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ToolJet/ToolJet --skill merge -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/merge, .gemini/skills/merge, .github/skills/merge and .opencode/skills/merge in your project.
Going by SKILL.md and its folder, ToolJet Multi-Repo Merge needs the command-line tools its instructions call (git and gh). Our summary lists: A checkout of the ToolJet repository with its ee submodules; gh CLI; zsh.
SKILL.md contains no URLs. Its commands use git and gh, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md flagged 1 warning(s): tells the agent its actions are pre-authorized / not to stop for confirmation. Read the flagged lines before installing; the check is not a guarantee either way.
ToolJet Multi-Repo Merge is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.1k tokens (SKILL.md is roughly 8.6k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with ToolJet Multi-Repo Merge: Finishing a Development Branch (obra/superpowers, 296k stars), Code Design Rationale Investigator (cursor/plugins, 10k stars), Contributor-First PR Merge (HKUDS/OpenHarness, 16k stars) and Migrate Internal Package into Ghost (TryGhost/Ghost, 55k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ToolJet (a GitHub organization) maintains it in ToolJet/ToolJet, which has 41,045 GitHub stars. The repository holds 7 skills in this directory. The repository was last updated on October 7, 2026.
Source: ToolJet/ToolJet on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.