Skip to content
Agentmart
Submit a tool

worktree-close

Remove a git worktree that is no longer needed.

Skill by asura1234

IndexedApache-2.0★ 1
Write a review

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/asura1234-worktree-close

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.

We use your email only for this newsletter. Privacy

About

Remove a git worktree that is no longer needed. Before removal it explicitly checks the worktree for uncommitted changes and unpushed commits, and only uses --force after the user confirms discarding them. PRs to this repo may be squash-merged, so whether a branch has landed is decided by content rather than ancestry; a local branch judged landed is deleted with -D without asking, one that has not landed or cannot be judged is kept and handed back, and the remote branch is deleted only when the user explicitly asks. Use when the user asks to "delete a worktree", "clean up a worktree", "close a worktree", "wrap up a worktree", or "I don't need this isolated copy anymore". Works across agents; mainly git, plus basic shell tools such as sed/du/mkdir/cp, and reads and writes the Claude memory directory. It refuses to remove the worktree its own agent session runs in and hands that back. Argument — worktree name or path (defaults to the worktree containing the current directory, which is refused when that is the session's own worktree).

Use cases: writing, agent-building

No 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-close

What's inside

Skill name
worktree-close
Description
Remove a git worktree that is no longer needed. Before removal it explicitly checks the worktree for uncommitted changes and unpushed commits, and only uses --force after the user confirms discarding them. PRs to this repo may be squash-merged, so whether a branch has landed is decided by content rather than ancestry; a local branch judged landed is deleted with -D without asking, one that has not landed or cannot be judged is kept and handed back, and the remote branch is deleted only when the user explicitly asks. Use when the user asks to "delete a worktree", "clean up a worktree", "close a worktree", "wrap up a worktree", or "I don't need this isolated copy anymore". Works across agents; mainly git, plus basic shell tools such as sed/du/mkdir/cp, and reads and writes the Claude memory directory. It refuses to remove the worktree its own agent session runs in and hands that back. Argument — worktree name or path (defaults to the worktree containing the current directory, which is refused when that is the session's own worktree).
License
Apache-2.0
Instructions
197 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • description: longer than 1024 characters

Files (1)

  • SKILL.md

SKILL.md (first lines)

Remove a git worktree you no longer need. Mostly git, plus basic shell tools (sed/du/mkdir/cp) and a
read-write touch of the Claude memory directory; runnable by any AI agent.

Removing a worktree is NOT the same as retiring a branch. A worktree is just an isolated checkout —
it may be long-lived, may have been used for many branches, and may be on a detached HEAD. So this
skill removes the worktree, and decides the branch separately: a branch whose content is already in
origin/master is swept up automatically, anything else is kept and handed back to the user.

Target: $ARGUMENTS (uses the worktree containing the current directory if not provided; that
default is refused below when it is the session's own working directory)

```
========== RESOLVE TARGET ==========

TRY: `git worktree list`
IF failed
  ERROR "The current directory is not inside a git repository; cannot clean up a worktree."

main_worktree = path of the FIRST entry of `git worktree list`
`git -C <main_worktree> worktree prune`

-- Identify by worktree, not by branch: a worktree may be detached or hold any branch.
IF $ARGUMENTS is not empty
  worktree_path = the `git worktree list` entry whose PATH equals $ARGUMENTS,
                  else whose basename equals $ARGUMENTS,
                  else whose checked-out branch equals $ARGUMENTS
  IF none matched
    ERROR "No worktree found with name/path/branch $ARGUMENTS. Run git worktree list first to confirm."
  IF more than one matched
    ERROR "$ARGUMENTS matches more than one worktree; use the full path instead."
ELSE
  worktree_path = the `git worktree list` entry containing `pwd`
  IF none
    ERROR "The current directory is not inside any worktree; provide a worktree name or path."

IF <worktree_path> is <main_worktree>
  ERROR "Cannot remove the main worktree."

branch = branch checked out in <worktree_path> (may be empty for a detached HEAD)

-- Never remove the worktree this agent session runs in. The session's working directory is the
--   one the session was started in, the provider's own cwd for its whole life, not whatever a
--   shell `cd` last chose. Live (2026-10-20, Codex 0.163.0): a worker
--   removed its own worktree mid-turn; Codex then ran no Stop hook, so Bus never received that
--   answer or the next one and closed both requests as reply_not_captured.
session_cwd = the working directory this agent session was started in
IF <session_cwd> is <worktree_path> or below it
  ERROR "Refusing to remove <worktree_path>: it is this agent session's working directory, and removing it breaks the session's completion hooks. Hand it back: have an agent whose working directory is outside it (for example one in <main_worktree>) run worktree-close on it."

========== CHECK FOR UNSAVED WORK ==========

-- Bus has no submodules, so a plain `git worktree remove` refuses a worktree with modified or
--   untracked files. That refusal covers only the working tree, though: it says nothing about
--   COMMITS that exist only here, and an in-progress merge/rebase/cherry-pick can look clean.
--   These explicit checks are the guard against losing work. Never skip them and never jump
--   straight to --force.

dirty_super = `git -C <worktree_path> status --short`
in_progress = any of MERGE_HEAD / CHERRY_PICK_HEAD / REVERT_HEAD / rebase-merge / rebase-apply
              under `git -C <worktree_path> rev-parse --git-dir`

-- Commits that exist only here are lost too, since this checkout is about to disappear.
-- `--not --remotes` asks the exact question that matters: which commits are reachable from HEAD but
--   from NO remote-tracking ref. Do NOT use `@{upstream}..HEAD`: a worktree-new branch has no
--   upstream on purpose (--no-track), and that command then FAILS, which reads as "nothing
--   unpushed" and would green-light discarding every commit on a brand-new branch. Do NOT use
--   `origin/master..HEAD` either: it false-alarms on a detached worktree or a side branch whose
--   commits are pushed but simply not merged to master (verified — it reported 6 safe commits).
-- CAVEAT: after a PR is squash-merged the remote branch is usually deleted, and once any
--   `fetch --prune` has run there is no remote-tracking ref left holding those commits, so this
--   prints the branch's ENTIRE history as "unpushed" for work that is fully landed. Before reporting
--   it, run merged_by_content(<branch>) from the BRANCH section; when it says MERGED, say
--   "already squash-landed on origin/master; these commits will not be lost" instead of raising the alarm.
unpushed_super = `git -C <worktree_path> log --oneline HEAD --not --remotes`

needs_force = false
IF any of the three is non-empty
  Print "⚠️ <worktree_path> has work that would be discarded:"
  Print the non-empty results, labelled (uncommitted / operation in progress / unpushed)
  Print "Force removal permanently loses the above. Confirm to continue?"
  -- STOP and wait for explicit user confirmation. Do NOT proceed on your own judgement.
  needs_force = true after the user confirms

========== RESCUE CLAUDE MEMORY ==========

-- Claude Code keys auto-memory by ABSOLUTE project path (~/.claude/projects/<slug>/memory/, slug =
--   abs path with every "/" → "-"). worktree-new symlinks the worktree's memory dir to the main
--   repo's, so normally there is nothing to rescue. But a worktree created BEFORE that linking
--   existed holds a REAL memory dir that would be silently orphaned once this worktree is gone.
-- (Codex needs nothing: ~/.codex/memories is a single global store.)

main_slug = <main_worktree> abs path with every "/" replaced by "-"
wt_slug   = <worktree_path> abs path with every "/" replaced by "-"
main_mem  = ~/.claude/projects/<main_slug>/memory
wt_mem    = ~/.claude/projects/<wt_slug>/memory

IF <wt_mem> exists AND is a real directory (NOT a symlink) AND holds any *.md
  `mkdir -p "<main_mem>" && cp -n "<wt_mem>"/*.md "<main_mem>"/ 2>/dev/null`
  Print "Merged the worktree's Claude memory files into the main repo's shared store (MEMORY.md index conflicts need a manual check)."

========== REMOVE THE WORKTREE ==========

IMPORTANT: Do NOT `cd`. Use `git -C <main_worktree>` for every git command from here on.

IF needs_force
  `git -C <main_worktree> worktree remove --force <worktree_path>`
  -- One --force is enough; a second invocation errors with "is not a working tree".
ELSE
  `git -C <main_worktree> worktree remove <worktree_path>`
  -- If this still refuses, something changed since the check: go back to CHECK FOR UNSAVED WORK.
-- This also removes .git/worktrees/<name>/ and the ignored target/ inside the worktree.

`git -C <main_worktree> worktree prune`

========== BRANCH ==========

-- Deleting the worktree does NOT retire <branch>; it stays a normal branch in the main repo.
--   Split by whether its work already landed:
--     LANDED     → delete it here, no question asked. Its commits are all reproducible from

From asura1234/bus, Apache-2.0.

More from asura1234/bus

Signals

Stars
1
Forks
0
Open issues
0
Last commit (this folder)
Oct 20, 2026 (9 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
Apache-2.0
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from asura1234

Cite this page

worktree-close skill. Agent Mart. https://agentmart.dev/skills/asura1234-worktree-close (last updated 2026-10-24)