grove is a CLI for creating multi-repository development workspaces backed by git worktree.
A workspace is a directory containing one worktree per repository, while canonical clones are cached separately.
By default, grove uses:
~/.grove/repos/ # canonical cached clones
~/groves/<workspace>/ # generated workspaces
Example:
~/groves/auth-feature/
api/
web/
worker/
- initialize a workspace from multiple repositories
- add repositories to an existing workspace
- remove repositories from an existing workspace
- inspect branch and dirty state across all repos in a workspace
- list known workspaces
- remove workspace worktrees without deleting canonical clones
- navigate to a workspace with shell integration via
grove cd
- Go 1.25+ to build the binary
- Git installed and available on
PATH - GitHub authentication via
gh auth loginorGITHUB_TOKENfor GitHub repo discovery
Standard build:
go build -o grove ./cmd/groveIf your environment restricts the default Go cache location:
GOCACHE=/tmp/grove-gocache CGO_ENABLED=0 go build -o grove ./cmd/groveInstall the latest release:
curl -fsSL https://raw.githubusercontent.com/rohankmr414/grove/main/scripts/install.sh | shInstall a specific version:
curl -fsSL https://raw.githubusercontent.com/rohankmr414/grove/main/scripts/install.sh | sh -s -- v0.1.0Upgrade an existing installation to the latest release:
curl -fsSL https://raw.githubusercontent.com/rohankmr414/grove/main/scripts/install.sh | shBy default the script installs to ~/.local/bin. Override that with INSTALL_DIR:
curl -fsSL https://raw.githubusercontent.com/rohankmr414/grove/main/scripts/install.sh | INSTALL_DIR=/usr/local/bin shCurrent install script targets:
- macOS:
amd64,arm64 - Linux:
amd64,arm64
Upgrade behavior:
- if the requested version is already installed at the target path, the script exits without replacing the binary
- if a different version is installed at the target path, the script replaces it in place
- if no compatible existing
grove versionoutput is available, the script proceeds with installation
After install or upgrade, the script prints shell integration commands so grove cd and auto-entering a workspace after grove init work immediately.
It also creates a default config at $XDG_CONFIG_HOME/grove/config.yaml when XDG_CONFIG_HOME is set, or ~/.config/grove/config.yaml otherwise, if one does not already exist. The same default config directory also gets a workspace-init/ folder for files you want copied into every new workspace.
Config file:
$XDG_CONFIG_HOME/grove/config.yaml
# or, if XDG_CONFIG_HOME is unset:
~/.config/grove/config.yaml
Example:
workspace_root: ~/groves
repo_cache_root: ~/.grove/repos
github:
enabled: true
orgs:
- acmeNotes:
github.orgsis optional- if
orgsis empty,grovequeries repositories visible to the authenticated GitHub user - cached canonical clones under
repo_cache_rootare also used as a discovery source - files placed in
$XDG_CONFIG_HOME/grove/workspace-init/, or~/.config/grove/workspace-init/whenXDG_CONFIG_HOMEis unset, are copied into the root of each newly initialized workspace - this is useful for files like
CLAUDE.md,.tool-versions, or team-specific bootstrap docs
Auth priority:
gh auth tokenGITHUB_TOKEN
If neither is available, GitHub discovery is skipped and grove falls back to cached repository metadata and cached canonical clones.
GitHub repo metadata is cached at ~/.grove/cache/repos.json. grove uses that cache immediately when it exists and refreshes it in the background during init and repo add, which keeps repeated commands fast without blocking on GitHub every time.
Initialize a workspace:
./grove init auth-featureAdd repositories to the current workspace:
cd ~/groves/auth-feature
./grove repo addRemove repositories from the current workspace:
cd ~/groves/auth-feature
./grove repo removeShow workspace status:
./grove status auth-featureOr from inside a workspace:
./grove statusRemove a workspace:
./grove remove auth-featurePrint a workspace path:
./grove path auth-featureList workspaces:
./grove listShow command help:
./grove help init
./grove --helpgrove cd and auto-jumping after grove init require shell integration because a subprocess cannot change the parent shell's working directory.
Enable it for the current shell:
eval "$(./grove shell-init zsh)"Then:
grove cd auth-featureWith shell integration enabled, this will also drop you into the workspace after a successful init:
grove init auth-featureThe generated shell integration also loads Cobra-generated shell completion. You can also install completion directly:
./grove completion zsh
./grove completion bashTo enable it permanently in zsh, add this to ~/.zshrc:
eval "$(/absolute/path/to/grove shell-init zsh)"When you initialize a workspace, grove:
- discovers repositories from cached clones and GitHub
- lets you choose repositories interactively
- ensures a canonical clone exists under
repo_cache_root - fetches latest refs
- creates a worktree under the workspace directory
Workspace branches use:
workspace/<workspace>
If that branch does not exist, grove creates it from the repository default branch.
Each workspace also includes VS Code metadata:
.vscode/settings.jsonenables Git repository detection in subfolders and scans two levels deep, so opening the workspace root withcode .finds each repo more reliably.- top-level files in
~/.config/grove/workspace-init/are copied into the workspace root before repositories are added.