Skip to content
| Marketplace
Sign in
Visual Studio Code>SCM Providers>Forest — Git WorktreesNew to Visual Studio Code? Get it now.
Forest — Git Worktrees

Forest — Git Worktrees

Vlad.studio

|
5 installs
| (0) | Free
Manage parallel feature development with git worktrees
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Forest

Forest

VSCode extension for parallel feature development using git worktrees. One Linear ticket = one branch = one worktree = one VSCode window.

Install from VS Code Marketplace

Concepts

Term Action
New Tree Unified wizard: pick new or existing branch, optionally link a Linear ticket
Ship Push branch + create PR (with optional automerge) + move ticket to configured status
Cleanup Merge PR + delete worktree + move ticket to configured status
Delete Tree Remove worktree, keep branches
Delete Tree + Local Remove worktree + local branch, keep remote
Delete Tree + Branches Remove worktree + all branches + move ticket to canceled
Update Merge from main + re-copy env files
List Quick-pick list of all active trees

Prerequisites

  • git (required)
  • gh CLI (for PR creation and merge)

Setup

Add .forest/config.json to your repo root (tip: ask Claude to generate one for your project):

{
  "version": 1,
  "copy": [".env", ".env.local"],
  "shortcuts": [
    { "name": "install", "command": "bun install --frozen-lockfile", "onNewTree": true },
    { "name": "dev", "command": "bunx turbo dev" },
    { "name": "claude", "command": "claude" },
    { "name": "shell" },
    { "name": "App", "url": "http://localhost:3000" }
  ],
  "linear": {
    "teams": ["ENG"],
    "statuses": {
      "issueList": ["triage", "backlog", "unstarted", "started"],
      "onNew": "started",
      "onShip": "in review",
      "onCleanup": "completed"
    }
  }
}

Per-developer overrides go in .forest/local.json (should be gitignored):

{
  "linear": {
    "apiKey": "lin_api_YOUR_KEY"
  },
  "ai": {
    "provider": "gemini",
    "model": "gemini-2.5-flash",
    "apiKey": "YOUR_KEY"
  },
  "browser": ["external", "Firefox"],
  "terminal": ["iTerm", "integrated"]
}

Generating Config with AI

To set up Forest, ask Claude (or any AI) to read this README and generate .forest/config.json. The AI should inspect the repo and ask you:

  1. Files to copy into trees? → check which of .env, .env.local, .envrc exist
  2. Shortcuts? → what terminals to open (dev server, claude, shell), any browser URLs, any one-time setup commands (e.g. bun install with onNewTree: true)
  3. Linear integration? → yes/no, and team key(s) (e.g. ["ENG", "UX"]). Get your API key from https://linear.app/settings/account/security

Config reference

Field Required Default Description
version yes — Always 1
copy no [] Files to copy from repo root into each tree
shortcuts no [] Terminals, browsers, files to open per tree
linear no disabled Linear integration. Auto-enabled when teams or apiKey is set. teams is an array of team keys (e.g. ["ENG"] or ["ENG", "UX"]). statuses controls issue list and lifecycle transitions including onCancel (must use lowercase state names: triage, backlog, unstarted, started, completed, canceled)
github no true GitHub integration toggle. Set false to disable
branchFormat no ${ticketId}-${slug} Branch naming. Supports ${ticketId}, ${slug}
baseBranch no main Base branch name (origin/ prefix is added automatically)
maxTrees no 10 Max concurrent worktrees
ai no disabled AI-generated PR descriptions. Set provider (anthropic, openai, gemini), model, and apiKey. Best placed in local.json
logging no true File-based logging to ~/.forest/forest.log. Rotates at 5 MB
browser no ["simple"] Browser app list. First item is the default; right-click a shortcut to pick another. Values: simple (VS Code Simple Browser), external (system default), or an app name (e.g. "Firefox")
terminal no ["integrated"] Terminal app list. First item is the default; right-click to pick another. Values: integrated (VS Code terminal), or an external app (iTerm, Terminal, Ghostty). External terminals receive the shortcut command automatically

Shortcut types are inferred from fields: url → browser, path → file, otherwise → terminal (explicit type still accepted). Shortcuts support onNewTree: true to auto-open when a tree is first created (e.g. for dependency installation). Terminals also accept command and env. Browser shortcuts accept a per-shortcut browser override (same values as the top-level browser setting). Both browser and terminal accept a single string for backward compatibility.

Variable expansion in shortcuts: ${ticketId}, ${branch}, ${slug}, ${repo}, ${treePath}, ${prNumber}, ${prUrl}.

local.json (gitignored) merges over config.json — use for per-dev AI keys and overrides.

Features

Tree Grouping

  • Todo — Linear issues without a branch yet
  • Cleaning up — cleanup in progress (loading spinner)
  • In Progress — no PR created yet
  • In Review — PR is open
  • Done — PR has been merged

Tree Health Indicators

ENG-1234  Fix login bug   3↓ · 2h
ENG-5678  Add dark mode   PR approved · 1d
  • N↓ — commits behind base branch
  • Age — time since last commit
  • PR status — open, approved, changes requested

Auto-Cleanup on Merged PRs

When a PR is merged, you get a notification: "ENG-1234 PR was merged. Clean up?" → click Cleanup to remove the worktree automatically.

Update (Rebase + Refresh)

Update fetches and merges (or rebases) your tree on the base branch and re-copies config files. If the merge/rebase fails, it shows an error.

Shortcut Variable Expansion

Shortcuts support these variables in commands, URLs, and file paths:

Variable Description Example value
${ticketId} Linear ticket ID ENG-123
${branch} Full branch name ENG-123-fix-login
${slug} Branch name without ticket prefix fix-login
${repo} Repository name my-app
${treePath} Absolute path to the worktree /Users/you/.forest/trees/my-app/ENG-123
${prNumber} PR number (after ship) 42
${prUrl} PR URL (after ship) https://github.com/org/repo/pull/42
{ "name": "Linear", "url": "https://linear.app/team/issue/${ticketId}" },
{ "name": "PR", "url": "${prUrl}" },
{ "name": "logs", "command": "tail -f ${treePath}/logs/dev.log" }

Direnv Support

If a .envrc file exists in the tree, Forest automatically runs direnv allow during tree creation.

Claude Code Trust

Claude Code asks for trust confirmation when opening a new workspace. Since each tree creates a new directory, you'd get this prompt for every tree. To avoid it, add ~/.forest/trees to Claude's trusted directories:

In ~/.claude/settings.json:

{
  "trustedDirectories": ["/Users/you/.forest/trees"]
}

Replace /Users/you with your actual home directory.

Configurable Linear Statuses

Customize which Linear states to show in the issues sidebar and which states to set on new/ship/cleanup.

Status names in issueList use Linear's built-in types: triage, backlog, unstarted, started, completed, canceled. Status names in onShip, onNew, etc. can be custom workflow state names (e.g. "in review") — Forest resolves them via the Linear API. Use team keys (e.g. ENG), not display names. Multiple teams are supported.

"linear": {
  "teams": ["ENG"],
  "statuses": {
    "issueList": ["backlog", "unstarted"],
    "onNew": "started",
    "onShip": "in review",
    "onCleanup": "completed",
    "onCancel": "canceled"
  }
}

Usage

All commands are available from the Forest sidebar (tree icon in activity bar) or the command palette (Cmd+Shift+P → "Forest: ...").

Typical workflow:

  1. New Tree from a Linear ticket (or New Linear Issue + Tree to create a new ticket)
  2. A new VSCode window opens with terminals running
  3. Code, test, iterate — each tree is fully isolated
  4. Ship when ready — pushes and creates a PR
  5. Cleanup after merge — removes worktree, branch, and ticket
  6. Delete to remove a tree (keep branches, delete local only, or delete all)

Switch between trees from the sidebar. All processes keep running in background windows.

Commands

Command Description
Forest: New Tree Create tree (unified wizard)
Forest: Switch Tree Open another tree's window
Forest: Ship Push + create PR
Forest: Ship + Automerge Push + create PR + enable automerge
Forest: Cleanup Merge PR + remove tree
Forest: Delete Tree Remove tree, keep branches
Forest: Delete Tree + Local Remove tree + local branch
Forest: Delete Tree + Branches Remove tree + all branches
Forest: Update Merge from main + re-copy config files
Forest: Rebase Rebase onto main
Forest: List List all trees
Forest: Open Main Open main repo window
Forest: Open PR Open PR in browser
Forest: Reveal in Finder Open worktree directory in Finder
Forest: Copy Branch Name Copy current tree's branch to clipboard
Forest: Copy Setup Prompt Copy AI setup prompt to clipboard

Recommended VS Code Settings

"window.nativeTabs": true,
"window.titleBarStyle": "native",
"window.customTitleBarVisibility": "never",
"window.title": "${rootName}",                // readable tab labels per worktree
"window.restoreWindows": "preserve",          // survives restarts
"window.closeWhenEmpty": true,
"git.openRepositoryInParentFolders": "always" // git works in worktree subdirs

To open terminals as editor tabs (instead of the bottom panel), add this keybinding (Cmd+T):

{
  "key": "cmd+t",
  "command": "workbench.action.createTerminalEditor"
}

Install locally

git clone <repo> && cd forest
bun install
bun run package
npx @vscode/vsce package
code --install-extension forest-0.1.0.vsix

Development

bun install
# Press F5 in VSCode to launch Extension Development Host
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft