Forest is a simple CLI tool for managing git worktrees and tmux sessions.
It was created to support my development workflow, which involves multiple AI agents working in the same repository on different tasks, isolated with Git worktrees. I would find myself often creating a new tmux session, navigating to the repo I'd like to work on, creating a Git worktree, navigating to the worktree, then setting up my typical layout of a coding agent, an editor, and other miscellaneous windows depending on the project. With the proliferation of worktrees/tmux sessions, it got a little challenging to manage.
Forest does essentially just that, but in an automated, configurable fashion. It optionally adds a friendly TUI on top of that to hopefully make things easier to manage.
Disclaimer: This tool was created entirely with AI, with minimal direct code review from me. I needed a tool that served a certain purpose, but I also don't have the time to treat it as more mature software project. It's functional, but as you can imagine, there's probably tons of slop all around.
go install github.com/mhamza15/forest@latest
First, register a git repository as a project:
forest project add ~/dev/myapp
Next, switch to a worktree and tmux session for a branch:
forest tree switch --project myapp feature/login
This creates a worktree at <worktree_dir>/myapp/feature-login (worktree_dir defaults to ~/.local/share/forest/worktrees) when needed, starts a tmux session named myapp-feature-login, and switches to it. If the worktree already exists, it reuses the existing worktree and just switches to its tmux session.
If the branch does not exist locally but exists on a remote, it is fetched automatically and the local branch is set up to track the remote.
To browse all projects and their worktrees interactively:
forest tree
Forest is a CLI tool for managing git worktrees and tmux sessions.
It simplifies the workflow of creating and managing multiple working
copies of a repository, each in its own directory with a dedicated
tmux session.
Usage:
forest [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
config Open configuration in your editor
help Help about any command
project Manage projects
session Manage tmux sessions
tree Manage and browse worktrees
Flags:
-h, --help help for forest
--verbose enable debug logging
-v, --version version for forest
Use "forest [command] --help" for more information about a command.
Register, list, and manage forest projects.
Usage:
forest project [command]
Available Commands:
add Register a new project
list List registered projects
remove Unregister a project
Create, switch to, remove, and browse worktrees. Run without a subcommand
to open the interactive tree browser.
Usage:
forest tree [flags]
forest tree [command]
Available Commands:
list List worktrees for one or all projects
prune Remove worktrees whose branches have been merged or deleted
remove Remove a worktree and its tmux session
switch Switch to a worktree, creating it if needed
The interactive tree browser (forest tree) supports vim keybindings (j/k, ctrl+n/ctrl+p, arrows), enter/l to open, tab to expand/collapse, d to delete, n to create a new tree, ? to toggle help, and q to quit.
Manage tmux sessions without affecting worktrees.
Usage:
forest session [command]
Available Commands:
kill Kill a tmux session without removing its worktree
list List active tmux sessions
Opens the global config in $EDITOR. If a project name is given,
opens that project's config instead.
Usage:
forest config [project] [flags]
Global config lives at $XDG_CONFIG_HOME/forest/config.yaml, or ~/.config/forest/config.yaml:
# yaml-language-server: $schema=https://raw.githubusercontent.com/mhamza15/forest/main/internal/config/schema/config.schema.json
# Default directory for storing worktrees. Organized as: <worktree_dir>/<project>/<branch>.
# Defaults to $XDG_DATA_HOME/forest/worktrees, or ~/.local/share/forest/worktrees.
worktree_dir: /path/to/worktrees
# Default branch to base new worktrees on.
branch: main
# Default tmux window layout for new sessions across all projects. Each entry creates a separate window.
layout:
- command: opencode
- name: editor
command: nvim
- name: shell
command: ""Per-project configs live at $XDG_CONFIG_HOME/forest/projects/<project>.yaml, or ~/.config/forest/projects/<project>.yaml. and can override any global setting:
# yaml-language-server: $schema=https://raw.githubusercontent.com/mhamza15/forest/main/internal/config/schema/project.schema.json
# The path to the repo.
repo: /path/to/repo
# The directory to store this project's worktrees. Leave empty or omit
# to use the global default.
worktree_dir: /path/to/worktrees
# The default branch to base new worktrees on. Leave empty or omit to
# use the global default.
branch: main
# Files to copy from the repo root into each new worktree.
copy:
- .env
- config/local.yml
# Files to remove from each new worktree. Tracked files are marked
# skip-worktree first, so the deletion stays local to that worktree.
remove:
- .envrc
# Project-specific layout (overrides global layout).
layout:
- command: opencode
- name: editor
command: nvim
- name: shell
command: ""remove is applied when Forest creates a worktree. To restore a removed tracked
file in an existing worktree, clear the skip-worktree bit and then check the
file out again:
git update-index --no-skip-worktree -- path/to/file
git checkout -- path/to/fileforest completion fish > ~/.config/fish/completions/forest.fish
forest completion bash > /etc/bash_completion.d/forest
forest completion zsh > "${fpath[1]}/_forest"
Project names and branch names complete dynamically.
Forest ships as a Fisher-compatible fish plugin with short abbreviations for every command:
| Abbreviation | Expansion |
|---|---|
f |
forest |
ft |
forest tree |
ftl |
forest tree list |
ftrm |
forest tree remove |
ftsw |
forest tree switch |
ftpr |
forest tree prune |
ftp |
forest tree --project |
ftlp |
forest tree list --project |
ftrmp |
forest tree remove --project |
ftsp |
forest tree switch --project |
ftswp |
forest tree switch --project |
ftprp |
forest tree prune --project |
fp |
forest project |
fpa |
forest project add |
fpl |
forest project list |
fpr |
forest project remove |
fs |
forest session |
fsl |
forest session list |
fsk |
forest session kill |
fsp |
forest session --project |
fslp |
forest session list --project |
fskp |
forest session kill --project |
fc |
forest config |
Install with Fisher:
fisher install mhamza15/forest
Or source directly:
source /path/to/forest/conf.d/forest.fish