Local development
Run the monorepo on one machine, and isolate git worktrees
Contributor notes for the primary checkout and parallel Worktrunk worktrees. Operators who only want a first search should stay on Getting started. Production layouts are under Deploy.
The same content lives in the repo as DEVELOPMENT.md.
Primary checkout
pnpm installCopy each *.env.example to .env (server/, worker/, search/, packages/db/, and the repo-root Compose file). Set AI_GATEWAY_API_KEY in server/.env, worker/.env, and search/.env.
pnpm dev:allThat builds shared packages (db, queue, search-client), starts Docker infra (docker-compose.dev.yml), and runs the admin UI, indexer API, search API, and worker.
| Process | Default |
|---|---|
| Admin UI (Vite) | http://localhost:5173 |
| indexer-api | http://localhost:3000 |
| search-api | http://localhost:3001 |
| tusd | http://localhost:8080/files/ |
| Postgres | localhost:5432 / demo_search |
| Valkey | localhost:6379 / logical DB 0 |
| RustFS (S3) | http://localhost:9000 |
Docs site (this site; separate process, not :3000):
pnpm --filter docs devOpen http://localhost:4000.
pnpm infra # Docker: db, valkey, rustfs, tusd
pnpm build:packages
pnpm db:push
pnpm db:studio
pnpm worker:devEnv files
Gitignored .env files (copy from the matching *.env.example):
| File | What it is for |
|---|---|
server/.env | AI_GATEWAY_API_KEY, DATABASE_URL, VALKEY_URL, optional PORT / CORS_ORIGIN |
worker/.env | Same key + S3 + queue knobs |
search/.env | Same key + DATABASE_URL, optional PORT / CORS_ORIGIN |
packages/db/.env | DATABASE_URL for db:push / Studio |
.env (repo root) | Local Compose only: tusd port, hook URL, CORS origin |
client/.env | Optional Vite overrides (client/.env.example) |
Tracked client/.env.development and client/.env.production only set VITE_APP_ENV.
TUSD_HOOK_FORWARD_LOCAL is local-worktree only. Do not set it in production or image env.
Root .env TUSD_CORS_ALLOW_ORIGIN can allow any localhost UI port so worktrees can share tusd :8080. Omit it to allow only http://localhost:5173.
Worktrees
Worktrunk (wt) creates a sibling checkout. Project hooks then isolate it. Start any agent in that directory after wt finishes.
| Shared with the primary checkout | Isolated per worktree |
|---|---|
Docker Compose (Postgres, Valkey, RustFS, tusd :8080) | App ports via hash_port (10000–19999) |
| pnpm content-addressable store | Postgres dswt_* (copy of demo_search) |
| Valkey logical DB |
node_modules is not copied. pre-start runs pnpm install --frozen-lockfile --prefer-offline so the worktree only relinks from the store.
Install (once)
sudo pacman -S worktrunk && wt config shell install
# or: cargo install worktrunk && wt config shell installFirst create in this repo asks you to approve hooks (wt config approvals add). Hooks live in .config/wt.toml. Scripts: scripts/worktree/isolate.sh, scripts/worktree/teardown.sh.
Create
wt switch --create feature-nameCreates ~/projects/demo-search-ai.feature-name, copies .env files from the primary checkout, rewrites ports / database / Valkey DB, installs from the pnpm store, copies demo_search → dswt_*, then tethers client / search / server / worker.
wt switch --create -x claude feature-name -- 'the task'
wt switch feature-nameSame branch name → same ports on any machine. Do not bind 5173 / 3000 / 3001 in a worktree.
Look around / remove
wt list # URL column = Vite
wt urls # client / api / search
wt open
cat .worktree-env
wt dev # restart the four processes
pnpm worktree:isolate # rewrite env if setup failed
wt remove # drops dswt_* ; does not stop shared DockerUploads still go through shared tusd on :8080. VITE_TUSD_HOOK_FORWARD + TUSD_HOOK_FORWARD_LOCAL route hooks to this worktree's indexer-api. Restart the primary indexer on :3000 if it was already running so it picks up hook forwarding.