AI Worktree Manager — Create isolated git worktrees and launch your coding assistant (claude, codex, gemini) in one command.
cwt new fix-auth main
Creates a worktree, checks out a new branch, copies config files, and drops you into an assistant session — all in seconds.
Run cwt inside an existing git repository. Shell integration targets zsh.
Install it, reload your shell, move into any git repository, and run cwt new.
You need zsh and git; assistant CLIs are optional unless you want auto-launch.
If ~/.config/cwt/config.yaml is missing, the first interactive run opens a short setup wizard for that repository. You can keep the default .worktrees layout, reuse an existing Claude or Codex worktree folder, or choose another directory.
# install (recommended)
curl -fsSL https://raw.githubusercontent.com/IamGroooooot/cwt/main/install.sh | sh
# reload your shell
source ~/.zshrc
# move into any git repository
cd /path/to/your/repo
# create a worktree only
cwt new fix-auth --no-launch
# or create a worktree and launch an assistant
cwt new fix-auth --assistant codexIf you're not sure, use the installer. Choose Homebrew for package-managed updates, a plugin manager if you already manage zsh plugins that way, and manual install only when you want a custom checkout path.
curl -fsSL https://raw.githubusercontent.com/IamGroooooot/cwt/main/install.sh | shThis is the shortest path for most users.
It installs cwt, adds the source line, and enables zsh completion automatically.
brew install IamGroooooot/cwt/cwtHomebrew resolves IamGroooooot/cwt to the tap repository IamGroooooot/homebrew-cwt.
After installing via Homebrew, follow the caveats output so your .zshrc points at the Homebrew prefix.
Advanced Homebrew
# latest main branch from IamGroooooot/cwt
brew install --HEAD IamGroooooot/cwt/cwt
# local checkout or uncommitted changes
source ./cwt.shUse brew install for the latest tagged release and --HEAD for the latest main commit from IamGroooooot/cwt.
Homebrew 5 requires formulae to live in a tap, so local checkout testing should source ./cwt.sh directly instead of going through Homebrew.
# zinit
zinit light IamGroooooot/cwt
# antigen
antigen bundle IamGroooooot/cwt
# oh-my-zsh
git clone https://github.com/IamGroooooot/cwt.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/cwt
# then add 'cwt' to plugins=(...) in .zshrcgit clone --depth 1 https://github.com/IamGroooooot/cwt.git ~/.cwt
echo 'fpath=("$HOME/.cwt/completions" $fpath)' >> ~/.zshrc
echo '[[ -f "$HOME/.cwt/cwt.sh" ]] && source "$HOME/.cwt/cwt.sh"' >> ~/.zshrc
echo 'autoload -Uz compinit && compinit' >> ~/.zshrc
source ~/.zshrcIf you install somewhere other than ~/.cwt, replace that path in both lines above.
The installer automatically sets up zsh tab completion. After installing, you get:
cwt <TAB> → new, ls, cd, rm, config, update (with descriptions)
cwt new <TAB> → suggest worktree name
cwt new --<TAB> → --help, --assistant, --claude, --codex, --gemini, --launch-target, --current, --split, --tab, --all-permissions, --default-permissions, --yolo, --dangerously-skip-permissions, --no-launch
cwt cd <TAB> → list existing worktree names
cwt rm <TAB> → list existing worktree names
cwt rm --<TAB> → --help, --force/-f
Manual setup (for plugin managers or custom installs):
# Example: manual install at ~/.cwt
# Add to .zshrc BEFORE compinit
fpath=("$HOME/.cwt/completions" $fpath)
[[ -f "$HOME/.cwt/cwt.sh" ]] && source "$HOME/.cwt/cwt.sh"
autoload -Uz compinit && compinitIf you installed somewhere else, replace $HOME/.cwt with your actual install path.
If you installed via Homebrew, use the caveats output so the path matches your Homebrew prefix.
cwt [global-options] <command> [options]
Commands:
new Create a new worktree and launch an assistant
ls List all worktrees with status
cd Enter an existing worktree
rm Remove a worktree
config Show or change this project's worktree root
update Self-update cwt
Global Options:
-q, --quiet Suppress informational messages
-h, --help Show help
-v, --version Show version
cwt new fix-auth --assistant codex # create + launch in current shell
cwt new fix-auth --assistant codex --split # create + launch in split pane (tmux/zellij)
cwt new fix-auth --no-launch # create only
cwt config ../repo-worktrees # store a worktree root for this repocwt new fix-auth # pick base branch interactively
cwt new fix-auth main # base off main
cwt new fix-auth main feat/x # explicit branch name
cwt new fix-auth --assistant codex # launch codex after create
cwt new fix-auth --gemini # launch gemini after create
cwt new fix-auth --assistant codex --split # tmux pane / zellij pane
cwt new fix-auth --assistant codex --tab # tmux window / zellij tab
cwt new fix-auth --assistant codex --all-permissions # codex + --yolo
cwt new fix-auth --yolo # shortcut: --assistant codex --all-permissions
cwt new fix-auth --dangerously-skip-permissions # shortcut: --assistant claude --all-permissions
cwt new --no-launch my-task # skip assistant launchIf fzf is installed, cwt prefers it for branch selection, worktree picking, and setup-wizard folder/location choices. Otherwise, numbered lists and the arrow-key browser are used.
When the default .worktrees directory is used, cwt new requires .worktrees/ to already be present in .gitignore and refuses to edit the file automatically.
When CWT_AUTO_LAUNCH=false, explicit launch flags (for example --assistant, --split, --tab, --launch-target) still launch.
cwt lsShows each worktree with branch name, clean/dirty status, last commit, and relative time.
The data table is printed to stdout while decorations go to stderr, so output is pipeable:
cwt ls 2>/dev/null | grep dirtycwt cd fix-auth # enter worktree directory
cwt cd fix-auth --assistant codex
cwt cd fix-auth --gemini
cwt cd fix-auth --assistant codex --split
cwt cd fix-auth --assistant codex --tab
cwt cd fix-auth --assistant codex --all-permissions
cwt cd fix-auth --yolo
cwt cd fix-auth --dangerously-skip-permissions
cwt cd # interactive selectionWhen you run cwt cd with no name from inside a linked worktree, it moves you back to the main repository and suggests other available worktrees.
Use launch target options when you want assistant sessions in another pane/tab:
cwt new fix-auth --assistant codex --launch-target split
cwt new fix-auth --assistant codex --split
cwt cd fix-auth --assistant codex --tab
cwt cd fix-auth --assistant codex --currentcurrent(default): launch in current shellsplit: launch in a new split panetab: launch in a new tab (tmuxwindow /zellijtab)
Fallback behavior:
- If launch target is set in config/env and no tmux/zellij session is active, cwt warns and launches in current shell.
- If
--split/--tab/--launch-targetis explicitly passed and no tmux/zellij session is active, cwt returns an error.
Launch precedence in cwt new:
--assistant,--current,--split,--tab, and--launch-targetforce launch even whenCWT_AUTO_LAUNCH=false.- If
--no-launchis passed later in the same command, launch is skipped (last flag wins).
Keep default behavior as-is, and opt in only when needed:
cwt new fix-auth --assistant codex --all-permissions
cwt cd fix-auth --assistant claude --all-permissions--all-permissions: enable full-permission mode- Codex: adds
--yolo - Claude: adds
--dangerously-skip-permissions
- Codex: adds
--default-permissions: force normal/default mode--yolo: shortcut for--assistant codex --all-permissions--dangerously-skip-permissions: shortcut for--assistant claude --all-permissions
cwt rm fix-auth # confirm before removing
cwt rm -f fix-auth # skip confirmation
cwt rm # interactive selectionRemoves the worktree directory and its associated branch.
If you pass a specific name and no worktrees exist, cwt rm <name> returns an error.
cwt updateFor git-based installs (for example ~/.cwt), cwt update pulls the latest commit and re-sources cwt.sh.
If you installed cwt in a custom path, set CWT_DIR before running update:
CWT_DIR=/path/to/cwt cwt updateIf you installed via Homebrew, update with:
brew upgrade IamGroooooot/cwt/cwtIf you installed with --HEAD, fetch the latest main commit with:
brew upgrade --fetch-HEAD IamGroooooot/cwt/cwtIf you installed via a plugin manager, update through the plugin manager, or point CWT_DIR to that plugin checkout and run cwt update.
Use -q or --quiet before the subcommand to suppress informational messages (info and item-level output). Errors and success messages are still shown.
cwt -q new fix-auth main # create worktree quietly
cwt --quiet ls # list with minimal outputWhen stdin is not a TTY (for example in CI or scripts), cwt fails fast instead of waiting on prompts:
cwt newwithout a name returns an error with usage guidance.cwt cdwithout a name returns an error in non-interactive mode only when run from the main repository.cwt rmwithout a name returns an error with usage guidance when worktrees exist.cwt rm <name>without--forcereturns an error because confirmation cannot be prompted.cwt new <name>without a base branch defaults toHEADin non-interactive mode.
Subcommands now reject unknown flags with an error and a help hint:
cwt new,cwt cd,cwt rm,cwt ls, andcwt updatefail on unsupported options.- Use
cwt <command> --helpto see valid options for each subcommand.
Place a .worktreeinclude file in your project root to auto-copy files into new worktrees:
# .worktreeinclude
.env
.env.local
config/*.secret.json
Entries must stay inside the repository. cwt skips parent-path escapes and symlinks that resolve outside the repo.
cwt reads an optional config file on each invocation:
~/.config/cwt/config.yaml
Override the path with CWT_CONFIG=/path/to/config.
If the current git project does not have a cwt entry yet, the first interactive run opens a setup wizard for that project.
The wizard offers the default .worktrees layout, detected Claude or Codex worktree folders when they exist, or a custom directory picker that starts from the parent of your git root.
Use cwt config when you want to inspect or change the worktree root for the current repository:
cwt config # show current project config
cwt config --browse # choose a folder interactively
cwt config ../repo-worktrees
cwt config --default # go back to .worktrees# ~/.config/cwt/config.yaml
version: 1
defaults:
default_base_branch: 'main'
default_assistant: 'claude'
auto_launch: 'false'
launch_target: 'current'
permission_mode: 'default'
cmd_claude: 'claude'
cmd_codex: 'codex'
cmd_gemini: 'gemini'
projects:
- git_root: '/Users/you/src/project-a'
worktree_dir: '../project-a-worktrees'
- git_root: '/Users/you/src/project-b'
worktree_dir: '.worktrees'All options are optional. Unset values keep the default behavior.
The defaults block is global, but projects[*].worktree_dir is stored per git root so each repository can keep its own worktree location.
worktree_dir accepts absolute paths too. Relative paths are resolved from the main git root, not from the directory where you ran cwt.
For safety, cwt rejects obviously unsafe destinations such as /, the git root itself, or anything inside .git.
When a custom worktree root is active, cwt new prints the resolved destination before creating anything.
If you still have the old ~/.config/cwt/config file, cwt will read it as a fallback and switch back to YAML the next time it saves config.
By default, worktrees are created under <project>/.worktrees/<name>.
If the current project has a configured worktree_dir, cwt uses that directory instead and shows the resolved root before creation.
Each worktree gets a new branch (wt/<name>-<rand> by default) and can copy files listed in .worktreeinclude. After setup, the selected assistant command is launched in the worktree directory.
- zsh (macOS default)
- git 2.15+
- fzf (optional, for interactive selection)
- Any supported assistant CLI (optional, auto-launched unless
--no-launch)claudecodexgeminiorgemini-cli
- tmux or zellij (optional, only for
--split/--tab)
For git-based installs (default):
~/.cwt/uninstall.shFor Homebrew installs:
brew uninstall IamGroooooot/cwt/cwtFor plugin-manager installs, remove the plugin checkout and related cwt lines from your shell config.