worktree-merge-cleanup
On-demand home for the pre-merge worktree precondition and the unified post-merge cleanup sequence — how to run `gh pr merge --squash --delete-branch` from…
Skill by devseunggwan
Chalk Labs
Need help deploying worktree-merge-cleanup?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/devseunggwan-worktree-merge-cleanup
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/worktree-merge-cleanup
What's inside
- Skill name
worktree-merge-cleanup- Description
- On-demand home for the pre-merge worktree precondition and the unified post-merge cleanup sequence — how to run `gh pr merge --squash --delete-branch` from the base-branch worktree, the submodule `--force` caveat, the squash-ancestry stale-HEAD guard, and the no-`&&`-chain rule.
- License
- MIT
- Instructions
- 356 lines in SKILL.md · view on GitHub
Agent Skills spec issues
- body: contains an absolute path from the author's machine
Files (1)
- SKILL.md
SKILL.md (first lines)
# worktree-merge-cleanup
## Overview
`gh pr merge --squash --delete-branch` does a local checkout of the base branch
(main / dev / prod) in the post-squash stage, and it deletes the local head
branch by reachability against the local base HEAD. Both facts make the command
sensitive to *which worktree* it runs from and *whether the base is synced* —
get either wrong and the merge fails at the git layer or silently skips the
local-branch delete, forcing manual recovery.
This skill is the on-demand home for that procedure. The always-loaded rule set
keeps only a pointer here; the deterministic `--delete-branch` failure mode is
additionally enforced structurally by the `gh-merge-worktree-precondition`
PreToolUse hook (see [Relationship to enforcement](#relationship-to-enforcement)).
**Core principle:** run the post-merge cleanup steps as *separate* Bash calls,
never collapsed into one `&&`-chain — a git hard error mid-sequence
short-circuits the chain and its trailing output is easily misread as success.
## When to Use
- About to merge a PR with `gh pr merge --squash --delete-branch` from an
issue-branch worktree.
- The merge just failed with `fatal: '<base>' is already used by worktree at ...`
or `cannot delete branch 'X' used by worktree at ...`.
- After a squash-merge the local feature branch was not deleted
(`warning: deleting branch 'X' ... not yet merged to HEAD`).
- Cleaning up a worktree that contains a submodule.
- Removing the worktree and head branch of a PR the user closed without
merging. The removal mechanics are the same as below (clean-check, submodule
`--force` without `deinit`, explicit workdir afterwards, remote tip equals
the PR's `headRefOid` before `push origin --delete`), but a post-merge
standing approval does not cover it: list the worktree and branches and ask
once. Load this skill before the first removal command even for a one-off
closed PR — skipping it is how the shared-config `deinit` damage repeats.
- Cleaning up many stale worktrees across repos at once → follow
`references/bulk-stale-worktree-cleanup.md` (inventory, classification order,
squash-safe content oracle, regenerable-artifact list, checkpointed background run,
and the stash/keep-branch pass for removing holds when the user asks for all).
## Pre-call checklist
`gh pr merge --squash --delete-branch` must be **called from the worktree that
owns the base branch**. Calling from an issue-branch worktree triggers the git
exclusive-ref guard:
```text
fatal: 'main' is already used by worktree at /Users/.../<main-worktree>
```
1. Confirm the worktree occupying the base branch with `git worktree list`.
2. **If `--delete-branch` is included**: remove the PR head branch's worktree
first (`git worktree remove <issue-worktree-path>`). If the shell's working
directory is that worktree, every later shell call fails at its implicit
`cd` once the directory is gone — run the remove from (or with `-C`) the base
worktree, and give every following call an explicit working directory
(`workdir`, `git -C`, `--repo`) instead of retrying. On Hermes the
terminal tool's persistent cwd is applied before your command runs, so a
`cd <base> && …` inside the command still fails with `cd: <removed path>:
No such file or directory` — set the tool's `workdir` parameter.
Likewise, step 5's scratch deletion removes only files you created for
this PR: list them with mtimes and leave older files other sessions wrote. The post-merge local
branch delete fails if the branch is still occupied — `cannot delete branch
'X' used by worktree at ...` — even when invoked from the base (main)
worktree, because the failing branch is the *head*, not the base. After
removal, re-run `git worktree list` to confirm.
- ⚠️ **The worktree is the agent session's own working folder** (Hermes desktop freezes a chat's cwd at creation; check the runtime `Current working directory` / the turn's workdir): removing it kills the session — every later message fails with "working folder no longer exists" before any model call. Still remove it if the cleanup is approved, but say in the same report that this chat must be moved (desktop **Move to project**) to a live folder before the next message, and name the folder (base worktree or the next issue's worktree).
- ⚠️ **Something live may still run from the worktree**: before removing it, check that no symlink points into it (an agent's plugin or skills directory linked to the worktree loads from it: `ls -la <load dir>`) and that no process has its cwd there (`lsof -d cwd 2>/dev/null | grep -F "<worktree path>"`, which also catches a subdirectory without the recursive walk of `+D`; `pgrep -fl <worktree path>` matches command lines only and misses a process that merely `cd`'d there). Stop or repoint those first and name them in the report.
- ⚠️ **The `codex-review-wrap` companion leaves its app-server broker running with the reviewed worktree as cwd.** Find it (`lsof -a -p <pid> -d cwd` on the `app-server-broker.mjs serve --cwd <worktree>` process) and stop only that pid before removing the worktree — never a broad `pkill`.
- ⚠️ **Submodule-containing worktree**: plain `git worktree remove` is
rejected with `fatal: working trees containing submodules cannot be moved
or removed`. Use `git worktree remove --force <path>` **only after
confirming the worktree is clean** (`git -C <path> status --porcelain`
empty, and no `!!` line from `--porcelain --ignored` other than a
regenerable dependency or build cache — `remove` deletes ignored files too). `--force` destroys uncommitted changes in a dirty worktree, so
never make it the default. Never run `git submodule deinit` in a linked worktree as a
cleanup step: it does not lift the rejection (the check looks at the
registered submodule, not its checkout), and it deletes
`submodule.<name>.url` from the repository config that every worktree
shares, so sibling worktrees lose their submodule registration. Go
straight to the clean-check + `--force`. If a deinit already ran, restore
the entry from the main checkout with `git submodule init <path>` and
confirm with `git config --get submodule.<name>.url`.
3. `cd <base-worktree-path>` or chain `cd <path> && gh pr merge ...` in the same
Bash call (avoid cwd-reset trap between Bash calls).
- **Fork clones: pass `--repo <fork-owner>/<repo>` on every `gh pr` call,
the merge included.** In a clone whose GitHub repo is a fork, gh
resolves a bare `gh pr merge <N>` (and `view` / `comment` / `edit`)
against the parent repo: it fails with `Could not resolve to a
PullRequest` at best and acts on the upstream PR of the same number at
worst.
4. Even if the call fails on a worktree conflict, the PR may already be merged
on remote (gh order: remote merge → local sync). Manual cleanup — run each as
a **separate** Bash call, never chained (a failure in one step must not
short-circuit the rest): `git worktree remove <path>`, then
`git branch -D <branch>`, then `git worktree prune` (snapshot and dry-run
it first — see [prune is repository-wide](#prune-is-repository-wide--snapshot-before-running-it)),
then `git pull origin <base>`.
5. **Squash-ancestry stale HEAD guard (post-merge sync mandatory)**: immediately
after `gh pr merge --squash --delete-branch`, run `git pull origin
<base-branch>` as a **separate step**. gh merges remote then deletes local
branch by reachability against local HEAD — but does not fetch the local
base, so if local base is still at pre-merge SHA the delete silently skips
(`warning: deleting branch 'X' that has been merged to 'refs/remotes/origin/X',
but not yet merged to HEAD`). Distinct from item 4's worktree case — only
`git pull` fixes it, not `git worktree remove`.
## When the user merged out-of-band
A repository bot can also merge the PR once approval and checks are green, so your own `gh pr merge` prints `already merged` (exit 0). Treat that as an out-of-band merge: read `gh pr view <N> --json state,mergedAt,mergedBy,mergeCommit` and report who merged it. The user's approval to merge still covers the cleanup below.
When the user reports "merged" after merging themselves (a `/merge` PR-comment
slash command, the web UI), the cleanup below deletes things: the head
worktree, the local branch, scratch files, the remote head branch, and it may
post an issue close-out. A merge report is not an instruction to delete. Run
the whole sequence without asking only when the user's own instructions
(CLAUDE.md, AGENTS.md, or agent memory) record a standing approval for
post-merge cleanup. Without one, run the read-only checks (steps 1–2), thenFrom devseunggwan/praxis, MIT.
More from devseunggwan/praxis
- 0.592score
stale-pr-revival
devseunggwan
Bring an open, stalled pull request back to a mergeable state without rewriting its history — read every review surface, merge the base in, integrate what…
SkillAFreshness: A★ 1Claude Code +9 - 0.588score
codex-review-wrap
devseunggwan
Worktree-aware wrapper for /codex:review.
SkillAFreshness: A★ 1Claude Code +9 - 0.587score
upstream-bug-report
devseunggwan
Take a defect in an installed third-party plugin, server, or library from local diagnosis to an issue on its public repository — prove the fix in a fresh…
SkillAFreshness: A★ 1Claude Code +9 - 0.585score
retrospect
devseunggwan
Session retrospect — analyze the current Claude Code session against the rules it ran under (project and global `CLAUDE.md`), identify friction patterns and…
SkillAFreshness: A★ 1Claude Code +9 - 0.584score
surface-enumeration
devseunggwan
Pre-implementation input-surface enumeration — before writing a parser/validator/sanitizer/classifier, enumerate every input variant so each becomes a…
SkillAFreshness: A★ 1Claude Code +9 - 0.584score
reset-strikes
devseunggwan
Reset the current session's strike counter to 0 and clear the recorded violation list.
SkillAFreshness: A★ 1Claude Code +9 - 0.584score
strike
devseunggwan
Declare a rule violation in the current Claude Code session.
SkillAFreshness: A★ 1Claude Code +9 - 0.581score
strikes
devseunggwan
Show the current session's strike count (0-3) and the list of recorded violation reasons.
SkillAFreshness: A★ 1Claude Code +9 - 0.581score
perf-leak-review
devseunggwan
Point at performance-defect and memory-leak candidates in a diff — a read-only LLM reviewer reads the change plus the repository around it and reports…
SkillAFreshness: A★ 1Claude Code +9 - 0.580score
tradeoff
devseunggwan
Score the options at a decision fork on four cost axes — reversibility, blast radius, cost-if-wrong, process cost — with a provenance grade on every cell so a…
SkillAFreshness: A★ 1Claude Code +9 - 0.580score
merge-briefing
devseunggwan
On-demand home for the pre-merge approval procedure — the three-surface pre-ask probe, grading every open finding by its blocking decoration, carrying the…
SkillAFreshness: A★ 1Claude Code +9 - 0.579score
cmux-recover-sessions
devseunggwan
Bulk recover Claude Code sessions after a crash, power loss, OOM kill, or reboot by scanning the .jsonl files Claude Code persists automatically.
SkillAFreshness: A★ 1Claude Code +9
Signals
- Stars
- 1
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Oct 14, 2026 (16 days ago)
- Last release
- Oct 24, 2026 (6 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/devseunggwan/praxis
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from devseunggwan
- 0.592score
stale-pr-revival
devseunggwan
Bring an open, stalled pull request back to a mergeable state without rewriting its history — read every review surface, merge the base in, integrate what…
SkillAFreshness: A★ 1Claude Code +9 - 0.588score
codex-review-wrap
devseunggwan
Worktree-aware wrapper for /codex:review.
SkillAFreshness: A★ 1Claude Code +9 - 0.587score
upstream-bug-report
devseunggwan
Take a defect in an installed third-party plugin, server, or library from local diagnosis to an issue on its public repository — prove the fix in a fresh…
SkillAFreshness: A★ 1Claude Code +9 - 0.585score
retrospect
devseunggwan
Session retrospect — analyze the current Claude Code session against the rules it ran under (project and global `CLAUDE.md`), identify friction patterns and…
SkillAFreshness: A★ 1Claude Code +9 - 0.584score
reset-strikes
devseunggwan
Reset the current session's strike counter to 0 and clear the recorded violation list.
SkillAFreshness: A★ 1Claude Code +9 - 0.584score
strike
devseunggwan
Declare a rule violation in the current Claude Code session.
SkillAFreshness: A★ 1Claude Code +9
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get worktree-merge-cleanup running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
worktree-merge-cleanup skill. Agent Mart. https://agentmart.dev/skills/devseunggwan-worktree-merge-cleanup (last updated 2026-10-24)