https://github.com/captainsafia/grove
CLI tool for managing git worktree-based workflows
https://github.com/captainsafia/grove
bun cli git typescript worktrees
Last synced: 3 months ago
JSON representation
CLI tool for managing git worktree-based workflows
- Host: GitHub
- URL: https://github.com/captainsafia/grove
- Owner: captainsafia
- License: mit
- Created: 2025-09-29T02:09:02.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-03-28T23:14:29.000Z (3 months ago)
- Last Synced: 2026-03-29T01:43:50.664Z (3 months ago)
- Topics: bun, cli, git, typescript, worktrees
- Language: Rust
- Homepage: https://grove.safia.sh
- Size: 2.02 MB
- Stars: 61
- Watchers: 1
- Forks: 6
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# grove
Grove is a CLI tool that encapsulates the patterns that I use for working with Git worktrees locally on my machine. To learn more about this pattern, you can check out [this blog post](https://blog.safia.rocks/2025/09/03/git-worktrees/).
## Features
- Initialize repos with a bare clone optimized for worktrees
- Create, list, and remove worktrees
- Sync with origin and prune stale worktrees
- Run commands from anywhere within the project hierarchy
- Shell integration for seamless directory navigation
- Self-update to the latest version or PR build
## Platform Support
- Linux (x64, arm64)
- macOS (x64, arm64)
- Windows (x64)
## Installation
### Quick Install (Linux/macOS)
```bash
curl https://i.safia.sh/captainsafia/grove | sh
```
### Quick Install (Windows PowerShell)
```powershell
irm https://i.safia.sh/captainsafia/grove.ps1 | iex
```
This will download the appropriate binary for your system and install it to `~/.grove/bin`.
To install a specific version:
```bash
curl https://i.safia.sh/captainsafia/grove/v1.0.0 | sh
```
For Windows PowerShell:
```powershell
irm https://i.safia.sh/captainsafia/grove/v1.0.0.ps1 | iex
```
## Usage
### Initialize a new worktree setup
Create a new directory structure optimized for git worktree workflows:
```bash
grove init https://github.com/user/repo.git
```
This command will:
- Create a directory named after the repository (e.g., `repo/`)
- Clone the repository as a bare clone into `repo/repo.git/`
- Configure the remote fetch to support all branches
- Provide instructions for creating worktrees
After initialization, you can create worktrees:
```bash
cd repo
grove add main
grove add feature/new-feature
```
### Add a new worktree
Create a new worktree for a branch:
```bash
grove add feature/new-feature
```
Create a new worktree with an auto-generated adjective-noun name:
```bash
grove add
# Example generated name: quiet-meadow
# If .groverc sets "branchPrefix": "safia", example: safia/quiet-meadow
# Directory remains: quiet-meadow
# branchPrefix only accepts alphanumeric characters
```
Track a remote branch:
```bash
grove add feature/new-feature --track origin/feature/new-feature
```
Bootstrap a newly created worktree with project-scoped commands:
```json
{
"branchPrefix": "safia",
"bootstrap": {
"commands": [
{ "program": "npm", "args": ["install"] },
{ "program": "cargo", "args": ["check"] }
]
}
}
```
Save this as `.groverc` in your Grove project root (the directory that contains your bare clone, for example `repo/.groverc` next to `repo/repo.git`).
When `grove add` is called without an explicit branch name, Grove generates an adjective-noun name and prepends `branchPrefix` to the branch name when configured. `branchPrefix` must be alphanumeric only (letters and numbers). The worktree directory keeps the generated base name.
When `grove add` creates a worktree, it runs each bootstrap command in order inside that new worktree directory.
- Commands must be portable across Linux/macOS/Windows.
- Use executable + args only (no shell syntax like pipes, `&&`, or redirects).
- If one command fails, Grove continues running the remaining commands and reports a partial bootstrap state.
### Remove worktrees
Remove a single worktree:
```bash
grove remove feature/new-feature
```
Remove multiple worktrees at once:
```bash
grove remove feature/new-feature bugfix/login-flake
```
Force removal even with uncommitted changes. When `--force` removes a dirty worktree, Grove skips the confirmation prompt and logs a warning after removal:
```bash
grove remove feature/new-feature bugfix/login-flake --force
```
Skip the confirmation prompt for clean worktrees:
```bash
grove remove feature/new-feature --yes
```
### Navigate to a worktree
Open a new shell session in a worktree directory:
```bash
grove go feature-branch
```
This spawns a new shell in the worktree directory. Exit the shell (Ctrl+D or `exit`) to return to your previous directory.
You can also navigate by partial branch name for nested branches:
```bash
# If you have a worktree for feature/my-feature
grove go my-feature
```
The `GROVE_WORKTREE` environment variable is set to the branch name while in the worktree shell.
#### Shell Integration
For a smoother experience, you can set up shell integration so `grove go` changes your current directory instead of spawning a new shell:
**Bash:**
```bash
echo 'eval "$(grove shell-init bash)"' >> ~/.bashrc
source ~/.bashrc
```
**Zsh:**
```bash
echo 'eval "$(grove shell-init zsh)"' >> ~/.zshrc
source ~/.zshrc
```
**Fish:**
```bash
echo 'eval "$(grove shell-init fish)"' >> ~/.config/fish/config.fish
source ~/.config/fish/config.fish
```
With shell integration enabled, `grove go feature-branch` will directly change your working directory.
### Run Commands from Anywhere
Grove commands work from anywhere within your project hierarchy - you don't need to be in the bare clone directory. Whether you're deep inside a worktree's source code or at the project root, grove automatically discovers the repository:
```bash
# Works from inside a worktree
cd ~/projects/myproject/feature-branch/src/components
grove list # Discovers and lists all worktrees
# Works from the worktree root
cd ~/projects/myproject/feature-branch
grove add another-feature
# Works from the bare clone
cd ~/projects/myproject/myproject.git
grove sync
```
Grove caches the discovered repository path in the `GROVE_REPO` environment variable for faster subsequent commands.
### List all worktrees
```bash
grove list
```
Show detailed information:
```bash
grove list --details
```
Show only dirty worktrees:
```bash
grove list --dirty
```
### Sync with origin
Update the bare clone with the latest changes from origin:
```bash
grove sync
```
This fetches the default branch (main or master) from origin and updates the local reference.
Sync a specific branch:
```bash
grove sync --branch develop
```
### Prune merged worktrees
Preview what would be removed:
```bash
grove prune --dry-run
```
Remove worktrees for branches merged to main:
```bash
grove prune
```
Force removal even if worktrees have uncommitted changes:
```bash
grove prune --force
```
Use a different base branch:
```bash
grove prune --base develop
```
Remove worktrees older than a specific duration (bypasses merge check):
**Note:** When using `--older-than`, the merge status check is bypassed, and all worktrees older than the specified duration will be removed. The `--base` flag cannot be used with `--older-than`.
You can use human-friendly formats (e.g., `30d`, `2w`, `6M`, `1y`) or ISO 8601 duration format (e.g., `P30D`, `P2W`, `P6M`, `P1Y`):
```bash
# Remove worktrees older than 30 days
grove prune --older-than 30d
# Remove worktrees older than 6 months
grove prune --older-than 6M
# Remove worktrees older than 1 year
grove prune --older-than 1y
# Preview what would be removed for worktrees older than 2 weeks
grove prune --older-than 2w --dry-run
# ISO 8601 format is also supported
grove prune --older-than P30D
```
### Self-update
Update grove to the latest version:
```bash
grove self-update
```
Update to a specific version:
```bash
grove self-update v1.0.0
# or
grove self-update 1.0.0
```
Update to a specific PR build (requires GitHub CLI):
```bash
grove self-update --pr 42
```
**Note:** The self-update command uses the same installation script as the initial installation. If you installed grove using the quick install method, this command will update the binary in `~/.grove/bin`. If you installed grove using a different method (e.g., manually downloading the binary), you may need to update it manually.
## Commands
- `grove init ` - Create a new worktree setup
- `grove add [name] [options]` - Create a new worktree
- `grove go ` - Navigate to a worktree
- `grove remove [names]... [options]` - Remove one or more worktrees
- `grove list [options]` - List all worktrees
- `grove sync [options]` - Sync the bare clone with origin
- `grove prune [options]` - Remove worktrees for merged branches
- `grove shell-init ` - Output shell integration function (bash, zsh, or fish)
- `grove self-update [version] [options]` - Update grove to a specific version or PR
- `grove version` - Show version information
- `grove help [command]` - Show help
## Development
### Prerequisites
- [Rust](https://www.rust-lang.org/tools/install) (stable toolchain)
- Git
### Setup
```bash
# Clone the repository
git clone https://github.com/captainsafia/grove.git
cd grove
# Build the project
cargo build
# Build optimized release binary
cargo build --release
```
### Development Commands
```bash
# Build debug binary
cargo build
# Build optimized release binary
cargo build --release
# Run directly in development
cargo run --
# Type check without building
cargo check
# Run all tests
cargo test
# Clean build artifacts
cargo clean
```