Skip to content

feat: support removing multiple worktrees at once#19

Merged
Jercik merged 10 commits intomainfrom
multiple-choice
Feb 27, 2026
Merged

feat: support removing multiple worktrees at once#19
Jercik merged 10 commits intomainfrom
multiple-choice

Conversation

@Jercik
Copy link
Copy Markdown
Owner

@Jercik Jercik commented Feb 26, 2026

Summary

  • CLI argument changes from [target] to variadic [target...], allowing worktree-remove feat/a feat/b feat/c
  • Interactive mode (-i) now uses a multi-select checkbox instead of single-select
  • Unified orchestration: all targets (single or multiple) route through removeBatch, eliminating the duplicated resolution/preflight logic that previously existed in removeWorktree
  • Batch path resolves all targets upfront, checks all for uncommitted changes with a single prompt, confirms once, then removes in parallel (p-limit, concurrency 4)
  • Single-target invocations get compact confirmation prompts and skip the batch summary
  • performWorktreeRemoval returns a discriminated union (status: "ok" | "failed" | "cancelled") so batch accounting accurately tracks failures and user cancellations exit cleanly

Test plan

  • pnpm exec vitest run — all 53 tests pass
  • pnpm exec tsc -b --noEmit — type-check passes
  • pnpm exec eslint src/ — no lint errors
  • pnpm run fta — all files under complexity threshold
  • Manual: node --experimental-strip-types src/cli.ts -i — shows checkbox multi-select
  • Manual: node --experimental-strip-types src/cli.ts branch1 branch2 — removes both
  • Manual: node --experimental-strip-types src/cli.ts --dry-run -i — shows what would be removed for multiple selections

Add multi-select to both interactive and non-interactive modes:
- CLI argument changes from [target] to variadic [target...]
- Interactive mode uses checkbox (multi-select) instead of single select
- Batch path resolves all targets upfront, checks uncommitted changes
  once, confirms in a single prompt, then removes in parallel (p-limit)
- Single target still uses the existing removeWorktree flow
github-actions[bot]

This comment was marked as resolved.

Jercik

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

…ccounting

performWorktreeRemoval has failure paths that return without throwing,
causing Promise.allSettled to count them as fulfilled. The batch summary
would over-report success (e.g. "Removed 2 of 2" when one failed).
Return { ok: boolean } so removeBatch can accurately track outcomes.
github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

Route all targets through removeBatch, eliminating the duplicated
resolution/preflight logic in removeWorktree. The batch path now
handles n=1 with appropriate singular grammar and compact confirmation
prompts. Delete remove-worktree.ts entirely.

Extract cwd-switch detection and handling into handle-cwd-switch.ts
to keep remove-batch.ts within complexity thresholds.
@Jercik

This comment has been minimized.

@Jercik

This comment has been minimized.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

- Return ok:false from performWorktreeRemoval when git unregister fails
- Force-skip internal prompts in multi-target batch (prevents concurrent
  readline races since user already confirmed in Phase 2)
- Use "Would remove" instead of "Removed" in dry-run summary
- Log explicit failure line for fulfilled-but-not-ok results
- Deduplicate targets by normalized path before processing
github-actions[bot]

This comment was marked as resolved.

- prepareCwdSwitch now finds the actual target containing cwd instead of
  always using the first target's name
- performWorktreeRemoval returns ok:false when git unregister fails
- Multi-target batch passes force:true to skip internal prompts
- Dry-run summary uses "Would remove" wording
- Batch summary logs explicit failure for fulfilled-but-not-ok results
github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

Add `skipTrashFailurePrompt` to `performWorktreeRemoval` so batch mode
can prevent concurrent readline races without also enabling destructive
fallback when trash fails. Multi-target batches now report trash failures
as errors instead of silently proceeding with `git worktree remove --force`.

Also error when all batch targets resolve to empty instead of silently
returning success (regression from the single-target path).
github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

Single-target failures now exit with code 1, matching multi-target
behavior. Previously, single-target mode skipped Phase 4 entirely,
causing performWorktreeRemoval failures to silently exit 0.
github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

Use a discriminated union (status: "ok" | "failed" | "cancelled") for
PerformWorktreeRemovalResult instead of a boolean. Single-target user
cancellation (declining the trash-failure prompt) now exits cleanly
with code 0 instead of being misreported as a failure with code 1.
github-actions[bot]

This comment was marked as resolved.

Add comment explaining why resolution exits immediately on invalid
targets — it runs before confirmation or removal, so no worktrees
are modified yet.
github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

Wrap the OutputWriter with target-name prefixes (e.g., [foo] Moving
directory to trash...) for multi-target batches so interleaved parallel
output is attributable. Single-target mode is unchanged.

Extract prefixOutput into output-writer.ts and batch result reporting
into report-batch-results.ts to keep remove-batch.ts under the FTA
complexity threshold.
github-actions[bot]

This comment was marked as resolved.

github-actions[bot]

This comment was marked as resolved.

@Jercik Jercik merged commit c75efbf into main Feb 27, 2026
5 checks passed
@Jercik Jercik deleted the multiple-choice branch February 27, 2026 08:51
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 1.4.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant