Core Concepts
Understanding these four concepts is enough to use Grove effectively.
Glossary
If any of these terms blur together, come back here.
| Term | Meaning |
|---|---|
| Repository | Your Git project — the .git folder and everything it tracks |
| Branch | A named line of development within a repository |
| Worktree | A separate folder on disk where a branch is checked out |
| Grove | This tool — manages worktrees, environments, and agent visibility |
| Provider | How Grove starts your dev environment (Docker, Node scripts, etc.) |
| Workspace | The actual checked-out folder for a worktree |
| Manifest | A 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:
| Provider | Detected when |
|---|---|
docker-compose | docker-compose.yml or compose.yaml exists + .env.worktree found |
node-scripts | package.json has a dev or start script |
custom-shell | Configured explicitly in .grove/config.json |
unknown | No 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:
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-sharedGrove 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:
{
"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:
| Level | What you get | Setup required |
|---|---|---|
| 0 | TUI visibility into all worktrees, git status, change footprint | None |
| 1 | Docker stack management with unique ports per worktree | .env.worktree file |
| 2 | Full env lifecycle, naming templates, shared infra, env contracts | .grove/config.json |
| 3 | Agent 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:
grove pruneOr 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
--yesis 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.