First-time setup: a guided tour
You’ve installed Git Treeline and you’re looking at a project. This page walks through the full setup, section by section — what Treeline generates, what every config field does, and how to decide what your project needs. By the end you’ll have an isolated worktree running your app.
1. Install
# macOS / Linux (Homebrew)
$ brew install git-treeline/tap/git-treeline
# or from source
$ go install github.com/git-treeline/git-treeline@latest
Treeline is a single binary with no runtime dependencies. It works on macOS and Linux. Windows is supported for core features (ports, env, databases); the HTTPS subdomain router (gtl serve) is macOS/Linux only.
2. Run gtl install
$ cd your-project
$ gtl install
Detected Rails project
Wrote .treeline.yml
Created user config at ~/.config/git-treeline/config.yml
Post-checkout hook: .git/hooks/post-checkout
Allocated port 3000
Wrote .env.local
Local HTTPS routing lets you access worktrees at https://myapp-main.prt.dev
HTTPS router setup: Yes, install now
Ready. Run gtl start to start your server.
gtl install handles the full setup in one step:
- Generates config — detects your framework (Next.js, Vite, Rails, Express, Python, Rust, Go) and creates a tailored
.treeline.ymlwith agent context inAGENTS.md - Creates user config if this is your first project on the machine
- Installs the post-checkout hook so future checkouts auto-allocate resources
- Allocates ports and writes env for the current worktree
- Offers HTTPS routing (optional) — trusts a local CA and sets up port forwarding. Skip this if you only need localhost.
Every step is idempotent — safe to re-run any time. If you already have a .treeline.yml, it skips config generation and goes straight to allocation and setup.
For fine-grained control, gtl init generates just the config file without running setup. Use --project myapp to set the project name, --template-db myapp_dev for database template, or --skip-agent-config to skip agent context.
3. Tour the generated config
Here’s a fully loaded .treeline.yml. Your generated file will be simpler — init only includes what it detects. Let’s walk through each section so you know what’s available and when you’d add it.
# --- Identity ---
project: myapp
merge_target: develop
# --- Ports ---
port_count: 2
# --- Environment ---
env_file: .env.local
env:
PORT: "{port}"
ESBUILD_PORT: "{port_2}"
DATABASE_NAME: "{database}"
DATABASE_URL: "postgresql://localhost:5432/{database}"
REDIS_URL: "{redis_url}"
APPLICATION_HOST: "localhost:{port}"
# --- Database ---
database:
adapter: postgresql
template: myapp_development
pattern: "{template}_{worktree}"
# --- Files ---
copy_files:
- config/master.key
# --- Commands ---
commands:
setup:
- bundle install --quiet
- yarn install --silent
start: bin/dev
# --- Lifecycle hooks ---
hooks:
pre_setup:
- psql -lqt | grep myapp_development
post_setup:
- echo "Ready"
# --- Aliases ---
aliases:
mailhog: 8025
sidekiq: 9292
# --- Editor ---
editor:
title: "{project} ({branch}) — {url}"
color: auto
theme: GitHub Dark project
The name used in the registry, in branch URLs (myapp-feature-auth.prt.dev), and as a namespace for port reservations. Defaults to the directory name. Most projects never change this.
merge_target
The branch that gtl prune --merged checks against. Treeline auto-detects this from your git remote — you only need to set it if your repo uses something other than main/master (e.g. develop, staging).
port_count
How many contiguous ports each worktree gets. Default is 1. Set it higher when your app needs multiple ports — Rails with esbuild needs 2 (one for the server, one for the asset builder), a full-stack monolith with a separate WebSocket server might need 3.
Ports are allocated in blocks. If port_count: 2 and the base is 3002, the first worktree gets 3002–3003, the next gets 3012–3013 (based on the increment in your user config).
env_file
Where Treeline writes the env file. Usually .env.local (Next.js, Vite) or .env (Express, Rails). If the source file you want to seed from has a different name, use the extended form:
env_file:
path: .env
seed_from: .env.example env
Key-value pairs written to the env file. Values support interpolation tokens that Treeline resolves at setup time:
| Token | Resolves to |
|---|---|
{port} | First allocated port |
{port_N} | Nth allocated port (e.g. {port_2}) |
{database} | Cloned database name |
{redis_url} | Full Redis URL with namespace |
{redis_prefix} | Redis key prefix (prefixed strategy) |
{project} | Project name |
{worktree} | Worktree directory name |
{router_url} | HTTPS URL for this worktree (e.g. https://myapp-feature.prt.dev) |
{router_domain} | Router domain (e.g. prt.dev) — for cookie domains, config.hosts, etc. |
{resolve:project} | URL of another project’s allocation (same branch) |
{resolve:project/branch} | URL of another project’s allocation on a specific branch |
database
Entirely optional. If your project doesn’t use a local database, or you handle database creation in commands.setup, omit this whole block.
When present, Treeline clones a database per worktree at setup time:
- adapter:
postgresql or sqlite - template: the source database to clone from. For PostgreSQL this is passed to
createdb --template. For SQLite it’s the file path to copy. - pattern: naming pattern for cloned databases.
{template}_{worktree} produces names like myapp_development_feature_auth
The template database is never modified. Use gtl db reset to re-clone, gtl db restore dump.sql to load from a dump, and --drop-db with gtl release to clean up. For a deep dive, see Database per branch.
copy_files
Files copied from the main repo directory into each new worktree. Typically secrets that aren’t in version control — config/master.key, .env.secret, certificates. Treeline copies them during setup so the worktree has everything it needs to boot.
commands.setup
Shell commands that run inside the worktree after the env file is written. Install dependencies, run migrations, seed data — whatever your project needs. They run in order and have access to the env vars Treeline just wrote ($PORT, $DATABASE_URL, etc.).
commands.start
Whatever you’d type to boot the app. bin/dev, npm run dev, foreman start, cargo run. Used by gtl start and the --start flag on gtl new and gtl review. The server runs under a lightweight supervisor that agents and scripts can control via gtl stop / gtl restart.
hooks
Lifecycle hooks for validation and cleanup. Four hook points:
Hook When On failure pre_setup Before commands.setup Aborts setup post_setup After all setup Warns, continues pre_release Before resource release Aborts release post_release After resource release Warns, continues
Use pre_setup to gate on prerequisites (template database must exist, secrets must be present). Use post_release for cleanup like notifying a monitoring service or removing cloud resources.
aliases
Project-level service aliases for the HTTPS router. If your team runs Mailhog on :8025 and Sidekiq web on :9292, define them here and everyone gets https://mailhog.prt.dev and https://sidekiq.prt.dev automatically. For personal tools, use gtl serve alias instead. See Named URLs for local services.
editor
Optional visual cues so you can tell worktree windows apart at a glance:
- title: window/tab title template. Supports
{project}, {branch}, {port}, {url}, {router_url} tokens. Works with VS Code and Cursor. - color: title/status bar color. Set
"auto" for a deterministic color derived from the branch name, or a hex value like "#1a5276". - theme: full IDE theme override per worktree (e.g.
"Monokai", "GitHub Dark").
4. Your machine config
.treeline.yml describes the project. Your user config (config.json) describes your machine — how ports are allocated, where worktrees go, which editor you use. It lives at:
- macOS:
~/Library/Application Support/git-treeline/config.json - Linux:
~/.config/git-treeline/config.json - Windows:
%APPDATA%/git-treeline/config.json
gtl install creates this automatically if it doesn’t exist. You can also run gtl config to see or modify it. Here are the key sections:
Port allocation
config.json (partial) {
"port": {
"base": 3002,
"increment": 2,
"reservations": {
"myapp": 3010,
"myapp/staging": 3020
}
}
} base is where dynamic allocation starts (3002 by default — ports 3000 and 3001 are reserved for gtl proxy and the HTTPS router). increment controls the gap between allocations. reservations pin specific projects or branches to stable ports — useful for long-lived worktrees that other services depend on.
# Pin your main repo to port 3010
$ gtl config set port.reservations.myapp 3010
# Pin the staging worktree to 3020
$ gtl config set port.reservations.myapp/staging 3020
Worktree path
By default, gtl new creates worktrees as siblings of the repo (../myapp-feature-x). If you prefer worktrees inside the repo:
config.json (partial) {
"worktree": {
"path": ".worktrees/{branch}"
}
}
Supports {project} and {branch} interpolation. If the path is inside the repo, Treeline ensures it’s in .gitignore automatically.
Redis
If your project uses Redis, Treeline can namespace each worktree to prevent key collisions. Prefixed (default) namespaces keys under myapp:feature-x:... in a shared DB 0. Database gives each worktree its own Redis DB number (1–15). Set redis.strategy in your user config. Most teams never change this.
5. Create your first worktree
$ gtl new feature-auth --start
Creating worktree feature-auth
Allocated ports 3002, 3003
Cloned database myapp_development_feature_auth
Copied config/master.key
Wrote .env.local
Running setup: bundle install --quiet
Running setup: yarn install --silent
==> https://myapp-feature-auth.prt.dev
Starting: bin/dev (port 3002)
One command: worktree created, ports allocated, database cloned, env file written, files copied, setup commands run, server booted. The --start flag kicks off the server under the supervisor immediately.
If you already have a worktree (e.g. from git worktree add), use gtl setup <path> to allocate resources for it. Going forward, the post-checkout hook installed by gtl install handles this automatically for new checkouts.
6. Verify everything works
$ gtl doctor
Config:
✓ .treeline.yml found
✓ User config loaded
✓ post-checkout hook installed
Allocation:
✓ Ports 3002-3003 allocated
✓ Database myapp_development_feature_auth exists
✓ Redis namespace assigned
Runtime:
✓ Server listening on :3002
✓ .env.local matches allocation
gtl doctor checks config, allocation, and runtime. If something is wrong — missing template database, port conflict, stale env file — it tells you exactly what to fix. Add --json for structured output.
7. What to commit
File Commit? Why .treeline.yml Yes Project config — shared with the team AGENTS.md Yes Agent context — tells AI agents how to use ports config.json No Per-machine settings — lives outside the repo registry.json No Allocation ledger — lives outside the repo
Once you commit .treeline.yml and AGENTS.md, every teammate who installs gtl can run gtl new <branch> --start and get a fully isolated environment. See New developer, one command for that walkthrough.
What’s next
You have a working config and your first worktree. From here, the depth you go depends on your project:
- New developer, one command — what your teammates see when they join
- Database per branch — clone, seed, or SQLite strategies
- Why port 3000 stays free — the proxy facade for OAuth, Stripe, and CORS
- Named URLs for local services — aliases for sidecars and tools
- Full documentation — complete CLI reference and config options