Skip to content

Commands

All commands run from the repository root with Bun. turbo runs the graph-aware, cached tasks across every workspace that defines the script.

Command What
bun run dev every app with a dev script: api :3000, web :5173, site :4321, docs :4322
bun run dev:app api + web only
bun run dev:site · bun run dev:docs one Astro site
bun run dev:desktop Tauri desktop shell around the dev server (needs Rust)
Command What
bun run verify lint, check and test in CI’s order — the pre-push command; add bun run build for the whole pipeline
bun run check turbo check — svelte-check in the app and packages, astro check in the sites
bun run test turbo testbun test in the TS packages and the API, Vitest (unit + component in Chromium) in the app, and packages/ui’s contrast check, which recomputes every token pair’s ratio from theme.css. The component tests need Playwright’s Chromium; apps/web’s pretest installs it on first run
bun run test:e2e Playwright against a production preview of apps/web (includes axe, WCAG 2.2 AA)
bun run lint · bun run lint:fix Biome — check / check and write (TS, JSON, CSS, Svelte, Astro; tabs, single quotes, 100 columns)
bun run format Biome format only
bun run build turbo build — every app
bun run clean remove build outputs
bun run licenses audit every dependency’s licence from the metadata an install already left on disk (--all for one line per package, --strict to exit 1 on anything not already recorded in THIRD-PARTY.md — what CI runs)
bun run rename rename the kit to your product across the tracked text files: --name, --slug, --identifier, --scope. Dry run unless --write; LICENSE.md, THIRD-PARTY.md, CHANGELOG.md, UPGRADING.md and the script itself are left verbatim, and it prints a residue checklist of what a text substitution must not touch (Docker volumes, the dev database, .env, lockfiles, the kit’s own repository URL)
Command What
bun run db:up · bun run db:down Postgres 17 + pgvector (pgvector/pgvector:pg17) in Docker via infra/compose.dev.yml (host port POSTGRES_PORT, default 5433)
bun run db:migrate apply packages/db/drizzle/*.sql, then verify nothing is still pending and exit 1 if something is — a branch merge can interleave migration timestamps, which Drizzle’s migrator would otherwise skip while printing success
bun run db:generate generate a migration from the schema
bun run db:push push the schema without a migration (development only)
bun run db:studio Drizzle Studio
Command What
bun run auth:schema regenerate the Better Auth tables after changing plugins — then db:generate and db:migrate
bun run admin:create -- --email … [--name …] [--yes] create or promote the first platform administrator. The password comes from ADMIN_PASSWORD or an interactive prompt, never from the command line, where it would land in shell history and ps. It runs through the kit’s own auth config — no bunx, no network — so it works inside the API container too. --yes is required to promote an account that already exists
bun run seed demo data: demo@example.com / demo-password-1234 (SEED_PASSWORD overrides), one organization with a team, two workspaces, three documents, six finished jobs with their credit-ledger rows, and an audit trail. Idempotent, and it refuses to run with NODE_ENV=production. No object is written to storage, so a seeded document cannot be downloaded
Command What
bun run api:openapi write apps/api/openapi.json for non-TypeScript client generation
bun run --cwd apps/api worker run the job worker as its own process (then WORKER_ENABLED=false on the API)
Command What
docker compose up -d --build production stack from the repository root (COMPOSE_FILE in .env)
COMPOSE_PROFILES=backup in .env, then docker compose up -d nightly pg_dump (+ uploads); run --rm backup bun src/cli.ts backup|list|restore. Profiles live in .env, not on the command line — deploy.sh --remove-orphans drops containers of profiles it cannot see
sudo REPO_URL=… EXPOSE=tailscale bash infra/scripts/provision.sh one-time VPS setup, as root (EXPOSE=public opens 80/443): Docker, Tailscale, deploy user, firewall, clone, .env — or curl … | sudo … bash as in the runbook
bash infra/scripts/deploy.sh pull IMAGE_TAG, restart, wait healthy, hit /readyz (what CI runs over SSH)
docker run --rm -i -e API_URL=… grafana/k6 run - < infra/loadtest/k6/smoke.js load test the API

See Operations.

These are each app’s own scripts, not root ones: run them from that directory, or from the root with bun run --cwd apps/<app> <script>.

App Commands
apps/web build (node) · build:node · build:cloudflare · build:static · build:static:desktop (into build-static/, what the Tauri shell bundles) · preview · check · test · test:e2e · i18n:compile · deploy:cloudflare
apps/api dev · worker · bun test · openapi
apps/site, apps/docs dev · build · preview · check · deploy:cloudflare (astro build && wrangler deploy)
apps/native dev:desktop · build:desktop · `android:init
packages/ui bunx shadcn-svelte@latest add <name> -c packages/ui
infra/backup bun src/cli.ts backup|list|restore|schedule (image: infra/backup/Dockerfile)
services/ai uv sync · uv run uvicorn ai.main:app --reload --port 8000 · uv run pytest · uv run ruff check .
Variable Effect
ADAPTER=node|cloudflare|static selects the SvelteKit adapter for vite build in apps/web
STATIC_OUT_DIR where ADAPTER=static writes (default build, the same directory the server adapters use). build:static:desktop sets it to build-static so a desktop build and a server build cannot overwrite each other
SKIP_ENV_VALIDATION=1 relax the API’s env validation for steps that never boot the app (type checks, CI builds) — never for dev or migrate. Values are still parsed, so they keep their real types; only the cross-field production rules are skipped, and DATABASE_URL / BETTER_AUTH_SECRET get placeholders
ADMIN_PASSWORD password for admin:create, instead of the interactive prompt
SEED_PASSWORD password for the account bun run seed creates (default demo-password-1234)
SITE_URL canonical origin for the Astro builds — each site has its own. astro build fails without it, and fails on an example.com placeholder; astro dev and astro check fall back to localhost:4321 / :4322