Supabase
Schema, migrations, and verify scripts in packages/supabase/. There is no local DB — the project is linked straight to the remote (prod) via packages/supabase/.temp/project-ref, so every push and write hits production. Migrations are dated SQL files at packages/supabase/migrations/YYYYMMDDHHMMSS_slug.sql.
Apply migrations with bun run push-migrations from the repo root — it filters to @arbe/supabase (so the cwd is right; running supabase db push from the repo root hits the separate edge-functions supabase/ dir and fails the migration-history check) and regenerates database.types.ts afterward. Don’t reach for the raw bunx supabase db push unless you need a flag the wrapper lacks.
bun run push-migrations # apply new migrations to prod + regen types (run from repo root)
cd packages/supabase # for the lower-level commands belowbunx supabase db push --linked --dry-run # preview onlybunx supabase migration list --linked # diff local vs remote historybun run --filter '@arbe/supabase' update-types # regenerate database.types.ts on its own
cd packages/ # workdir auto-resolves here, NOT packages/supabase/bunx supabase db query --linked "select tablename from pg_tables where schemaname='public'" -o table # ad-hoc readbunx supabase db query --linked -f supabase/tests/verify-orphan-house-cleanup.sqlbunx supabase db query --linked -f supabase/tests/verify-cascade-delete-atomicity.sqlExtensions: pg_cron is enabled. Workflow schedules own the wf:<id> jobs — a trigger syncs them from workflows.schedule, so manage them through the column, never cron.schedule directly (see workflows). Inspect with select * from cron.job, firing history in cron.job_run_details.
Verify scripts (packages/supabase/tests/*.sql) are begin; do $$ ... $$; rollback; blocks — DB untouched, asserts raise on first failure. Empty rows + no 400 = passed (the Management API swallows raise notice). A failure surfaces as unexpected status 400: ... ERROR: P0004: FAIL: <message>. psql "$POOLER_URL" -f … also works since scripts are pure SQL.
Gotchas worth remembering:
supabase db queryis not psql — it routes through the Management API, which rejects\set,\echo, or any\-prefixed line withsyntax error at or near "\". Keep verify scripts portable: no meta-commands; any end-of-run banner goes asraise noticeinside a DO block (and accept that the API swallows it).-fis mandatory for files. A bare positional likebunx supabase db query --linked ./tests/foo.sqlis interpreted as inline SQL and fails withsyntax error at or near ".".- Workdir auto-detection lands on
packages/, notpackages/supabase/. Paths passed to-fare resolved relative to that workdir, so from anywhere inside the supabase package you still writesupabase/tests/foo.sql. - Rewriting a function needs a new migration. To change
cleanup_orphaned_housesor anycreate or replace function, add a new dated migration that re-issues the statement — don’t edit historical migration files (e.g.20260417000000_retire_stranded_bots.sqllayered on top of earlier RLS work). - Connection pooler vs direct.
supabase db pushuses the pooler URL (port 5432,pooler.supabase.com). Directdb.<project>.supabase.co:5432works too but isn’t what the CLI advertises. - Never edit
database.types.tsby hand — it’s a generated artifact. Manual edits drift from the remote schema and silently break adapters that trust the type. Cannot find project ref?--linkedreads the ref only frompackages/supabase/.temp/project-ref(gitignored, not committed) — not fromconfig.tomlproject_idnor$SUPABASE_PROJECT_REF. On a fresh clone, relink once from inside the package:cd packages/supabase && bunx supabase link --project-ref gxlrglyxsrldjjrpkdsy. And run query/migration commands from insidepackages/— the repo-rootsupabase/is a separate dir (edge functions) whose--linkedlookup fails the same way.
Code: packages/supabase/migrations/, packages/supabase/tests/, packages/supabase/database.types.ts.
See system/storage, system/permissions.