An open API service indexing awesome lists of open source software.

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

Awesome Lists containing this project

README

          

# grove


Grove Logo

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
```