Drop-in kit to give any Docker-Compose project the "one-command isolated worktree per branch" workflow. Copy these files in, make 5 small edits, done.
See ../WORKTREES.md for why this exists and how it works
day-to-day. This folder is the what to implement checklist.
Adjust every merck / merck_iip / port number to match your own project.
| File | What it is | Where it goes |
|---|---|---|
new-worktree.sh |
Creates an isolated stack | scripts/new-worktree.sh |
rm-worktree.sh |
Tears one down | scripts/rm-worktree.sh |
makefile-snippet.mk |
worktree + worktree-rm targets and the host-URL rewrite |
paste into your Makefile |
docker-compose-snippet.yml |
The port-publishing pattern | apply to your docker-compose.yml |
claude-md-snippet.md |
The MANDATORY rules block | paste into CLAUDE.md / AGENTS.md |
cp worktree-kit/new-worktree.sh scripts/new-worktree.sh
cp worktree-kit/rm-worktree.sh scripts/rm-worktree.sh
chmod +x scripts/*.shThen edit inside new-worktree.sh:
- Port list (2 places):
for p in 5432 4000 8000 5173and thepg=/api=/lite=/web=lines — use your services' base ports. - The
.envoverrides it appends (POSTGRES_PORT,API_PORT, …) — match the env-var names your compose file reads. - The seed dump:
pg_dump -U merck -d merck_iip→ your DB user + name. - The health wait:
curl .../health→ your API's health endpoint.
In rm-worktree.sh there's nothing project-specific to change.
Every published port becomes ${VAR:-default}, and remove all
container_name: so two stacks don't collide on container names.
Paste the worktree / worktree-rm targets and the host_database_url
define + the migrate/seed targets that use it. Add worktree worktree-rm to
your .PHONY line.
So the team (and Claude) always use make worktree, never raw
git worktree add.
make worktree BRANCH=test/isolation
# → prints API + Vite URLs on offset ports; open them
make worktree-rm BRANCH=test/isolation DELETE_BRANCH=1Isolation = unique Compose project name + per-worktree port offset, both
written into the worktree's own .env. Compose publishes ports via
${VAR:-default} and sets no container_name, so N stacks coexist. Everything
else is convenience around that.