Worktree-scoped dev stack orchestrator. Run as many dev stacks as you have worktrees.
demo.mp4
What it is
A CLI that reads a lich.yaml file describing your stack (docker containers, host processes, env variables, lifecycle) and brings it up with per-worktree isolation. Run lich up in two worktrees, get two independent stacks running whatever code exists in those worktrees.
Who it's for
Developers who want to run parallel development stacks from multiple worktrees. Typically this is to enable workflows using multiple parallel coding agents.
Traditional local dev tooling is done ad hoc. It uses various tools: bash/npm scripts, procfiles, docker compose, etc. These systems generally can't run multiple copies of the same stack on one machine at the same time. Ports collide, container names conflict, memory leaks from zombie processes never cleaned up, agents get derailed running down bugs in tooling instead fixing actual problems. Lich implements a robust and observable system to manage this complexity.
curl -fsSL https://lich.sh/install.sh | bashOr download a release tarball from GitHub Releases and put lich on your PATH.
The fastest way to see lich working is the t3 starter. A T3 Stack (Next.js + tRPC + Prisma + Postgres + Tailwind) preconfigured with a lich.yaml:
git clone https://github.com/RPate97/lich-starter-t3
cd lich-starter-t3
lich upPostgres boots in a Docker container on a dynamically allocated port, DATABASE_URL is wired automatically, Prisma pushes the schema, Next.js starts. Open the URL lich prints and you have a working full-stack app.
Add a worktree and bring up a second stack from the same template:
git worktree add ../lich-starter-t3-feature -b feature
cd ../lich-starter-t3-feature
lich up
lich stacksWORKTREE STATUS UPTIME SERVICES URL
lich-starter-t3 up 00:02:15 2/2 http://web.lich-starter-t3.lich.localhost:3300/
lich-starter-t3-feature up 00:00:08 2/2 http://web.lich-starter-t3-feature.lich.localhost:3300/
Two stacks. Two databases. Two dev servers. No port collisions. Same lich.yaml. Both URLs work independently in your browser.
Tear down both:
lich nukeTo wire lich into an existing repo, install the lich-instrument skill and run it in your coding agent:
npx skills add https://github.com/RPate97/lich/skills/lich-instrument/lich-instrumentThe skill walks an agent through writing a lich.yaml for your stack. You may need to iterate a few times to get the env variable mapping and loading right; if you get stuck, the lich.yaml reference is the place to look. Then it's the same workflow:
lich up # brings the stack up
lich logs # tail logs
lich down # stop itversion: 1
services:
postgres:
image: postgres:16
ports:
- { container_port: 5432, published_env: POSTGRES_HOST_PORT }
environment:
POSTGRES_PASSWORD: dev
owned:
api:
cwd: apps/api
cmd: pnpm dev
port: { published_env: PORT }
env:
DATABASE_URL: "postgres://postgres:dev@localhost:${services.postgres.host_port}/app"Full docs at lich.sh. Entry points:
Lich ships agent skills that let Claude (or other agents) work with lich effectively:
lich: daily-driver on-ramp; understand the CLI surface and use itlich-instrument: guides an agent through writing alich.yamlfor your repo
Add a skill:
npx skills add https://github.com/RPate97/lich/skills/lich
npx skills add https://github.com/RPate97/lich/skills/lich-instrumentSetup:
git clone https://github.com/RPate97/lich
cd lich
bash scripts/install-git-hooks.shBuild:
cd packages/lich && bun install && bun run buildTest:
cd packages/lich && bun test # unit
cd packages/e2e && bun run test # end-to-endThe test suites disable telemetry automatically (set in vitest.config.ts and the e2e helper). For ad-hoc local runs of the lich binary while developing, set LICH_TELEMETRY=0 in your shell so your dev usage doesn't show up in real-user analytics:
echo 'export LICH_TELEMETRY=0' >> ~/.zshrc # or ~/.bashrcLich collects anonymous CLI usage telemetry (command name, exit code, duration, version, platform). No paths, no lich.yaml contents, no env values, no log content. The distinct_id is a machine-stable SHA-256 hash of your home directory + hostname + platform (one-way, no reversal), cached at ~/.lich/installation-id.
Disable:
export LICH_TELEMETRY=0 # per-shell
echo '{"telemetry":false}' > ~/.lich/config.json # per-user, persistentOr in lich.yaml:
runtime:
telemetry: falseFull disclosure of what's collected, where it goes, and how to delete the per-installation ID: lich.sh/telemetry.
If you can, please leave telemetry enabled.
MIT.