Install
openclaw skills install @haoranyu/clean-closed-issue-worktreesSafely audit and remove worktrees for closed issues
openclaw skills install @haoranyu/clean-closed-issue-worktreesClean completed worktrees through a mandatory scan-confirm-execute protocol. Match the language of all user-facing questions, reports, warnings, and results to the user's current language. Preserve commands, paths, branch names, and provider field names verbatim.
Resolve relative resource paths in this file from the skill directory. Before invoking the bundled script, resolve scripts/worktree_cleanup.py to an absolute path so the command does not depend on the target repository's working directory.
rm -rf, git worktree remove --force, git branch -D, unresolved variables, globs, or inferred paths.Identify the repository named by the supplied GitHub/GitLab URL and match it to an exact local remote. Do not assume the remote is origin or the default branch is main/master. If matching is ambiguous, ask the user.
Before browser use, look for a purpose-built provider skill, connector, or MCP. Then try an already authenticated gh/glab, then the official read-only API for public repositories. Use a browser MCP or built-in browser only as the last fallback. If all routes fail, ask the user for access or a closed-issue export. Read provider-access.md when selecting or using a provider route.
Extract candidate issue numbers from local branch names and closing commit messages, then verify each exact item against the provider. Do not treat the first page or first 100 results as exhaustive. Respect explicit filters in the supplied list URL.
Query harness task/session state when tools expose it. Read harness-detection.md for Codex, Claude Code, and unknown harness handling.
Run the local inventory script from a directory outside every removal candidate:
python3 <skill-root>/scripts/worktree_cleanup.py scan \
--repo /absolute/path/inside/repository \
--baseline <matched-remote>/<default-branch> \
--json-out "$TEMP_DIR/scan.json" \
--stdout none
Classify every registered worktree:
closed (or the direct PR/MR is merged), the worktree is clean and unlocked, the harness task is proven inactive or not managed, risky ignored paths are absent, and HEAD is retained by a local/remote ref or the baseline.Report exact paths, issue/PR/MR links and states, branch/detached state, dirty status, harness status, commit retention, ignored-path risks, per-worktree size, and the total estimated reclaimable space. Call directory-size totals estimated reclaimable space, not exact filesystem savings.
Ask one decision at a time when material choices are missing, provide a recommended answer, and look up discoverable facts instead of asking. For the final confirmation, identify the exact batch and state the default recommendation to retain branches.
Strong evidence is one of:
1459-fix-name or issue-1459-name;Closes #1459, provided the worktree has not been reused by another task.Directory numbers, title similarity, ordinary Ref #1459, multiple matches, or a mismatched repository are not strong evidence.
git status can be clean while ignored files would still be deleted. The script reports ignored top-level paths without reading their contents.
node_modules, .venv, dist, build, target, and coverage are considered regenerable and contribute to the space estimate..env*, keys, databases, credentials, uploads, local configuration, and unknown ignored paths require review and explicit approval.Do not enter this phase until the user has seen Phase 1 results and explicitly selected exact targets and branch behavior.
Read evidence-schema.md. Create the normalized selection and plan only in a system temporary directory. Do not add them to the target repository.
If a selected detached HEAD has no retaining ref, offer a backup branch first. Creating it is a separate write and must be included in the user's explicit approval. Use worktree-cleanup/backup-YYYYMMDD-<short-sha> and never overwrite an existing ref.
Create the immutable plan. The script refuses locally unsafe selections:
python3 <skill-root>/scripts/worktree_cleanup.py create-plan \
--repo /absolute/path/inside/repository \
--selection "$TEMP_DIR/selection.json" \
--output "$TEMP_DIR/plan.json"
Immediately before execution, re-query every exact issue/PR/MR and harness task state. Abort if an issue reopened, a PR/MR is no longer authoritative, or a task became active.
Execute only with the exact plan_id shown in the confirmation. The script rechecks the whole batch before the first mutation and aborts if HEAD, branch, dirty state, ignored paths, retaining refs, baseline, lock state, registration, path resolution, or repository identity changed:
python3 <skill-root>/scripts/worktree_cleanup.py execute \
--plan "$TEMP_DIR/plan.json" \
--confirm-plan <exact-plan-id> \
--delete-plan-on-success
When branch deletion was explicitly selected, require a baseline and permit only git branch -d. Squash/rebase branches with unique commits remain preserved unless the user separately approves a backup workflow.
Verify that removed directories and Git registrations are gone, retained branches/backups exist, protected worktrees are unchanged, and report the estimated space reclaimed plus any failures. Delete temporary artifacts after success; export Markdown/JSON only when the user requests a saved audit record.
Never treat prunable as permission. Report it separately. The bundled script intentionally refuses prunable metadata; use a separate exact, user-confirmed recovery or prune workflow after verifying the closed issue and missing directory.
The bundled script requires Python 3.9+ and Git. Provider and harness access remains outside the script so the same skill can run in Codex, Claude Code, and other agent environments without reading credential stores or browser cookies.