git-treeline

Run every branch at the same time

Declare what each branch needs in one YAML file: ports, databases, routing, env, lifecycle hooks. GTL provisions it. Three features, a bugfix, and a code review, all at once.

brew install git-treeline/tap/git-treeline
View on GitHub

Worktrees are easy to create. Hard to run.

A git worktree is a separate checkout of your repo in its own directory — git worktree add creates one in seconds. But every checkout shares the same ports, databases, and config.

without git-treeline

~/feature-a $ npm run dev

▸ Ready on http://localhost:3000

~/feature-b $ bin/dev

Error: listen EADDRINUSE : :3000

~/feature-b $ psql -c "CREATE DATABASE myapp_dev"

ERROR: database "myapp_dev" already exists

with git-treeline

~ $ gtl new feature-auth

Creating worktree feature-auth

Allocated port 3010

Cloned database myapp_dev_feature_auth

Wrote .env.local

Running setup commands...

==> https://myapp-feature-auth.prt.dev

named URL via gtl serve (one-time setup)

Your worktrees should be provisioned, not duct‑taped.

Port 3000 stays free. On purpose.

OAuth providers, Stripe webhooks, Mapbox, CORS policies — they’re all registered to localhost:3000. The moment a second branch takes that port, every integration breaks. Treeline never allocates common ports. It reserves them for the proxy.

$ gtl proxy 3000

Proxying :3000:4010 (feature-auth)

# OAuth callback → :4010

# Stripe webhook → :4010

# Mapbox origin → :4010

Configure once, never again

Register localhost:3000/callback in your OAuth dashboard. Register localhost:3000/webhooks in Stripe. Done.

Switch what’s behind it

gtl proxy 3000 routes to whichever worktree you’re in. The external world sees the same origin. You rotate what’s behind it.

Branch URLs for everything else

Your browser uses myapp-feature.prt.dev. Third-party services use port 3000. Both work at the same time.

How this works with OAuth, Stripe, and more →

Four pillars, one config file

Everything is driven by .treeline.yml at the root of your repo. Each feature page goes deeper: config options, terminal walkthroughs, and edge cases.

Two branches. Two apps. Zero conflicts.

Not containers — separate ports, databases, and config for every worktree. Declare what each branch needs in .treeline.yml and a git hook installed by gtl install allocates resources on every checkout.

How isolation works →

Environment isolation

$ gtl new feature-auth

Allocated port 3010

Cloned database myapp_dev_feature_auth

Wrote .env.local

==> https://myapp-feature-auth.prt.dev

named URL via gtl serve

The URL follows the branch, not the port.

Your app still listens on localhost:{port} but the router gives every branch a named HTTPS URL so you don’t need to remember which port is which. Port 3000 stays free for gtl proxy so OAuth, Stripe, and CORS stay configured to a single origin.

Networking in depth →

Networking

Networking
localhost:3010

Ephemeral port

https://myapp-feature-auth.prt.dev

HTTPS URL for this branch

Type a PR number. Get a running app.

gtl review 42 fetches a PR and boots the app in one command. A lightweight process supervisor handles start, stop, and restart — no PID files, no signal guessing.

Review and supervisor →

Workflows

gtl review

$ gtl review 42 --start

Fetched PR #42
Created worktree, allocated port 3020
Cloned database, ran setup
Server running
https://myapp-pr-42.prt.dev

named URL via gtl serve

Agents guess ports and config. They don't have to.

A built-in MCP server — the protocol AI coding agents use to call tools — lets agents query real port allocations, control the dev server, and inspect config. Works with any MCP-compatible editor.

Agent integration →

AI Agents

MCP config
{
  "mcpServers": {
    "gtl": {
      "command": "gtl",
      "args": ["mcp"]
    }
  }
}
No runtime dependency CLI-driven, nothing running in your app.
No lock-in A config file, not a library. Remove it and nothing breaks.
Zero bundle impact Nothing ships to production. Dev tooling only.
Opt-in per developer Works when installed, invisible when it isn’t.

See everything running

Two ways to view your worktrees: a macOS menu bar app for quick access, or a full-screen terminal dashboard for keyboard-driven control.

Solving real problems

Detailed walkthroughs for the scenarios that break multi-branch development.

Guide

First-time setup

Install, configure, and create your first isolated worktree. The full walkthrough.

Networking

Why port 3000 stays free

OAuth, Stripe, and CORS all expect localhost:3000. Here’s why that still works.

Isolation

Database per branch

Clone from a template in seconds, seed from hooks, or copy a SQLite file.

All scenarios →

Every branch, fully provisioned

brew install git-treeline/tap/git-treeline

Also go install or a release binary.