New Branch

SkillAI & models

Start new work without losing anything you already have. Once added, your AI can stash your uncommitted changes, bring main up to date, and create a fresh git branch from the latest main whenever you ask for one.

Available today. Use it from your connected AI after setup.

After adding it, ask for /new-branch or a fresh git branch when you want to start something new. Your AI will stash your changes, update main, and set up the branch for you.

Then ask your AI: use the New Branch skill

What your AI can do with it

  • Stash uncommitted local changes so nothing is lost
  • Update main to the latest version before branching
  • Create a fresh git branch from the latest main
  • Wait for an explicit /new-branch or fresh branch request instead of acting on its own
  • Stay out of everyday coding, pull request, Builder.io, and Fusion branch workflows

What this skill tells your AI

The instructions your AI receives, as published by builderio/agent-native in .agents/skills/new-branch/SKILL.md and read by ahel’s review.

Activation guard

Use this skill only when the user explicitly invokes /new-branch, mentions this skill as the workflow to run, or directly asks you to create a fresh git branch from main.

If this skill was loaded without an explicit user request to create a new branch, stop here. Report that branch movement requires explicit confirmation, then continue the original task on the current branch.

Do NOT invoke this skill in any of these situations

These are mistakes other agents have made that stranded concurrent work:

  • The user said "fix the bug" / "open a PR" / "ship this" / "address review feedback" — those work on the current branch. PR and ship workflows in this repo push the current branch; they don't branch-then-push.
  • The current branch name looks unusual (ai_*, claude/*, codex/*, changes-N, updates-N, pr-NNN, feat/...). Those are platform-managed or other agents' branches; moving off looks like work-loss to whoever started them.
  • You're running inside Builder.io / Fusion / a project container. The platform tracks the user's work by the branch it assigned — leaving silently breaks their UI.
  • The working tree has uncommitted changes. Checkpoint all nonignored local work before branching; do not classify changes by authorship or stash them silently.
  • You think a fresh branch would be "tidier." Tidiness is not a goal here; concurrent-agent durability is.

When in doubt: stay on the current branch. Ask the user before moving.

Quickly stash any local changes, pull latest from origin/main, and create a new working branch. Designed to be as fast as possible since other agents may be working concurrently on this repo.

Pre-flight: verify main has the latest merge

Before creating the branch, always verify that origin/main contains the most recently merged PR. If you just merged a PR (or know one was recently merged), run:

git fetch origin main
gh pr list --state merged --base main --limit 1 --json number,mergedAt,mergeCommit --jq '.[0]'
git log origin/main --oneline -1

Compare the merge commit SHA. If origin/main doesn't include it yet, wait and re-fetch — GitHub can take a few seconds to update after a squash merge. Never create a branch off stale main. Creating a branch that's missing a just-merged PR causes chaos: subsequent work assumes the merged code is there, leading to conflicts, regressions, and duplicated changes.

Steps

Run as a single chained command to minimize time off-branch. Resolve the authenticated GitHub username before choosing the branch name so concurrent users have separate branch namespaces. The git stash push is gated so we only pop a stash we just created — never an old stash from a previous session. The stash name embeds the source branch so an orphan can be identified later (orphans are how we've lost work in the past — see "Post-flight check" below):

GITHUB_USER=$(gh api user --jq .login) && test -n "$GITHUB_USER" || { echo "Unable to resolve the authenticated GitHub username" >&2; exit 1; }; LATEST=$({ git for-each-ref --format='%(refname:short)' refs/heads refs/remotes/origin; git ls-remote --heads origin; } | sed -E -e 's#^[0-9a-f]+[[:space:]]+refs/heads/##' -e 's#^origin/##' | sed -nE 's#^([^/]+/)?changes-([0-9]+)$#\2#p' | awk '$1 >= 50 { print }' | sort -n | tail -1); NEXT=$(( ${LATEST:-49} + 1 )); BRANCH_NAME="${GITHUB_USER}/changes-${NEXT}"; SOURCE=$(git branch --show-current); STASH_MSG="new-branch-from-${SOURCE:-detached}-$(date +%s)"; if git diff-index --quiet HEAD --; then CREATED=0; else git stash push -m "$STASH_MSG" && CREATED=1 || CREATED=0; fi; git checkout main && git pull origin main && git checkout -b "$BRANCH_NAME" && if [ "$CREATED" = "1" ]; then git stash pop; else echo "(no stash to pop)"; fi; echo "--- Done: $(git branch --show-current)"

Why the gate: git stash push exits 0 even when there are no local changes ("No local changes to save"), so chaining && CREATED=1 would always set CREATED=1 and an unconditional git stash pop would pop a pre-existing stash from earlier work, dumping unrelated files into the working tree. The git diff-index --quiet HEAD -- pre-check exits 0 only when there are no differences against HEAD in tracked files — we skip stashing entirely in that case so there's nothing to pop. Untracked files are intentionally not part of the gate (and not stashed): for a fast new-branch flow, untracked files following the user across git checkout is the desired behaviour, and git stash push without -u already ignores them. We let git stash pop errors (e.g. merge conflicts) surface naturally rather than swallowing them with 2>/dev/null, since the next section assumes you'll see and resolve them.

Branch naming

  • Use the pattern <github-username>/changes-N, for example steve8708/changes-545, where N is at least 50
  • Resolve <github-username> with gh api user --jq .login; do not substitute a display name or local git author name
  • Choose N from all local refs and current origin refs matching changes-N, whether legacy unprefixed or already username-prefixed, so the sequence does not reset
  • Ignore older numbers below 50 and unrelated branch names
  • If no matching branch exists at 50 or above, start with <github-username>/changes-50

After creation

  • Report the new branch name and working tree status.
  • If stash pop had merge conflicts that you can confidently resolve (e.g. --theirs for pnpm-lock.yaml), resolve them and proceed. If you can't resolve them confidently, abort the new branch instead of leaving the work stranded:
    git checkout --merge .         # back out the conflicted pop (stash stays in list)
    git checkout -                  # back to the source branch
    git branch -D <new-branch>      # remove the freshly-created branch
    git stash list | head -3        # show the stash so the user can act on it
    
    Then surface to the user: "Stash pop conflicted on <files>; the new branch was rolled back and <stash-name> is preserved. Want me to retry, drop the stash, or stay on the source branch?" Never silently leave a half-built branch + an orphaned stash — that's how concurrent-agent work disappears.
  • If stash pop brought back .claude/worktrees files, unstage them with git reset HEAD .claude/worktrees.
  • If a pop accidentally happened and brought in unrelated files (because the gate was bypassed), do NOT silently resolve conflicts. The stashed content stays in the stash list, so discard the popped working-tree changes (git rm deleted-by-us files, git checkout --ours for both-modified files) and surface this to the user.

Post-flight check

After every /new-branch invocation, list any pre-existing stashes and surface them to the user. Orphaned new-branch-from-* / WIP on * / babysit-tick*-concurrent-work-* stashes are how we've lost real work in the past — they pile up unnoticed.

git stash list

If the list shows stashes that aren't yours-from-this-run, name them in your response:

Heads-up — there are 3 pre-existing stashes (stash@{1}: WIP on updates-238, stash@{2}: On changes-3: new-branch-1777654416, stash@{3}: babysit-tick4-concurrent-work...). These may contain unrecovered work. Want me to inspect them?

This is the only reliable way to catch the leak — git won't warn you on its own.

Important

  • Speed matters — other agents run concurrently, so minimize time spent on main.
  • Never force-push or reset — other agents' work may be in-flight.
  • Don't push the new branch until there are actual changes to ship.
  • Treat orphaned stashes as bugs. If you see a new-branch-from-* stash older than this session, surface it. Don't drop it without the user's confirmation — it may be the only copy of someone's work.

Signals

GitHub stars
5k
Forks
440
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
new-branch
Source
github.com/builderio/agent-native