trees-cli
v0.1.3
Published
Git worktree manager — switch branches like cd
Downloads
249
Readme
trees
Git worktree manager — switch branches like cd.
Git's worktree interface is powerful but clunky. trees wraps it in a simple, opinionated CLI so jumping between branches feels natural.
tree up my-feature # create worktree + cd into it
tree down # cd back to main
tree list # see all worktrees + dirty status
tree switch # interactive picker
tree remove my-featureInstallation
npm install -g trees-cli
source ~/.zshrc # or ~/.bashrcThe install automatically adds a tree shell function to your ~/.zshrc and/or ~/.bashrc. This wrapper is needed because a Node process can't change your shell's directory — tree runs trees under the hood and handles the cd for you.
Commands
tree up <branch>
Switch to a branch worktree, creating it if it doesn't exist yet.
tree up main # switch to main
tree up feature/my-work # create worktree + switchWorktrees are stored at ~/.trees/repositories/<repo>/<branch>.
If a setup hook is configured, it runs automatically when a new worktree is created (not on subsequent switches).
tree down
Return to the main (non-worktree) copy of the repo.
tree remove <branch>
Remove a worktree. If you're currently inside it, you'll be moved to the main repo first.
tree remove feature/my-worktree list
Show all worktrees for the current repo with their dirty status.
BRANCH STATUS PATH
──────────────────────────────────────────────────────
main clean ~/projects/my-app
feature/auth dirty ~/.trees/repositories/my-app/feature/authtree switch
Interactively pick a worktree to switch to (uses arrow keys).
tree clean
Find and remove worktrees whose branches no longer exist locally. Shows a dry-run list and prompts before deleting anything.
tree config
Manage setup and teardown hooks for the current repo.
tree config # show effective config
tree config add setup "npm install" # run after worktree creation
tree config add teardown "npm run clean"
tree config clear setup # remove all setup commandsHooks can be saved globally (~/.trees/config.json) or locally (.treesrc.json in the repo root). You'll be prompted each time — the default is smart: local if a local config already exists, global otherwise.
Tab Completion
Tab completion is installed automatically alongside the shell function. It works in both zsh and bash:
tree <TAB>— completes subcommands (up,down,remove,list,switch,clean,config)tree up <TAB>— completes all local git branchestree remove <TAB>— completes only active worktree branchestree config <TAB>— completesadd,clear
If you installed before tab completion was added, run trees install to update the shell function, then reload your shell.
Configuration
Global — applies to a named repo across all machines:
// ~/.trees/config.json
{
"repos": {
"my-app": {
"setup": ["npm install"],
"teardown": ["npm run clean"]
}
}
}Per-repo — commit it (or gitignore it) alongside the code:
// .treesrc.json
{
"setup": ["npm install", "npm run bootstrap"],
"teardown": []
}Per-repo config takes precedence over global.
Contributing
Prerequisites
- Node 18+
- npm 9+
Setup
git clone https://github.com/<you>/trees
cd trees
npm install
npm run build
npm link # makes `trees` available in your PATH
source ~/.zshrc # shell function is auto-installed by postinstallDevelopment
npm run dev # watch mode — rebuilds on saveTest your changes directly with tree <command> in any git repo.
Project structure
src/
index.ts # CLI entrypoint (commander)
commands/
up.ts # tree up <branch>
down.ts # tree down
remove.ts # tree remove <branch>
list.ts # tree list
switch.ts # tree switch
clean.ts # tree clean
config.ts # tree config
lib/
git.ts # git operations (child_process)
config.ts # load/merge global + per-repo config
paths.ts # ~/.trees/repositories/<repo>/<branch>
shell.ts # __TREES_CD__ signal
hooks.ts # run setup/teardown commandsThe cd mechanism
tree up <branch> needs to change your shell's directory. Since Node can't do that directly, the mechanism works like this:
- The
treeshell function creates a temp file and passes it viaTREES_CD_FILE trees(Node) writes the target path to that file- The shell function reads the file and runs
cd
This approach lets trees run with a direct TTY connection, so interactive prompts (like tree switch or tree config add) work correctly.
Releasing
Releases are automated via auto. Labels on PRs drive version bumps:
| Label | Version bump | Appears in changelog |
|---|---|---|
| major | 1.0.0 → 2.0.0 | Yes — Breaking Changes |
| minor | 1.0.0 → 1.1.0 | Yes — Features |
| patch | 1.0.0 → 1.0.1 | Yes — Bug Fixes |
| documentation | none | Yes — Documentation |
| internal | none | Yes — Internal |
| dependencies | none | Yes — Dependencies |
| skip-release | none | No |
When a PR merges to main, CI runs auto shipit which:
- Determines the version bump from PR labels
- Bumps
package.jsonversion - Appends to
CHANGELOG.md - Creates a GitHub release + git tag
- Publishes to npm
First-time setup (one-time, after pushing the repo to GitHub):
Add repo secrets in GitHub → Settings → Secrets:
GH_TOKEN— a GitHub personal access token withreposcopeNPM_TOKEN— an npm access token with publish rights
Create the PR labels on the repo (one-time):
GH_TOKEN=<your-token> npx auto create-labelsOr trigger the
Create Labelsworkflow manually from the Actions tab.Tag the initial version so
autohas a baseline:git tag v0.1.0 git push --tags
