tawa devtawa dev reads your catalog-info.yaml, generates all platform environment variables, and either connects to real databases via SSH tunnels (online mode) or spins up a local mock server (offline mode). Your service runs locally with the exact same process.env it gets in production.
# Online mode (real databases, SSH tunnels)
tawa dev
# Offline mode (mock everything locally)
tawa dev --offline
# Start your dev server automatically
tawa dev --run
catalog-info.yaml for databases, dependencies, auth, routes, schedules, queues.env.local with all platform env vars (database URIs, service URLs, OAuth credentials, etc.)--run, spawns your framework's dev command (next dev, tsx watch, etc.)Connects to real platform databases via SSH tunnels through the jefferson server:
spec.databases.env.localtawa dev
# Creates SSH tunnels, writes .env.local, waits for Ctrl+C
Runs a local Express mock server on port 4500 that simulates all platform services:
| Mock Service | What It Does |
|---|---|
| Bio-ID | Returns valid-looking JWTs, JWKS endpoint, user info |
| Septor | Accepts audit events, stores in memory |
| Relay | Logs emails/SMS to console instead of sending |
| iec-queue | Accepts job enqueues, logs them |
| iec-wallet | Returns mock balances |
| Storage | File upload/download with local filesystem |
All mock data is stored in a local JSON file — no external dependencies needed.
tawa dev --offline
# Starts mock server on :4500, writes .env.local pointing to mocks
--run FlagStarts your dev server alongside mocks/tunnels. Detects the right command automatically:
package.json scripts.dev (most reliable)catalog-info.yaml:
nextjs → npx next devexpress / hono / fastify → npx tsx watch src/index.tstawa dev --run # online + dev server
tawa dev --offline --run # offline + dev server
The dev server inherits the generated .env.local and runs in the foreground. Ctrl+C cleanly shuts down everything (dev server, tunnels, mock server).
| Variable | Value |
|---|---|
BIO_ID_URL | https://bio.tawa.pro (online) or http://localhost:4500 (offline) |
JANUS_URL | Internal Janus URL or mock |
KOKO_URL | Internal Koko URL or mock |
SERVICE_NAME | From metadata.name |
SERVICE_NAMESPACE | {name}-sandbox |
spec.databases)| Declaration | Variable | Online | Offline |
|---|---|---|---|
type: mongodb | MONGODB_URI | mongodb://localhost:{tunnel-port}/{name}-dev | mongodb://localhost:27017/{name}-dev |
type: redis | REDIS_URL | redis://localhost:{tunnel-port}/0 | redis://localhost:6379/0 |
type: neo4j | NEO4J_URI | bolt://localhost:{tunnel-port} | bolt://localhost:7687 |
spec.auth)| Variable | Value |
|---|---|
BIO_CLIENT_ID | {name}-dev |
BIO_CLIENT_SECRET | dev-secret-{name} |
Each entry in spec.internalDependencies generates {SERVICE}_URL:
http://localhost:4500/mock/{service}| Flag | Description |
|---|---|
--offline | Use local mock server instead of real connections |
--run | Start the dev server after setup |
--port <n> | Mock server port (default: 4500) |
--env <name> | Environment name for variable generation |
The tawa CLI compiles to a standalone binary via bun build --compile:
# Build the binary (~61MB, arm64)
bun build src/index.ts --compile --outfile tawa-bin
# Run it — includes all commands including tawa dev
./tawa-bin dev --offline --run
The compiled binary includes all mock server code, tunnel manager, and env generator. No Node.js or npm required on the target machine.
| Problem | Fix |
|---|---|
| SSH tunnel fails | Check ssh jefferson works manually, verify SSH key |
| Mock server port taken | Use --port 4501 or check lsof -i :4500 |
.env.local not picked up | Restart your dev server — env files are read at startup |
| OAuth callback fails locally | Add http://localhost:{port}/api/auth/callback to your Bio-ID client via tawa oauth add-uri |
| Missing env var | Check catalog-info.yaml — variable names derive from service declarations |
Last updated: July 15, 2026