From claude-mods
Orchestrates git operations with safety tiers: read-only queries run inline, safe writes dispatch to a background agent, destructive actions require preflight confirmation. Handles status, commits, PRs, rebases, releases, worktrees, and batch land-all planning.
How this skill is triggered — by the user, by Claude, or both
Slash command
/claude-mods:git-opsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Intelligent git operations orchestrator. Routes read-only queries inline for speed, dispatches write operations to a background Sonnet agent (`git-agent`) to free the main session.
Intelligent git operations orchestrator. Routes read-only queries inline for speed, dispatches write operations to a background Sonnet agent (git-agent) to free the main session.
User intent (commit, PR, rebase, status, etc.)
|
+---> Tier 1: Read-only (status, log, diff, blame)
| |
| +---> Execute INLINE via Bash (fast, no subagent)
|
+---> Tier 2: Safe writes (commit, push, tag, PR, stash)
| |
| +---> Gather context from conversation
| +---> Dispatch to git-agent (background, Sonnet)
| | +---> Fallback: general-purpose with inlined protocol
| +---> Agent executes and reports back
|
+---> Tier 3: Destructive (rebase, reset, force-push, branch -D)
|
+---> Dispatch to git-agent (background, Sonnet)
| +---> Fallback: general-purpose with inlined protocol
+---> Agent produces PREFLIGHT REPORT (does NOT execute)
+---> Orchestrator relays preflight to user
+---> On confirmation: re-dispatch with execute authority
No subagent needed. Execute directly via Bash for instant results.
| Operation | Command |
|---|---|
| Status (rich) | bash $HOME/.claude/skills/git-ops/scripts/status.sh — one-shot HEAD + sync + tree + worktrees + branches + PR |
| Worktree survey | bash $HOME/.claude/skills/git-ops/scripts/worktree-survey.sh — per-worktree state, drift detection, prunable/WIP/ghost/orphan triage |
| Land-all plan | bash $HOME/.claude/skills/git-ops/scripts/land-all.sh [--porcelain] — classifies every branch as LANDABLE/STALE/WIP/ACTIVE/MERGED for a batch land (see "Land all" below) |
| Status (bare) | git status --short |
| Log | git log --oneline -20 |
| Diff (unstaged) | git diff --stat |
| Diff (staged) | git diff --cached --stat |
| Diff (full) | git diff [file] or git diff --cached [file] |
| Branch list | git branch -v |
| Remote branches | git branch -rv |
| Stash list | git stash list |
| Blame | git blame [file] |
| Show commit | git show [hash] --stat |
| Reflog | git reflog --oneline -20 |
| Tags | git tag --list --sort=-v:refname |
| Worktree list | git worktree list |
| PR list | gh pr list |
| PR status | gh pr view [N] |
| Issue list | gh issue list |
| CI checks | gh pr checks [N] |
| Run status | gh run list --limit 5 |
For T1 operations, format results cleanly and present directly. Use delta for diffs when available.
When to reach for the bundled scripts:
status.shworktree-survey.shWhen running any status check, scan for these anti-patterns and surface them before the status output. Don't wait for the user to notice. The status.sh script handles checks 1 and 2 automatically; checks 3 and 4 are Claude's responsibility.
Signal: In the main checkout (not a worktree) and git branch --show-current ≠ the repo's default branch (main/master/trunk).
Why it's bad: The main checkout is the fallback workspace. Feature branches sitting there block clean status reads, confuse worktree operations, and make it unclear what "current" state is. Feature work belongs in dedicated worktrees.
Flag it: Emit a prominent warning before the status output.
Fix:
git checkout main # return main to trunk
git worktree add .claude/worktrees/<name> <feature-branch> # move work to worktree
Detecting main checkout vs worktree:
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
# ".git" → main checkout → check applies
# contains "worktrees" → inside a worktree → skip this check
Signal: git branch --merged <default> returns branches other than the trunk.
Why it's bad: Merged-but-undeleted branches are noise that obscures what's actually in flight.
Flag it: Report the count. Suggest git branch cleanup to review and delete.
Signal: git log --oneline @{u}..HEAD contains subject lines matching wip|WIP|todo|TODO|fixme|FIXME|temp|TEMP|hack|HACK.
Why it's bad: WIP markers in pushed history signal unfinished work that shouldn't have left the local machine. Creates confusing history and blocks clean PRs.
Flag it: List the offending commits and suggest an interactive rebase to squash or rename.
Signal: staged + unstaged + untracked > 20 files.
Why it's bad: Large uncommitted diffs are hard to review, easy to lose, and signal a broken "commit as you go" habit.
Flag it: Note the total and suggest committing incrementally by logical unit.
Gather relevant context, then dispatch to git-agent (background, Sonnet).
Context gathering before dispatch:
| Operation | Context to Gather |
|---|---|
| Commit | What the user has been working on (from conversation), staged files, recent commit style |
| Push | Current branch, tracking info, commits ahead of remote |
| PR create | All commits on branch vs main, conversation context for description |
| Tag/release | Commits since last tag, version pattern in use |
| Stash | Current changes, user's stash message if provided |
| Cherry-pick | Target commit details, current branch |
| Branch create | Base branch, naming convention from recent branches |
| gh issue create | User description, labels if mentioned |
Dispatch template:
You are the git-agent handling a Tier 2 (safe write) operation.
## Domain Knowledge
For release or PR operations, read CI context first:
- Read: skills/ci-cd-ops/SKILL.md (release workflows, PR conventions)
## Context
- Current branch: {branch}
- Repository: {repo info}
- User intent: {what the user asked for}
- Conversation context: {relevant summary of what was being worked on}
## Operation
{specific operation details}
## Project Conventions
{commit style, branch naming, PR template if detected}
Execute the operation following your T2 protocol (verify state, execute, confirm, report).
Dispatch to git-agent with explicit instruction to produce a preflight report ONLY.
Dispatch template (preflight):
You are the git-agent handling a Tier 3 (destructive) operation.
## Context
- Current branch: {branch}
- Repository: {repo info}
- User intent: {what the user asked for}
## Operation
{specific operation details}
IMPORTANT: Do NOT execute this operation. Produce a T3 Preflight Report only.
Show exactly what will happen, what the risks are, and how to recover.
After user confirms: Re-dispatch with execute authority:
User has confirmed the Tier 3 operation after reviewing the preflight.
## Approved Operation
{exact operation from preflight}
## Confirmation
Proceed with execution. Follow T3 execution protocol:
1. Create a safety bookmark: note the current HEAD hash
2. Execute the operation
3. Verify the result
4. Report with the safety bookmark for recovery
# Dispatch to git-agent, runs in background, Sonnet model
Agent(
subagent_type="git-agent",
model="sonnet",
run_in_background=True, # Frees main session
prompt="..." # From dispatch templates above
)
The main session continues working while the agent handles git operations. Results arrive asynchronously.
For operations where the user is waiting on the result (e.g., "commit this then let's move on"):
Agent(
subagent_type="git-agent",
model="sonnet",
run_in_background=False, # Wait for result
prompt="..."
)
When the user explicitly asks for worktree isolation (e.g., "do this in a separate worktree", "prepare a branch without touching my working tree"):
Agent(
subagent_type="git-agent",
model="sonnet",
isolation="worktree", # Isolated repo copy
run_in_background=True,
prompt="..."
)
If git-agent is not registered as a subagent type (e.g., plugin not installed, agent files missing), fall back to general-purpose with the git-agent identity inlined in the prompt.
Detection: If dispatching to git-agent fails or the subagent type is not listed in available agents, switch to fallback mode automatically.
Fallback dispatch template:
Agent(
subagent_type="general-purpose", # Fallback
model="sonnet",
run_in_background=True,
prompt="""You are acting as a git operations agent. You are precise, safety-conscious,
and follow the three-tier safety system:
- T1 (read-only): execute freely
- T2 (safe writes): execute on instruction, verify before and after
- T3 (destructive): preflight report only unless explicitly told to execute
{original dispatch prompt here}
"""
)
Key differences from primary dispatch:
general-purpose instead of git-agent subagent typeWhen to use each:
| Condition | Dispatch Method |
|---|---|
git-agent available | Primary: subagent_type="git-agent" |
git-agent unavailable | Fallback: subagent_type="general-purpose" with inlined protocol |
| No agent dispatch possible | Last resort: execute T2 operations inline (main context) |
The last-resort inline path should only be used for simple T2 operations (single commit, simple push). Complex workflows (PR creation, release, changelog) should always use an agent.
git-ops owns the local half of releases only — analysing commits, generating CHANGELOG content, creating the local tag. The remote half (push, gh release create, repo metadata) belongs to the github-ops skill.
When user asks to "create a release", "bump version", or "tag a release":
Inline (T1): Check current version and commits since last tag
git describe --tags --abbrev=0 2>/dev/null
git log --oneline $(git describe --tags --abbrev=0 2>/dev/null)..HEAD
Determine version bump:
feat: commits -> minor bumpfix: commits -> patch bumpBREAKING CHANGE: or !: -> requires explicit user approval (never auto-major)Dispatch to git-agent (T2): Generate CHANGELOG content + create local tag.
Hand off to github-ops for the remote half: push commits, push tag, create the GitHub release with notes, update repo metadata if warranted. Do not call gh release create from git-ops — that crosses the local/remote boundary. See skills/github-ops/SKILL.md mode update.
When user asks to "generate changelog" or "update CHANGELOG.md":
When user says "create a PR" or "open a PR":
When user asks to "clean up branches" or "delete merged branches":
git branch --merged main | grep -v "main\|master\|\*"
When user asks "what should the next version be":
When user encounters merge conflicts:
git status to show conflicted filesWorktrees are first-class in this skill. The classification is:
| Op | Tier | How |
|---|---|---|
| Survey | T1 | bash scripts/worktree-survey.sh — read-only, reports per-worktree state + drift |
| New lane | T2 (inline) | bash scripts/new-lane.sh [--sibling] <slug> [base] — fast scripted provisioning: branch lane/<slug> in-repo at .claude/worktrees/<slug> (gitignored; --sibling for an outside <repo>-<slug> instead) + carries over gitignored env files. The one-command collision remedy — see "Lane provisioning" below |
| Create (bespoke) | T2 | git worktree add <path> -b <branch> via agent — for non-standard layouts the script doesn't cover |
| Land | T2 | Rebase worktree branch onto trunk + test + fast-forward. Multi-step procedure — see "Worktree Land Procedure" below |
| Prune (clean) | T2 | git worktree prune for ghost entries (registered but FS-missing). Always safe, no data loss possible |
| Remove | T3 | git worktree remove <path> — destroys filesystem state. Requires preflight + explicit confirm per worktree |
scripts/new-lane.sh <slug> [base-branch] is the fast, model-invocable way to isolate parallel
work — the remedy the peer-writer guards (session-start-unicode-scan.sh at boot,
pre-write-peer-guard.sh mid-session) point you to. It:
lane/<slug> in-repo at <main>/.claude/worktrees/<slug> — the native
Claude Code worktree location: tidy (no sibling dirs scattered across the parent) and gitignored
so git add -A can't stage its gitlinks — off [base-branch] (default: current branch);.claude/worktrees/ isn't gitignored it adds the entry
first (the in-repo location is only safe when ignored), so the default is safe in any repo;--sibling places it outside the repo at <repo>/../<repo>-<slug> instead — use when you need
structural isolation from repo-scoped destructive ops (git clean -ff, rm -rf <repo>) or in a
repo that can't gitignore the dir;.dev.vars, .env*, .secrets) the fresh worktree
would otherwise lack, so the lane runs immediately;cd "$(bash scripts/new-lane.sh hotfix main)";Lane work durability: committed lane work lives in the shared object store and survives even
deletion of the worktree dir (recover via git worktree add <path> lane/<slug>); only uncommitted
work is at risk from git clean -ff / rm -rf. Land early/often — see rules/worktree-boundaries.md.
Run it inline (deterministic, non-destructive); land the lane back via the Worktree Land
Procedure below or fleet-ops. Reach for it whenever two sessions would otherwise share one checkout.
Never recommend prune/remove without first running scripts/worktree-survey.sh
and presenting the output to the user. The survey categorises each worktree as:
(trunk) — the main repo itself, never prunePRUNABLE — merged into trunk, no uncommitted work, no unpushed commits → safe to removehas WIP — uncommitted changes → commit or stash first, never auto-removeunpushed — commits ahead of upstream → push or cherry-pick before removein-flight — not merged, not dirty → probably still in active useGHOST — registered but filesystem gone → git worktree prune fixesUNREGISTERED / orphan — filesystem dir with no git entry → DO NOT touch without explicit reviewFor landing a branch from a worktree onto the trunk (rebase + test + ff):
package.json / pyproject.toml / justfile)push-gate)Dispatch this to git-agent as a T2 operation with the worktree path + trunk name.
The front-door for "I've got 4-5 chips/sessions/worktrees, land the ones that are
done." git-ops discovers and classifies; fleet-ops executes the sequential,
test-gated landing. No duplicated landing logic — the two compose.
Triggers: "land everything", "land all my worktrees", "land the pending chips", "clean up and land what's done", "where are we and land it".
Procedure:
Survey (T1, read-only). Run scripts/land-all.sh --porcelain (add --recent-days N
if the user's lanes span longer than a week). Each candidate branch is classified:
| Status | Meaning | Default action |
|---|---|---|
LANDABLE | clean, ahead, not merged, recent, no live writer | land |
STALE | clean + ahead but last commit > --recent-days old | park (offer to prune/archive, or land explicitly) |
WIP | uncommitted tracked changes | park — commit in-lane first |
ACTIVE | a session is writing it right now (recent file activity) | never land — park |
MERGED | already an ancestor of trunk (incl. nothing ahead) | prune candidate |
Confirm the plan (AskUserQuestion, HARD RULE). Present the three groups — land these
LANDABLE / park these WIP+ACTIVE+STALE / prune these MERGED — and get explicit go.
Never skip this: landing is outward-facing on the trunk. Surface far behind (N) notes so the
user knows which lands may conflict.
Execute via fleet-ops. For the confirmed landable set:
bash $HOME/.claude/skills/fleet-ops/scripts/fleet.sh track <landable-branches...>
bash $HOME/.claude/skills/fleet-ops/scripts/fleet.sh land --all --running
fleet-ops lands oldest-first, runs the test gate, auto-rebases the remaining lanes after
each land, and marks any lane that hits a real conflict CONFLICT — it does not guess a
resolution. This is a T2 write; dispatch through git-agent or run inline if the user is waiting.
Escalate conflicts, don't auto-resolve. A CONFLICT lane stops being landed and is reported.
Offer: resolve in the lane, skip it, or revert (fleet revert <branch>). Sequential + auto-rebase
minimises conflicts (each lane rebases onto a trunk that already has the prior lands); genuine
semantic conflicts are always the user's call.
Offer cleanup (survey-first, T3). After landing, the MERGED branches and any
now-landed worktrees are prune candidates. Follow Survey-first discipline + the T3 Remove
preflight — never auto-git worktree remove; confirm per worktree. Respect
rules/worktree-boundaries.md throughout: ACTIVE/orphan/unregistered trees are never touched.
Safety invariants: ACTIVE lanes (live peer writer) are never landed — this is the
worktree-boundaries live-writer guard applied to landing. WIP needs an explicit commit first.
STALE needs explicit opt-in (--recent-days or naming the branch). Only LANDABLE lands by default.
See rules/worktree-boundaries.md. Summary:
rm -rf .claude/worktrees/ — the orphan count in survey is informational, never a cleanup cuegit add -A when .claude/worktrees/ has untracked entries (sweeps gitlinks into commits)When a git-related request arrives, follow this flow:
1. Classify the operation tier (T1/T2/T3)
2. If T1:
- Execute inline via Bash
- Format and present results
- DONE
3. If T2:
- Gather context (conversation, git state, conventions)
- Decide foreground vs background:
* User waiting on result? -> foreground
* User continuing other work? -> background
- Dispatch to git-agent with context
- Relay result when received
4. If T3:
- Gather context
- Dispatch to git-agent for PREFLIGHT ONLY
- Present preflight report to user
- Wait for explicit confirmation
- Re-dispatch with execute authority
- Relay result
| Task | Tier | Inline/Agent |
|---|---|---|
| Check status (rich) | T1 | Inline (scripts/status.sh) |
| Worktree survey | T1 | Inline (scripts/worktree-survey.sh) |
| View diff | T1 | Inline |
| View log | T1 | Inline |
| List PRs | T1 | Inline |
| Commit | T2 | Agent |
| Push | T2 | Agent |
| Create PR | T2 | Agent |
| Create tag | T2 | Agent |
| Create release | T2 | Agent |
| Stash push/pop | T2 | Agent |
| Cherry-pick | T2 | Agent |
| Create branch | T2 | Agent |
| Create worktree | T2 | Agent |
| Land worktree | T2 | Agent (rebase + test + ff) |
| Prune ghost worktrees | T2 | Agent (git worktree prune) |
| Rebase | T3 | Agent (preflight) |
| Force push | T3 | Agent (preflight) |
| Reset --hard | T3 | Agent (preflight) |
| Delete branch | T3 | Agent (preflight) |
| Discard changes | T3 | Agent (preflight) |
| Merge to main | T3 | Agent (preflight) |
| Remove worktree | T3 | Agent (preflight per worktree) |
| Tool | Purpose |
|---|---|
git | All git operations |
gh | GitHub CLI - PRs, issues, releases, actions |
delta | Syntax-highlighted diffs (if available) |
lazygit | Interactive TUI (suggest to user, not for agent) |
For detailed patterns, load:
./references/rebase-patterns.md - Interactive rebase workflows and safety./references/stash-patterns.md - Stash operations and workflows./references/advanced-git.md - Bisect, cherry-pick, worktrees, reflog, conflictsnpx claudepluginhub 0xdarkmatter/claude-mods --plugin claude-modsManages Git branch strategy, worktrees, commits, PR preparation, merge/rebase decisions, conflict resolution, tagging, and release notes. Validates state before making changes.
Handles complex git operations: rebases, merge conflict resolution, cherry-picking, branch management, and PR branch upkeep with force-with-lease safety.
Guides Git branching strategies (GitHub Flow, trunk-based, GitFlow), commit conventions, merge vs rebase, conflict resolution, and collaborative development best practices.