A multi-repo workspace management tool. Built on Git Worktree + Zellij + LazyGit.
- Multi-repo management - Work on the same branch across multiple repositories simultaneously
- Workspaces - Create, manage, and clean up workspaces
- Zellij integration - Automatically launch a well-organized terminal environment
- Hook system - Custom hooks support (simple/file/inline)
- File copying - Automatically copy config files to worktrees
- Template system - Save and reuse workspace configurations
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/weineel/zootree/releases/download/v0.0.1/zootree-installer.sh | shbrew install weineel/tap/zootreecargo install --path .zootree supports completion for subcommands, flags, and dynamic values (workspace names, repo names, template names) on bash, zsh, fish, PowerShell, and elvish.
Append one line to your shell's rc file. The script is regenerated on every
shell start, so it stays in sync with the installed zootree binary — no
manual refresh after upgrades.
| Shell | Add to | Line |
|---|---|---|
| bash | ~/.bashrc |
eval "$(zootree completions bash)" |
| zsh | ~/.zshrc (after compinit) |
eval "$(zootree completions zsh)" |
| fish | ~/.config/fish/config.fish |
zootree completions fish | source |
| PowerShell | $PROFILE |
zootree completions powershell | Out-String | Invoke-Expression |
| elvish | ~/.config/elvish/rc.elv |
eval (zootree completions elvish | slurp) |
Restart your shell (or source the rc file) to activate.
- All subcommands and flags
zootree start <TAB>— pending workspaceszootree open <TAB>/zootree done <TAB>— in-progress workspaceszootree cancel <TAB>— pending or in-progress workspaceszootree repo edit <TAB>/zootree repo remove <TAB>— registered reposzootree template save --from <TAB>— any workspacezootree create --template <TAB>— saved templateszootree create --repos <TAB>— registered repos (comma-separated)zootree list --status <TAB>— workspace status values (pending, in-progress, done, canceled)zootree done --strategy <TAB>— merge strategy values (squash, rebase, merge)
zsh and fish additionally show a brief description (workspace title + status, repo path, or template repos) next to each candidate.
If completions don't activate after install, verify the dynamic interceptor:
COMPLETE=zsh zootree -- zootree start ''This should output candidates one per line. If empty, ensure you have
workspaces with the expected status (zootree list).
mkdir -p ~/.config/zootree# Interactive
zootree repo add
# From path (name auto-extracted)
zootree repo add ~/projects/myrepo
# With options
zootree repo add ~/projects/myrepo --name myrepo --default-target-branch develop# Interactive
zootree create
# With options
zootree create --title "New feature" --repos frontend:feature/abc,backend:feature/abczootree start
# Or specify by name
zootree start my-workspace# Merge branches and clean up
zootree done
# Merge only, no cleanup
zootree done --no-clean
# Merge and push
zootree done --pushzootree repo add <path> # Add a repository
zootree repo list # List repositories
zootree repo remove <name> # Remove a repositoryzootree create [options] # Create a workspace
--title <title> # Title
--name <name> # Workspace name
--repos <repos> # Repo list (repo:branch format)
--branch <branch> # Branch name
--template <name> # Use a template
zootree start [name] # Start a workspace
--no-zellij # Don't launch Zellij
--run-agent [alias|command] # Launch a coding agent (see Configuration → Agent CLI)
zootree list # List workspaces
--status pending|in-progress|done|canceled
zootree open [name] # Open an existing workspace
zootree done [name] # Finish a workspace
--no-merge # Skip merge
--no-clean # Skip cleanup
--push # Push branches
--force # Force execution
zootree cancel [name] # Cancel a workspace
--no-clean # Skip cleanup
--force # Force executionzootree template list # List templates
zootree template save <name> --from <workspace>
# Save a workspace as a templatezootree prune # Clean up orphaned worktrees
zootree logs # View logszootree reads configuration from ~/.config/zootree/. Quick map:
| File / Field | Purpose |
|---|---|
config.toml |
Global defaults: workspace root, branch prefix, file copying, hooks, agent CLI |
repos/<name>.toml |
Per-repo overrides: path, target branch, copy files, hooks, lazygit config |
layouts/<name>.kdl |
Custom zellij layouts referenced from [zellij].layout |
[hooks] blocks |
Shell commands run at workspace/repo lifecycle events |
agent_cli / agent_cli_alias |
Coding agent template launched by zootree start --run-agent |
workspace_root = "~/zootree-workspaces"
branch_prefix = "zootree"
copy_files = [".env"]
agent_cli = "claude --dangerously-skip-permissions -- $prompt"
[zellij]
layout = "default"
[hooks]
post_create = "echo created"
post_start = "echo started"
pre_done = "echo done"
pre_cancel = "echo canceled"
pre_remove = "echo removed"
[log]
max_files = 5path = "~/projects/myrepo"
default_target_branch = "develop"
copy_files = [".env.local", ".vscode/settings.json"]
[hooks]
post_create = "npm install"
[lazygit]
config = "~/projects/myrepo/.lazygit.yml"# Simple command
post_create = "echo hello"
# File script
pre_remove = { file = "~/.config/zootree/hooks/cleanup.sh" }
# Inline script
pre_done = { inline = "echo 'cleaning up' && rm -rf $ZOOTREE_WORKTREE_PATH" }Available environment variables in hooks:
ZOOTREE_WORKSPACE- Workspace nameZOOTREE_REPO- Repository nameZOOTREE_BRANCH- Branch nameZOOTREE_TARGET_BRANCH- Target branchZOOTREE_WORKTREE_PATH- Worktree pathZOOTREE_WORKSPACE_DIR- Workspace directory
layout {
tab {
pane { name "frontend" }
pane { name "backend" }
}
}Available variables:
@REPO_NAME@- Repository name@WORKTREE_PATH@- Worktree path@BRANCH@- Branch name@WORKSPACE_NAME@- Workspace name@WORKSPACE_DIR@- Workspace directory
agent_cli is a command template for launching a coding agent in a zellij pane. The template is parsed with shell-style word splitting, and $prompt is substituted with the workspace's title (joined with description by a newline if present). $prompt may also be embedded inside a token, e.g. --prompt=$prompt.
The rendered command runs in:
- 1 repo → the repo tab's bottom-right pane
- ≥2 repos → the overview tab's last pane
Without --run-agent, those placeholder panes fall back to a regular shell.
agent_cli accepts either a literal command template or the name of an entry in agent_cli_alias:
agent_cli = "claude" # references alias "claude"
[agent_cli_alias]
claude = "claude --dangerously-skip-permissions -- $prompt"
claude-safe = "claude -- $prompt"
gemini = "gemini chat -- $prompt"
codex = "codex --skip-confirm -- $prompt"Alias lookup is single-level: a value not present in agent_cli_alias is used as a literal command (no warning).
zootree start ws # no agent
zootree start ws --run-agent # use agent_cli (default, "claude" here)
zootree start ws --run-agent claude-safe # switch to alias claude-safe
zootree start ws --run-agent="codex --skip -- $prompt" # literal command- Place
--run-agentafter the workspace name.zootree start --run-agent wswould treatwsas the alias value and leave the positional name empty (interactive picker). - Shell completion (
--run-agent <TAB>) lists all alias names; the entry matching the currentagent_clivalue is annotated(default).
-v, --verbose # Verbose output
-q, --quiet # Quiet output
-h, --help # Help
-V, --version # Version- Git
- Zellij
- LazyGit (optional)
首次克隆本仓库后,执行一次 cargo check --tests 以激活 pre-commit hook:
cargo check --testscargo-husky 会把 .cargo-husky/hooks/pre-commit 安装到 .git/hooks/。此后 git commit 会自动对已暂存的 .rs 文件运行 rustfmt 并把格式化结果纳入本次提交——CI 的 cargo fmt --check 通常就不会再被格式问题绊住。
若需要临时跳过 hook(例如紧急修复),可用 git commit --no-verify。