# git-treeline > git-treeline (CLI alias: `gtl`) is a **worktree provisioner** for developers who run multiple git branches simultaneously. It declaratively allocates ports, databases, routing, env files, editor config, and lifecycle hooks for every git worktree — one CLI, one YAML file. Nothing from Treeline runs inside your app's process or bundle. ## Overview git-treeline solves a specific problem: git worktrees are easy to create (`git worktree add` takes seconds) but hard to run because, without per-worktree configuration, checkouts can compete for the same ports and databases. Treeline provisions each worktree with isolated resources so you can run a feature branch, a PR review, a bugfix, and main — all at the same time. Install: ``` brew install git-treeline/tap/git-treeline ``` Or (Go 1.26+): `go install github.com/git-treeline/cli/cmd/git-treeline@latest` Binary releases: https://github.com/git-treeline/cli/releases Current version: v0.58.3 (released 2026-10-10) Runs on macOS and Linux. Homebrew installs `git-treeline` and the `gtl` alias. Go install provides `git-treeline`; use it instead of `gtl` in the examples below. `git treeline` also works. Git and the tools used by your database and setup commands must be installed. Upgrade with `gtl update`, then check `gtl version`. When upgrading from v0.58.0 or earlier, stop each older supervisor with `gtl stop --kill` from its original launch path (including symlink aliases), then run `gtl start`. Ctrl+C in the original terminal also works. Release notes: https://github.com/git-treeline/cli/releases/tag/v0.58.3 ## Before you start - Treeline supports macOS and Linux. Native Windows is not a supported release target. - Containers are not required. Apps can still use Docker when their own setup needs it. - PostgreSQL and SQLite cloning are optional and require a prepared template. Frameworks or setup commands create auxiliary databases. - Router URLs are local, not publicly reachable. Public access requires an explicitly started tunnel or sharing command. - Worktree resource isolation prevents development conflicts; it is not a security sandbox and does not restrict a process or agent's access to the machine. ## Core workflow 1. **Install**: `gtl install` — one-time setup per project. Creates `.treeline.yml`, installs the post-checkout hook, allocates ports, writes env file, optionally enables local HTTPS router. 2. **New worktree**: `gtl new feature-auth --start` — creates a git worktree, allocates a port, clones the database if configured, writes `.env.local`, runs setup commands, and starts the configured server. 3. **Start server**: `gtl start` — runs your app under a managed supervisor. Syncs env on fresh start. 4. **PR review**: `gtl review 42 --start` — fetches PR #42 into a worktree with full setup, starts server. 5. **Switch branch**: `gtl switch feature-payments` — fetches, checks out, refreshes env. 6. **Release**: `gtl release --drop-db --remove-worktree` — frees port, drops database, removes directory. ## Key concepts The installed Git hook provisions unallocated linked worktrees and refreshes editor settings on branch changes in an existing allocation. Setup hooks run when setup runs, including explicit retries. - **Provisioning**: On `gtl new` or `gtl setup`, Treeline allocates ports, clones the PostgreSQL or SQLite database, copies files, writes env, and runs setup commands. All idempotent. - **Env file**: Treeline writes a `.env.local` (or configured path) with interpolated values: `{port}`, `{database}`, `{router_url}`, `{resolve:project}`, etc. - **Registry**: A local file tracking all worktree allocations (project → branch → port + database). `gtl status` shows it; `gtl registry validate/repair` audits it. - **Supervisor**: `gtl start` runs your `commands.start` under a Unix socket supervisor. `gtl stop`, `gtl restart`, `gtl dashboard` all operate through it. - **HTTPS router** (`gtl serve`): Optional local CA + reverse proxy that serves each worktree at a named HTTPS URL like `https://myapp-feature-auth.prt.dev`. One-time `sudo` setup. - **Resolve / link**: `{resolve:project}` in env expands to the base URL of another project's current worktree. `gtl link` overrides which branch of another project you connect to. ## Config file: .treeline.yml Lives at project root, committed to git. Key fields: ```yaml project: myapp # namespace for ports and DB names port_count: 1 # ports per worktree (default 1) env_file: .env.local # where to write allocated env database: adapter: postgresql # or sqlite template: myapp_dev # source DB to clone from name: "{template}_{worktree}" sync_on_create: false # migrate template in detached checkout before cloning sources: # for gtl db pull production: via: fly app: my-fly-app staging: via: env var: STAGING_DATABASE_URL provision: # host-level baseline (gtl provision); declaring it also # opts in mise runtime installs from .ruby-version/.tool-versions apt: [libvips, imagemagick] # Linux packages (needs sudo) services: [redis-server] # apt-install + systemctl enable --now database: template: myapp_dev # optional; defaults to database.template source: production # hydrate template DB from named source hydrate: "bin/rails db:schema:load db:seed" # fallback; non-interactive, runs in repo dir copy_files: - config/master.key # copied from main worktree at setup env: # written to env_file, supports tokens PORT: "{port}" DATABASE_URL: "postgresql://localhost/{database}" APP_URL: "http://localhost:{port}" commands: setup: - bundle install - bin/rails db:migrate start: bin/rails server -p {port} migrate: bundle install && bin/rails db:migrate # fresh detached checkout editor: title: "{project} · {branch} :{port}" color: auto # or hex, e.g. "#3b82f6" hooks: post_setup: - echo "Ready on port {port}" oauth: # named start hook pre_start: gtl serve alias myapp-oauth {port} post_stop: gtl serve alias myapp-oauth --remove auto: false ``` Managed paths (`env_file.path`, `env_file.seed_from`, and `copy_files`) must be relative and stay within their project roots. Absolute paths, parent traversal, and escaping symlinks are rejected. ## Interpolation tokens (used in env map) | Token | Value | |-------|-------| | `{port}` | Primary allocated port | | `{port_2}` … `{port_10}` | Additional ports (when port_count > 1) | | `{database}` | Primary cloned database name (bare alias for `{database.name}`) | | `{database.name}` | Primary cloned database name (dotted path form) | | `{database.extra.}` | Auxiliary database name (e.g. `{database.extra.queue}`) | | `{redis_url}` | Redis URL with namespace | | `{redis_prefix}` | Redis key prefix | | `{project}` | Project name | | `{worktree}` | Worktree directory name | | `{branch}` | Branch name (editor.title only) | | `{router_url}` | HTTPS URL, e.g. `https://myapp-feature.prt.dev` | | `{router_host}` | Router domain only, e.g. `prt.dev` | | `{tunnel_url}` | Public tunnel URL | | `{tunnel_host}` | Tunnel base domain | | `{resolve:project}` | Base URL of another project's worktree | | `{resolve:project/branch}` | Same, pinned to a specific branch | ## CLI reference (summary) ### Setup - `install` — full one-step setup for new developers - `provision` [--dry-run] — bring a host up to the repo's declared baseline (apt packages, systemd services, mise runtimes, template database hydration) before `gtl setup` can succeed; idempotent, Linux-only for apt/services steps - `init` — generate `.treeline.yml` only (auto-detects framework, writes AGENTS.md); must be run inside a git repository - `rename ` — rename the project and update tracked names, env, and editor config; changed worktrees need `gtl setup` to provision new databases, and old databases are not dropped - `new ` [--base] [--start] [--open] [--no-setup] — create worktree + provision + optional start; `--no-setup` skips allocation, env, and setup commands; default base branch respects `worktree_base` config - `claim ` [--path ] [--no-setup] — adopt an existing branch into a new or reused worktree, fast-forward from origin, and provision it; `--no-setup` skips explicit provisioning of newly created worktrees; installed Git hooks can still run setup, and existing worktrees are still provisioned - `review <[#]PR#>` [--start] [--open] [--no-setup] — fetch GitHub PR into worktree (leading `#` accepted; quote it in shells where it starts a comment: `gtl review '#42'`); `--no-setup` skips allocation, env, and setup for a new worktree - `switch ` [--setup] [--restart] — switch branch in current worktree (leading `#` on PR numbers accepted) - `setup [path]` [--dry-run] — full provisioning (idempotent); preserves worktree on setup-command failure, exits with code 2 - `refresh` — re-allocate all worktrees - `reallocate [paths]` [--all-registry] [--apply] — bulk re-run setup - `release [path]` [--drop-db] [--remove-worktree] [--all] [--force] — free resources; release hooks run on every release path; `--force` overrides hook failures - `prune` [--stale] [--merged] [--drop-db] [--remove-worktree] — clean orphans - `clone ` — clone + detect + setup - `nuke` [--force] [--dry-run] — machine-wide recovery: stop all supervised servers, kill stale supervisors, clean orphaned state across all projects; prompts for confirmation - `registry validate` [--json] / `repair` / `forget ` — audit and repair the allocation registry ### Server management - `start` [--with ] [--await] — fresh start or resume supervisor; a fresh `--await` starts a background supervisor and returns when ready. Port cleanup requires explicit yes; empty input or EOF declines - `stop` [--kill] — stop server (supervisor stays alive unless --kill) - `restart` — sync env, push vars, restart server - `port` [--json] — print allocated port - `open` — open in browser - `routes` [--json] — print all routing URLs - `dashboard` / `dash` / `ui` — TUI showing all worktrees and server state ### Networking (HTTPS router) - `serve install` — generate CA, trust, port-forward 443→router, register background service - `serve status` — show router state and routes; router self-heals pf.conf if a macOS update reverts it - `serve restart` [--if-installed] — bounce router (no sudo needed) - `serve reload-pf` — re-apply pf rules after reboot - `serve alias [name] [port]` [--remove] — manage subdomain aliases - `serve logs` — stream or print recent router logs - `serve uninstall` — remove service, port forwarding, CA - `serve hosts sync / clean` — manage /etc/hosts entries - `proxy [target]` [--tls] — forward a local port to another local port with optional TLS; --tls enables HTTP/2 - `tunnel setup / start / status` — Cloudflare named tunnel for public access - `share` — quick public URL via anonymous tunnel (no setup) ### Environment & database - `env sync` — rewrite env file from current config - `env get ` / `env set ` — read/write env vars - `db name` — print current database name - `db reset` [--from ] [--force] [--dry-run] — drop and re-clone database from template; prompts for confirmation - `db restore ` [--force] [--dry-run] — restore from a dump file; prompts for confirmation - `db drop` [--force] [--dry-run] — drop the current allocation database without re-clone; in the main worktree this is the template itself. Destructive database prompts identify the target database, host, port, and user - `db refresh [env]` — drop and re-import from a retained sample without a network download (PostgreSQL only); refuses the main worktree - `db pull ` — pull a production/staging database (via fly, heroku, or env var); refuses the main worktree to protect the template - `db template update` — fetch remote merge_target and run commands.migrate in a temporary detached checkout, targeting the root template; Git 2.29+ and explicit primary database env binding required; existing checkout branches and worktree databases stay unchanged ### Navigation & status - `status` — show all allocations for current project; `--json` includes `related[]` cross-worktree relationships - `list` [--json] — list all worktrees with ports, databases, and server state - `where [branch]` — print path to a worktree - `cd ` — print path to a worktree (for shell `cd $(gtl cd ...)` patterns) - `doctor` [--json] — check config, env, ports, supervisor, framework guidance; `--json` emits structured diagnostics ### Config & editor - `config list / get / set / path / edit` — manage user config - `editor refresh` — re-apply editor config (title, color, theme) to current worktree - `mcp-config` — print MCP server config block for your editor - `version` [--json] — print CLI version; `--json` returns `{"cli": "0.58.3", "router": "0.58.3"}` (router is null when not running) - `update` — update the CLI to the latest release; version-aware (skips if already current); passively notifies after commands when a newer version is available ### Cross-worktree - `resolve [branch]` — print URL of another project's worktree - `link [branch]` — pin another project's branch for resolve in this worktree - `unlink ` — remove link override - `relate ` — create a durable cross-worktree relationship (persists in registry; appears in `status --json` as `related[]`) - `unrelate ` — remove a cross-worktree relationship ### Agent integration - `--json` flag on most commands for structured output - `gtl mcp` — start the MCP server (Model Context Protocol) for AI agent integration - MCP tools: `status`, `list`, `port`, `db_name`, `routes`, `resolve`, `env`, `where`, `doctor`, `config_get`, `new`, `setup`, `link`, `unlink`, `env_sync`, `config_set`, `start`, `stop`, `restart` - MCP resources: `gtl://allocations`, `gtl://config/user` - `gtl init` writes an `AGENTS.md` section with project-specific context for AI agents ## Networking architecture - **Port allocation**: Each worktree gets N consecutive ports (default 1) from a shared registry. Base port default: 3002, increment: 2. Dynamic allocation skips common development ports; explicit reservations can use them. Ports 3000 and 3001 are reserved by default for proxy and router. - **HTTPS router** (`gtl serve`): Reverse proxy + local CA. Serves `https://{project}-{branch}.{domain}` (default domain: `prt.dev`). macOS: uses pf for 443→router forwarding + LaunchDaemon for boot persistence. Linux: systemd user service. - **Route key**: `{project}-{branch}` sanitized. Long names auto-truncated with hash suffix (DNS label limit 63 chars). - **Aliases**: Named subdomains pointing at any port. Static (per config) or dynamic (via `gtl serve alias`). Hot-reloaded within 5 seconds. - **Port proxy** (`gtl proxy`): Forward a local port to another target port, with optional TLS. Listens on 3000 by default. - **Webhooks**: Local HTTPS names and port proxies do not provide public access. Use `stripe listen --forward-to localhost:3000/webhooks` with `gtl proxy 3000` for local Stripe testing, or a public tunnel for remotely delivered webhooks. - **Tunnels**: Named Cloudflare tunnels (`gtl tunnel`) for permanent public access; `gtl share` for anonymous one-shot tunnels. ## Database management - PostgreSQL: databases cloned with `createdb --template`. Pattern default: `{template}_{worktree}`. - SQLite: `.sqlite` file copied from template path. - `database.sources` configures remote pull targets (Fly, Heroku, or local env var holding a postgres:// URL). - `database.sync_on_create: true` fetches the remote merge_target and runs `commands.migrate` in a temporary detached checkout before a fresh clone. Requires Git 2.29+ and an env mapping using `{database}`, `{database.name}`, or `{database_1}`. Those tokens target the root template during migrations. Without a primary binding, automatic sync warns and uses the existing template; manual updates and strict setup fail. - Template updates leave existing checkout branches and worktree databases unchanged. The root template is intentionally migrated. `merge_target` defaults to origin/HEAD when available, otherwise main. Dependencies must be available or prepared by `commands.migrate`; normal setup commands and hooks do not run. Configured copies and the root env seed prepare the checkout. Unbound database URLs in common dotenv files and implicit auxiliary URL targets are rejected; any shadow database must be separate from the template. - `database.extra` declares auxiliary database naming patterns as a map of strings (for example, `queue: "{database.name}_queue"`) or list of strings. Treeline names and tracks these for cleanup; your framework or setup commands must create them. Only the primary database is cloned. Named extras are accessible via `{database.extra.}`. `database.name` replaces the legacy `database.pattern` key (old key still accepted as fallback). - `gtl db template update` migrates the template database itself (for keeping the source up to date). ## User config Per-machine settings at `~/Library/Application Support/git-treeline/` (macOS) or `~/.config/git-treeline/` (Linux). Key settings: - `port.base` (default 3002), `port.increment` (default 2) - `port.reservations`: pin specific projects/branches to fixed ports - `redis.strategy`: `prefixed` (key namespacing) or `database` (separate Redis DBs) - `router.domain` (default `prt.dev`; must be localhost or a valid narrow DNS suffix, not an IP address, wildcard, or public suffix), `router.port` (default 3001), `router.mode` (prompt/enabled/disabled) - `worktree.path`: where `gtl new` creates worktrees, supports `{project}` and `{branch}` tokens - `editor.name`, `editor.themes`, `editor.colors`: per-project or per-branch overrides - `tunnel.name`, `tunnel.domain`: Cloudflare tunnel config - `review.skip_switch_confirm`: skip confirmation when `gtl review` switches current worktree ## Menu bar app Menulet v0.2.0 requires macOS 14+. Click a row to open the editor; Command-click opens its URL; Option-click copies it. It reads the allocation registry and supports opening worktrees, refreshing env, and releasing allocations. Its supervisor controls use the older socket path and are incompatible with CLI v0.58.1 and later; use CLI start/stop/restart commands. ## Docs - [Getting started](https://git-treeline.dev/docs/getting-started/) - [Lifecycle](https://git-treeline.dev/docs/lifecycle/) - [Configuration reference](https://git-treeline.dev/docs/configuration/) - [CLI reference](https://git-treeline.dev/docs/cli/) - [Database](https://git-treeline.dev/docs/database/) - [Networking](https://git-treeline.dev/docs/networking/) - [Hooks](https://git-treeline.dev/docs/hooks/) - [Supervisor](https://git-treeline.dev/docs/supervisor/) - [Editor customization](https://git-treeline.dev/docs/editor/) - [Cross-worktree resolve](https://git-treeline.dev/docs/resolve/) - [AI agent integration](https://git-treeline.dev/docs/agents/) - [Troubleshooting](https://git-treeline.dev/docs/troubleshooting/)