Docs / Resolve

Cross-worktree resolve

When multiple Treeline-managed repos run on one machine, each worktree gets its own ports. Resolve turns a stable name (another project on the same branch) into the correct base URL at env write time, so frontends and APIs stay wired without hand-editing ports.

The problem

Typical layout: a frontend repo and an API repo, both managed by Treeline. The browser loads the UI from one worktree and the UI calls an HTTP API in another. Each worktree receives a different port allocation, so a hardcoded localhost:3xxx in config breaks as soon as you create another branch or re-run setup.

You need a value that tracks the API worktree for the same branch name (or an explicit override), not a single static port.

How resolve works

In your env template you write placeholders such as {resolve:project} (the project key is the Treeline project name, for example {resolve:api} or {resolve:api/main} when you need a nested key).

When Treeline writes the env file, it looks up the target project in the registry, finds the allocation for the same branch name as the current worktree (unless you pinned a branch with gtl link), and substitutes a base URL.

Default output shape is http://127.0.0.1:{port} (loopback, not the hostname localhost). If the HTTPS router is running, Treeline may substitute an HTTPS router URL instead so callers can use stable hostnames.

Resolution happens at env write time (setup, switch, link, start-time sync), not on every HTTP request from your app.

gtl resolve CLI

gtl resolve <project> [branch] prints the resolved base URL for a target project. Omit the branch to use the current worktree branch as the match key.

Pass --json for machine-readable output in scripts.

Shell
gtl resolve api
gtl resolve api feature/payments
gtl resolve api --json

gtl link / gtl unlink

Linking overrides which branch a resolve token targets. Example: gtl link api staging pins {resolve:api} to the staging branch allocation, even when your current worktree is on another branch.

Overrides persist across restarts. After a link change, Treeline regenerates env and restarts the supervised server so the running process sees new values.

Run gtl link with no arguments to list current links. gtl unlink api removes the override for that project.

Shell
gtl link api staging
gtl link
gtl unlink api

Link prerequisites

The target worktree must already exist in the registry: gtl setup (or equivalent) must have run in that project for the branch you reference. gtl link validates this before persisting an override.

Env template example

In .treeline.yml, under env:, you might declare:

.treeline.yml (excerpt)
env:
  API_URL: "{resolve:api}"

Before resolution, the generated env file on disk could still contain the literal token (or Treeline may show the template in diagnostics). After resolution for a worktree where the api project has branch feature/payments at port 3044, the value becomes something like:

.env.local (conceptual)
API_URL=http://127.0.0.1:3044

Edge cases

  • Missing resolve target: env generation fails with an error if the registry has no matching allocation for the required project and branch.
  • Circular resolves: if two projects resolve to each other through the router in a loop, the router can respond with 508 Loop Detected.
  • Partial link failure: the registry may update while env write emits a warning. Treat warnings as a signal to run gtl doctor or re-run sync.
  • --restart on link: deprecated. Since v0.33.0, link operations restart the supervised server automatically when needed.

Multi-repo patterns

For a full walkthrough (frontend repo + API repo, link overrides, and day-to-day workflow), see use case: multi-repo.

See also

Back to docs