Git Worktree Workspace Orchestrator
Project description
Grove (gw)
grove /ɡrōv/ noun — a small group of trees growing together.
Why?
Monorepos solve cross-project work, but not everyone has one. You've got separate repos, separate CI, separate deploys — and that's fine until you need to work across them.
One feature across three services means git worktree add three times, tracking three branches, jumping between three directories, cleaning up three worktrees when you're done. It's annoying.
Grove gives you the multi-repo worktree workflow that monorepos get for free. One command, one workspace, all repos on the same branch.
Install
Homebrew
brew tap nicksenap/grove
brew install grove
PyPI
pipx install gw-cli
# or
pip install gw-cli
From source
uv tool install .
Then add shell integration to your .zshrc (or .bashrc):
eval "$(gw shell-init)"
This enables gw go to change your working directory and auto-cds into new workspaces after gw create.
Usage
# Setup — register one or more directories containing your repos
gw init ~/dev ~/work/microservices
gw add-dir ~/other/repos
gw remove-dir ~/old/repos
gw explore # deep-scan for repos (2–3 levels)
# Workspaces
gw create my-feature -r svc-a,svc-b -b feat/login # create workspace
gw list # list workspaces
gw list -s # list with git status summary
gw status my-feature # git status across repos
gw sync my-feature # rebase all repos onto base branch
gw go my-feature # cd into workspace
gw run my-feature # run dev processes (TUI)
gw add-repo my-feature -r svc-c # add a repo to existing workspace
gw remove-repo my-feature -r svc-a # remove a repo from workspace
gw rename my-feature --to new-name # rename a workspace
gw doctor # diagnose workspace health issues
gw delete my-feature # clean up (worktrees + branches)
# Presets — save repo groups for quick workspace creation
gw preset add backend -r svc-auth,svc-api,svc-worker
gw preset list
gw preset remove backend
gw create my-feature -p backend # use a preset instead of -r
All interactive menus support type-to-search filtering, arrow-key navigation (single-select), or arrow + tab (multi-select) with an (all) shortcut.
Per-repo config
Drop a .grove.toml in any repo to override defaults:
# merchant-portal/.grove.toml
base_branch = "stage" # branch from origin/stage instead of origin/main
setup = "pnpm install" # run after worktree creation
teardown = "rm -rf node_modules" # run before worktree removal
pre_sync = "pnpm run build:check" # run before rebase during sync
post_sync = "pnpm install" # run after successful rebase
pre_run = "docker compose pull" # run before gw run starts
run = "pnpm dev" # started by gw run (foreground)
post_run = "docker compose down" # run on gw run exit / Ctrl+C
All hook keys accept a string or a list of commands:
setup = ["uv sync", "uv run pre-commit install"]
Hook failures are warnings — they never block the operation they're attached to.
Design philosophy
The hook system follows the npm-style pre/post convention: one primitive (run, sync) with optional pre_ and post_ counterparts that fire around it. Instead of building special-purpose features (secret injection, dependency installs, container management), Grove gives you generic hook points and gets out of the way.
| When | Hooks | Example use |
|---|---|---|
| Worktree created | setup |
pnpm install, inject secrets, seed DB |
| Worktree removed | teardown |
rm -rf node_modules, revoke temp creds |
| Before/after rebase | pre_sync, post_sync |
Type-check before rebase, reinstall after |
| Dev session | pre_run, run, post_run |
Pull containers, start dev server, tear down |
gw run
gw run launches a Textual TUI that manages run hooks across all repos. Each repo gets its own log pane with a sidebar showing status indicators (green = running, yellow = starting, red = exited with error).
| Key | Action |
|---|---|
j / k / ↑ / ↓ |
Navigate repos |
g / G |
Jump to first / last |
1–9 |
Quick-select repo by number |
r |
Restart selected repo |
q |
Quit (terminates all processes) |
Pre-run hooks fire before the TUI launches, post-run hooks fire after it exits.
Dashboard (gw dash)
A Textual TUI for monitoring Claude Code agents across all your workspaces. Agents are sorted into a kanban board with four columns — Active, Attention, Idle, Done — based on live status. Inspired by Clorch.
gw dash install # install Claude Code hooks
gw dash # launch the dashboard
gw dash uninstall # remove hooks
| Key | Action |
|---|---|
h / l |
Navigate columns |
j / k |
Navigate cards |
Enter |
Jump to agent's Zellij tab |
y / n |
Approve / deny permission request |
/ |
Search / filter agents |
Escape |
Clear search |
r |
Refresh |
q |
Quit |
How it works
Claude Code hooks write agent state to ~/.grove/status/<session_id>.json on every event. The dashboard polls these files every 500ms and renders a real-time kanban view of all active agents.
Tracked per agent: status, working directory, git branch, dirty file count, last tool used, tool/error/subagent counts, activity sparkline, permission request details, and initial prompt.
Zellij tab matching
When you press Enter to jump to an agent, the dashboard finds the right Zellij tab using a multi-step strategy:
| Priority | Strategy | Example |
|---|---|---|
| 1 | Exact tab name = project name | grove → tab grove |
| 2 | Case-insensitive tab name | Grove → tab grove |
| 3 | Workspace name from CWD matched against tab names | CWD has feat-rewrite → tab matching |
| 4 | CWD path match via zellij action dump-layout |
Agent CWD under tab CWD or vice versa |
| 5 | Project name substring in tab name | api → tab public-api |
Terminal multiplexer integration
Grove integrates with Zellij for tab management. When running inside Zellij:
gw go --close-tabcloses the current Zellij tab (useful when you're done with a workspace)gw dashlets you pressEnterto jump directly to an agent's Zellij tab, andy/nto approve or deny permission requests
Support for tmux and other terminal multiplexers is planned.
Works with AI coding tools
Worktrees mean isolation. That makes Grove a natural fit for tools like Claude Code — spin up a workspace, let your AI agent work across repos without touching anything else, clean up when done:
gw create -p backend -b fix/auth-bug
claude "fix the auth token expiry bug across svc-auth and api-gateway"
gw delete fix-auth-bug # removes worktrees, branches, and workspace
Grove copies your CLAUDE.md into new workspaces, so your agent gets project context from the start.
Requirements
Python 3.12+ (installed automatically by Homebrew)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gw_cli-0.12.14.tar.gz.
File metadata
- Download URL: gw_cli-0.12.14.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d10c034ca7470cad620f87137c98b044dddbbfab4c92d084d284a72a3ad7be9
|
|
| MD5 |
a03bd744f3803ef9fdd204f3fceac9d5
|
|
| BLAKE2b-256 |
c77f309dbed3fbee5e21b2a561d0f4ea161db69e32843da6bf2d1b6b5f2ab3c5
|
Provenance
The following attestation bundles were made for gw_cli-0.12.14.tar.gz:
Publisher:
release.yml on nicksenap/grove
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gw_cli-0.12.14.tar.gz -
Subject digest:
3d10c034ca7470cad620f87137c98b044dddbbfab4c92d084d284a72a3ad7be9 - Sigstore transparency entry: 1191132556
- Sigstore integration time:
-
Permalink:
nicksenap/grove@5f0c6a29d10b470ac843bda42f009b0470379491 -
Branch / Tag:
refs/tags/v0.12.14 - Owner: https://github.com/nicksenap
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f0c6a29d10b470ac843bda42f009b0470379491 -
Trigger Event:
push
-
Statement type:
File details
Details for the file gw_cli-0.12.14-py3-none-any.whl.
File metadata
- Download URL: gw_cli-0.12.14-py3-none-any.whl
- Upload date:
- Size: 74.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
895bf6b25d1356437517bdf466655e4fb8e40206419be6fa35f423467d2b6e66
|
|
| MD5 |
0f7dabafaf14c15b7e5c15ace9ba2c64
|
|
| BLAKE2b-256 |
e6e06fe31ab1a88f7f84576407577e247262019e1113f3a7aaf283c89054b55f
|
Provenance
The following attestation bundles were made for gw_cli-0.12.14-py3-none-any.whl:
Publisher:
release.yml on nicksenap/grove
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gw_cli-0.12.14-py3-none-any.whl -
Subject digest:
895bf6b25d1356437517bdf466655e4fb8e40206419be6fa35f423467d2b6e66 - Sigstore transparency entry: 1191132569
- Sigstore integration time:
-
Permalink:
nicksenap/grove@5f0c6a29d10b470ac843bda42f009b0470379491 -
Branch / Tag:
refs/tags/v0.12.14 - Owner: https://github.com/nicksenap
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f0c6a29d10b470ac843bda42f009b0470379491 -
Trigger Event:
push
-
Statement type: