Skip to content

Core Concepts

Understanding these four concepts is enough to use Grove effectively.

Glossary

If any of these terms blur together, come back here.

TermMeaning
RepositoryYour Git project — the .git folder and everything it tracks
BranchA named line of development within a repository
WorktreeA separate folder on disk where a branch is checked out
GroveThis tool — manages worktrees, environments, and agent visibility
ProviderHow Grove starts your dev environment (Docker, Node scripts, etc.)
WorkspaceThe actual checked-out folder for a worktree
ManifestA JSON file an AI agent writes to report its status back to Grove

Worktrees

A git worktree is a separate directory where a git repository is checked out at a specific branch. Unlike git checkout, worktrees let you have multiple branches checked out simultaneously — each in its own directory, each independently editable.

~/repos/my-app/                  ← main worktree (main branch)
~/repos/my-app-worktrees/
  feat-auth-refresh/             ← worktree (feat/auth-refresh branch)
  fix-helm-chart/                ← worktree (fix/helm-chart branch)

Grove reads git worktree list and displays all of them in the TUI. No Grove setup required for this level of functionality.

Why worktrees instead of stashing/switching branches?

  • You never lose running processes or environment state
  • Each directory has its own node_modules, build output, and Docker stack
  • You can run two environments simultaneously without port conflicts (when Grove manages ports)

Providers

A provider is how Grove starts and stops a worktree's development environment. Grove detects the right one automatically:

ProviderDetected when
docker-composedocker-compose.yml or compose.yaml exists + .env.worktree found
node-scriptspackage.json has a dev or start script
custom-shellConfigured explicitly in .grove/config.json
unknownNo recognized project type — Grove takes no destructive action

You can also configure providers explicitly in .grove/config.json to skip auto-detection. The custom-shell provider is always explicit — it never auto-detects — and lets you run any shell script as the startup sequence (see Custom startup scripts).

.env.worktree

Each worktree gets its own .env.worktree file — gitignored, machine-local, generated by Grove:

bash
COMPOSE_PROJECT_NAME=my-app-feat-auth-refresh
WEB_PORT=8081
API_PORT=8082
DB_PORT=5433
DB_SCHEMA=my_app_feat_auth_refresh
SHARED_PROJECT_NAME=my-app-shared

Grove generates this from naming templates in .grove/config.json using port allocation to ensure no two worktrees share ports. When you run grove start, Grove creates this file if it doesn't exist. You can regenerate it with grove start <branch> --refresh-env.

Agent Manifest

The agent manifest is a .worktree-manifest.json file that any process (an AI agent, a shell script) can write to a worktree root to communicate status back to Grove:

json
{
  "agentName": "claude",
  "agentStatus": "running",
  "agentActivity": "writing tests for AuthService",
  "startedAt": "2025-04-10T14:23:00Z",
  "testResults": {
    "passed": 42,
    "failed": 0,
    "skipped": 3,
    "lastRun": "2025-04-10T14:30:00Z"
  }
}

Grove reads this on sync (s in TUI or grove sync) and displays it in the detail panel. agentStatus values: idle, running, waiting, done, errored.

This file is gitignored — it's per-worktree, per-session state.

Levels of integration

Grove is a progressive enhancement — you adopt as much as you need:

LevelWhat you getSetup required
0TUI visibility into all worktrees, git status, change footprintNone
1Docker stack management with unique ports per worktree.env.worktree file
2Full env lifecycle, naming templates, shared infra, env contracts.grove/config.json
3Agent status display in TUI, machine-readable grove status --json.worktree-manifest.json

Each level builds on the previous. Remove Grove and your project works exactly the same — there are no custom abstractions that need to stay in place.

Common mistakes

Deleting a worktree folder manually with rm -rf

This leaves stale metadata in .git/worktrees/. Fix it:

bash
grove prune

Or use grove delete <branch> instead — it handles cleanup automatically.

Running commands in the wrong worktree

Each worktree is just a directory. Double-check your terminal's working directory before running migrations, tests, or destructive operations. grove status shows which branch each path maps to.

Assuming worktrees share uncommitted changes

They don't. Uncommitted changes live in the working directory of the worktree where you made them. Only committed changes are visible across worktrees.

Expecting node_modules to be shared

Each worktree has its own node_modules. If branches have different dependencies, you'll need to npm install in each worktree separately. This is intentional — it prevents dependency conflicts between branches.

Modifying the same file in two worktrees simultaneously

You can't check out the same branch in two worktrees. But if two worktrees are on different branches and both modify the same file, you'll get a conflict when you eventually merge — same as any branch workflow.

When Grove is overkill

Grove is most useful when you're juggling multiple branches, PRs, or AI agents. You probably don't need it when:

  • You're making a small, self-contained change that doesn't require context-switching
  • You're new to Git and still building your mental model of branches and commits
  • Your project is tiny and you only ever work on one thing at a time

When the stash-and-switch pain becomes real, Grove will be here.

Safety guarantees

A few things Grove will never do:

  • Modify your main worktree without being told to
  • Delete a worktree without confirmation (unless --yes is passed)
  • Commit or push anything on your behalf
  • Share data between worktrees that shouldn't be shared

Worktrees are a built-in Git primitive. Grove is a wrapper. If Grove had a bug and you deleted it, your worktrees would still exist and be accessible via standard git worktree commands.

Released under the MIT License.