This guide covers how to set up and run the Rift development environment locally.
For the impatient, here is the minimal setup to get the dev server running:
# 1. Install dependencies
bun install
# 2. Start PostgreSQL
docker compose -f docker-compose.postgres.yml up -d
# 3. Set up database schema
bun run web:db:reset
# 4. Copy environment template
cp apps/start/.env.example apps/start/.env.local
# Edit .env.local and add at minimum: BETTER_AUTH_SECRET
# 5. Start the dev server
bun run devThe app will be available at https://rift.localhost.
On first run, portless will set up a local CA and bind port 443. This requires a one-time sudo prompt. If you'd rather do it ahead of time, run bunx portless trust from apps/start/ before bun run dev. On Arch (and any system where sudo resets HOME), start the proxy yourself once with sudo HOME=$HOME ./node_modules/.bin/portless proxy start so the proxy and the unprivileged client share ~/.portless/; otherwise the dev script may report Proxy is already running on port 443 with a different config because the elevated proxy's state lives in /root/.portless while the client reads ~/.portless.
bun installThis installs all workspace dependencies across the monorepo.
Rift uses PostgreSQL for persistence. The easiest way is via Docker:
docker compose -f docker-compose.postgres.yml up -dThis starts PostgreSQL on port 5432 with:
- Database:
rift - Username:
rift - Password:
rift
Next, initialize the database schema:
bun run db:resetCreate your local environment file:
cp apps/start/.env.example apps/start/.env.localEdit apps/start/.env.local and configure the required envs.
Rift uses a Cloudflare Worker to convert uploaded files (PDFs, Office docs, etc.) to markdown. This is required for file attachments.
bun setup:markdown-workerThis interactive script will:
- Check prerequisites
- Authenticate with Cloudflare
- Deploy the worker
- Generate API credentials
Add the output to your apps/start/.env.local:
CF_MARKDOWN_WORKER_URL=https://your-worker.your-subdomain.workers.dev
CF_MARKDOWN_WORKER_TOKEN=your-generated-tokenAfter installation, Zero's native SQLite binary needs to be downloaded:
cd node_modules/@rocicorp/zero-sqlite3
npm run installWithout this, the Zero cache will crash with "Could not locate the bindings file."
From the repository root:
bun run devThis starts:
- The TanStack Start dev server, exposed via portless at
https://rift.localhost(Vite itself listens on a random port in 4000–4999 picked by portless) - Zero cache, exposed via portless at
https://zero.rift.localhost(also on a random portless-assigned port; the script forwards portless'sPORTtoZERO_PORT) - Turbo task runner with TUI
Access the app at: https://rift.localhost
From repository root:
bun run dev # Start dev server with Zero cache
bun run build # Build for production
bun run lint # Run linter across all packages
bun run check # Run type checks
bun run db:reset # Reset database and run migrationsFrom apps/start/:
# Database
bun run db:reset # Reset database and run migrations
bun run zero:migrate # Run Zero migrations
bun run zero:reset # Reset Zero sync state
# Development
bun run dev # Start dev server only
bun run zero-cache # Start Zero cache only
# Testing
bun run test # Run Vitest tests
bun run lint # Run ESLint
bun run lint:fix # Run ESLint with auto-fix
# Utilities
bun run seed:dummy-chats # Seed with test dataThe SQLite native binary needs to be installed:
cd node_modules/@rocicorp/zero-sqlite3
npm run install- Port 443: Used by the portless HTTPS proxy (fronts the dev server at
https://rift.localhostand Zero cache athttps://zero.rift.localhost) - Port 5432: Used by PostgreSQL
- Ports 4000–4999: portless picks two at random for the underlying Vite dev server and Zero cache
If these are taken, you can modify ports in the respective config files. To bypass portless temporarily, run bun --bun vite dev --port 3000 directly inside apps/start/ and zero-cache-dev (which defaults to port 4848) in a second terminal — set VITE_ZERO_CACHE_URL=http://localhost:4848 in .env.local while doing so.
On first run, portless generates a local CA and asks for sudo to install it and bind port 443. If your browser still shows a TLS warning for https://rift.localhost, run bunx portless trust from apps/start/ to re-trust the CA. After running portless trust you also need sudo update-ca-trust on Arch (the user-mode trust command can stage the CA into /etc/ca-certificates/trust-source/anchors/ but cannot rebuild the system bundle without root). Firefox-family browsers don't use the system bundle by default — set security.enterprise_roots.enabled to true in about:config or import ~/.portless/ca.pem manually.
Ensure PostgreSQL is running:
docker compose -f docker-compose.postgres.yml psIf needed, restart it:
docker compose -f docker-compose.postgres.yml restartSee README.md for more project details.