Skip to main content

Run a branch or worktree

Point any service at a git branch or an external checkout for a single run - without editing path: in corgi-compose.yml. The flags are per-service and repeatable; any service you don't flag runs from its compose path: as usual. They work on corgi run, corgi exec, and corgi test, and all three repoint the service's working dir - so its env generation, beforeStart/afterStart, and process all run there.

The flags​

FlagWhat it doesDestructive?
--service-branch <svc>=<branch>Runs the service from a reused git worktree under .corgi/corgi_services/.worktrees/<svc>-<branch>No - main checkout untouched
--service-dir <svc>=<path>Runs the service from an existing directory you already haveNo
--service-checkout <svc>=<branch>git checkout <branch> in place in the service's path:Yes - refuses on a dirty tree, leaves the repo on that branch
--feature <branch>Runs every service whose repo has that branch from a worktree for it; the rest stay on their current checkoutNo - main checkouts untouched

A service may appear in only one of the first three at a time. --feature is fleet-wide and yields to any of them for a service they name.

Examples​

# run a feature branch of api; the rest of the stack runs from compose path:
corgi run --service-branch api=feature/login

# mix: api on a branch, web from an explicit dir, others from compose path:
corgi run --detach \
--service-branch api=feature/login \
--service-dir web=/tmp/wt/web

# switch the actual checkout in place (clean tree only)
corgi run --service-checkout api=hotfix/x

# test or run a one-off command on a branch
corgi test --service api --service-branch api=feature/login
corgi exec api --service-branch api=feature/login --ensure-deps -- npm run migrate

One change, several repos: --feature​

A change that spans services usually lands as one branch name in each repo it touches. --feature takes that name once and applies it everywhere it exists:

corgi run --feature ABC-123-checkout-flow --detach --wait

For every service corgi asks its repo whether the branch exists - as a local head or on origin. Services that have it run from a worktree for it; services that don't stay on whatever they are checked out at. Nothing is checked out in place, and a missing branch is never an error - that asymmetry is the point, since a feature rarely touches the whole stack.

A remote-only branch is fetched first, so a fresh (or --depth 1) clone works without any prior git fetch. Per-service flags win: give --service-branch api=other alongside --feature ABC-123 and api uses other while everything else still follows the feature branch.

This is what makes a full-stack CI job possible: check out the repos, pass the PR's branch name once, and every repo that carries the change joins the run.

How --service-branch reuse works​

The worktree path is deterministic per (service, branch). On each run corgi prunes stale entries and then:

  • reuses the worktree if it already exists and is healthy - keeping installed deps (node_modules, etc.) and any uncommitted work in it;
  • creates it (git worktree add) only when missing or broken.

So re-running the same branch is fast and never throws away state. The branch must exist (local or remote). Your service's main checkout is never touched.

Managing worktrees​

Worktrees accumulate one per branch under .corgi/corgi_services/.worktrees/:

corgi worktree list # print every corgi-created worktree
corgi worktree prune # git worktree remove them all (also done by corgi clean)

When to use which​

  • Reviewing a PR branch or trying someone's change → --service-branch (safe, your checkout stays put).
  • Comparing two branches side by side → run each in its own stack on different ports; each is isolated in its own worktree.
  • You already have a checkout/worktree somewhere → --service-dir.
  • You want the repo genuinely switched to the branch → --service-checkout.
  • AI agents → one agent can run an isolated branch while another runs main, with no collisions. See AI agents.