npm.io
0.5.2 • Published yesterdayCLI

@cestoliv/wt

Licence
Version
0.5.2
Deps
6
Size
96 kB
Vulns
0
Weekly
0

wt

A fast TUI for git worktrees — browse, create, open, and delete without leaving the terminal. Plus one-command AI agents:

wt agent fix-auth "Plan the auth refactor"

→ spins up an isolated worktree and launches Claude in Zed, pre-loaded with your prompt.

Install

npm install -g @cestoliv/wt   # also the update command

Requires Node.js 20+ and Git. The command is wt. Optionally install the gh and/or glab CLIs (authenticated) to let wt prune confirm merges via merged PRs/MRs — see Prune.

Let your AI assistant set it up

Already using an AI coding assistant (Claude Code, Cursor, …)? Paste this prompt — it reads wt skill to learn the tool, then configures wt for you:

Run `wt skill` to learn how the `wt` CLI works and what its config options are.
Then configure it for me: choose sensible values for my editor, base branch,
setup commands, and the `wt agent` settings — ask me about anything you can't
infer from this project. Write the result to the config file (find its path with
`wt config --path`), then show me the final config.

Quick start

wt                                        # Browse worktrees (interactive TUI)
wt create my-feat                         # New worktree, opens your IDE
wt agent my-feat "Plan the feature"       # New worktree + AI agent in Zed (macOS)
wt agent fix-bug "Fix bug" --mode auto    # Use auto mode instead of the default
wt prune                                  # Remove merged worktrees (per-branch confirm)
wt config                                 # Edit config in $EDITOR
wt skill                                  # Print the skill file (for AI agents)

wt agent <branch> <plan_prompt> [--mode <mode>] — the standout

wt agent feat/login "Read the codebase, then propose a plan for login."
wt agent fix-bug "Fix the auth bug" --mode auto
wt agent refactor "Refactor API layer" --mode default

Creates a worktree exactly like wt create, then auto-starts your agent (default claude, run with --permission-mode default) in Zed's integrated terminal — pre-filled with your prompt and left interactive for you to take over.

Available modes (--mode, defaults to default; change the default with the agent_mode config key):

  • default — Standard interactive mode with approval for each action (default)
  • acceptEdits — Allow file changes but keep command execution controlled
  • plan — Architecture-first mode with no surprise mutations
  • auto — Claude's safety model makes decisions instead of prompting
  • dontAsk — Minimal interruptions in trusted environments
  • bypassPermissions — Skip all permission checks (dangerous, CI/sandbox only)

Under the hood it writes a temporary .zed/tasks.json, installs a global Zed keymap chord, opens Zed and fires the chord via osascript, then removes the temp task so the repo stays clean.

Requires macOS, Zed, and Accessibility permission for the app running wt. Not granted yet? wt agent opens System Settings → Privacy & Security → Accessibility, waits while you grant it (you may need to quit and reopen the app), then retries automatically. On other platforms — or when ide isn't zed — the worktree is still created and opened, just without the agent.

If the path already exists, wt agent offers to open it — or open it and start the agent — instead of erroring (in a non-interactive shell it exits non-zero).

Tip: trust the parent directory of your worktrees in Claude once, and every worktree created beneath it starts hands-free.

Browse — wt

An interactive, fuzzy-searchable list of your worktrees:

MY-PROJECT
  ▶ main            (main)  ~/dev/my-project
      fix: resolve auth bug (2h ago)
    feat/dashboard  ~/dev/my-project-feat-dashboard
      wip: add chart component (1d ago)

↕ navigate · Enter open · D delete · P prune · C create · A agent · Q quit

Type to fuzzy-filter branches instantly. Inside a repo it shows that repo's worktrees; run it outside any repo ("home") to browse worktrees across all registered repos.

C creates a worktree and A creates one and starts an AI agent in it — both work from anywhere and are step-by-step wizards. Run from home and they first prompt for the repo, then the branch (C stops there); A adds a plan prompt and a permission mode — worktree (repo → branch) → plan prompt → permission mode. Pressing Esc steps back to the previous question (answers preserved), or back to the list from the first step. After creating, the list refreshes and stays open (preserving your search and cursor) instead of exiting — only Enter and Q/Esc leave the TUI. P prunes every worktree whose branch has already been merged (see wt prune below). Note that a/c/d/p are command keys, so they can't be typed into the search box.

The main worktree is tagged (main) and is protected — D only removes linked worktrees, never the main repository.

Create — wt create [branch]

wt create feat/login   # From base branch (origin/main by default)
wt create              # Prompts for a branch name

Creates a worktree as a sibling directory (../my-project-feat-login), runs your setup_commands, and opens it in your IDE. Run it outside a repo to pick from registered repos.

If the path already exists, wt create offers to open it in your IDE instead of erroring (in a non-interactive shell it exits non-zero).

Prune — wt prune

wt prune   # remove every merged worktree, one confirmation per branch

Cleans up the worktrees you're done with: it finds every worktree whose branch has already been merged into the base branch (base_branch, default origin/main) and removes it — always confirming each branch individually, and force-confirming when git refuses (submodules or uncommitted changes), just like a manual D delete. The branch itself stays; only the worktree is removed. Your teardown_commands run before each removal.

Merge detection is tiered. Patch-id matches (via git cherry) catch a single-commit branch squash-merged through a PR, offline. For the ambiguous case — the branch tip is an ancestor of base but 0 commits ahead, which both a fast-forward / merge-commit merge and a worktree holding only uncommitted work produce — it consults the forge: a merged PR/MR (via gh for GitHub or glab for GitLab, including self-hosted, auto-detected from the remote) is the only reliable signal, so a branch with unmerged work-in-progress is never mistaken for merged. If no forge CLI is available (or you're offline) such branches are simply left alone. A worktree still sitting exactly on the base commit is never offered. wt prune best-effort fetches the remote first; if the base ref can't be resolved (offline, missing), it removes nothing. The TUI exposes the same action under the P key. Works in repo mode and across all registered repos in global mode (each against its own base_branch).

Configuration

Edit with wt config (wt config --path prints the file location — ~/Library/Preferences/wt-nodejs/config.json on macOS).

Key Default Description
ide "zed" Editor to open worktrees with
ide_open_args ["-n"] Extra args passed to the IDE command
base_branch "origin/main" Branch new worktrees are created from
worktree_path "../" Where worktrees are placed (relative to repo)
setup_commands [] Commands to run in new worktrees
teardown_commands [] Commands to run in a worktree just before it is deleted (e.g. ["docker compose down -v"])
agent_command "claude" Base command; --permission-mode <mode> injected, then prompt appended
agent_mode "default" Default permission mode for wt agent (overridden by --mode)
agent_trigger_chord "ctrl-shift-cmd-c" Zed keymap chord wt agent installs and presses
auto_refresh_minutes 5 How often the interactive list re-fetches worktrees (shows a "last refreshed" header); 0 disables it
repo_overrides {} Per-repo overrides for any key above

Override any key per repo:

{
  "repo_overrides": {
    "/path/to/repo": {
      "base_branch": "origin/develop",
      "setup_commands": ["pnpm install", "pnpm build"]
    }
  }
}

Pre-release builds

Add the publish-dev label to a PR to publish that branch as a unique, pinned prerelease (e.g. 0.1.0-pr12.gabc1234); the exact install command is posted as a PR comment. There's no rolling dev channel — each build is a distinct version you install explicitly.

License

MIT