Using Paperclip's embedded PGlite database as a zero-cost local sandbox: activation, where data lives on disk, running test heartbeats without real API calls, resetting sandbox state, and when to switch to real PostgreSQL.
How Paperclip's embedded PGlite database works as a zero-cost local sandbox, how to run test heartbeats without spending real API credits, and when to switch to real PostgreSQL.
PGlite is a full PostgreSQL engine compiled to WebAssembly that runs in-process — no separate database server required. When DATABASE_URL is blank in your .env, Paperclip automatically uses PGlite as its persistence layer.
This means:
- Zero setup — no Postgres install, no Docker, no connection strings
- Full SQL compatibility — every Paperclip query runs identically
- Data lives on disk — in .paperclip/dev.db in the project root
paperclip/
.paperclip/
dev.db ← PGlite database file (all your sandbox data)
dev.db-wal ← write-ahead log (normal, auto-managed)
You can inspect this file with any SQLite-compatible viewer (e.g. the SQLite Viewer VS Code extension — PGlite files are SQLite-format compatible for reads).
The fastest way to iterate in the sandbox is to use the dry-run flag, which runs the heartbeat scheduling logic but calls a mock adapter instead of the real AI:
# Trigger a dry-run heartbeat for all active agents
curl -X POST http://localhost:3100/api/heartbeat/trigger \
-H "Content-Type: application/json" \
-d '{"dry_run": true}'
A dry-run:
- Selects tasks exactly as a real run would
- Creates heartbeat_runs records with status: 'dry_run'
- Does not call any adapter (no API cost)
- Writes to activity_log so you can verify routing logic
When you want a clean slate:
Option A — Delete just the database file:
rm .paperclip/dev.db .paperclip/dev.db-wal
# Restart pnpm dev — Drizzle will re-run migrations automatically
Option B — Reset via the API (keeps the server running):
curl -X POST http://localhost:3100/api/dev/reset
# ⚠ Only available when NODE_ENV=development
Both options wipe all companies, agents, issues, and logs. The schema is recreated automatically on next startup.
When you're ready for production — or when you want to share a persistent sandbox with teammates — swap to a real PostgreSQL instance:
# .env
DATABASE_URL=postgresql://user:password@localhost:5432/paperclip_dev
Paperclip detects the DATABASE_URL and skips PGlite entirely. Drizzle runs the same migrations against the real database on startup.
No code changes needed — the switch is purely configuration. All Drizzle queries work identically against PGlite and PostgreSQL.
| Limitation | Impact |
|---|---|
| Single-process only | Can't run two server instances pointing at the same PGlite file |
| No network access | Can't connect external tools (pgAdmin, DBeaver) directly — use the API instead |
| File lock | Stop pnpm dev before deleting dev.db |
| Not for production | PGlite is a dev/test tool only — always use real PostgreSQL in production |
Start pnpm dev (PGlite auto-created)
↓
Create test company + agents
↓
Trigger dry-run heartbeats (zero cost)
↓
Verify routing, logging, task selection
↓
Switch to real adapter for live testing
↓
Reset sandbox when done → rm dev.db
.env change switches from PGlite to real PostgreSQL?