Skip to content

Local development

Guide for running Buntime on desktop: monorepo in watch mode, .env at the root, external plugins with hot-reload, Docker Compose with profiles, and three binary execution modes (dev, bundle, compiled).

For environment variables and directories, see Environments. For Kubernetes deploy, see Helm charts.

Terminal window
# From the monorepo root
bun install
bun dev

This starts in parallel:

  • @buntime/runtime in watch mode
  • @buntime/cpanel in watch mode
  • Each @buntime/plugin-* core in watch mode

With no additional configuration, the runtime listens on http://localhost:8000 and the cpanel is available at /cpanel. Required variables come from the .env file at the monorepo root.

Launch configurations (.claude/launch.json)

Section titled “Launch configurations (.claude/launch.json)”

For one-click starts via tooling that reads Claude Code’s launch config, the repo ships four named configurations:

NameCommandPortStandalone?
buntime-devbun run dev (root: runtime + cpanel watcher + plugin watchers in parallel)8000yes — recommended default
runtime-devbun run --filter @buntime/runtime dev (runtime in watch mode)8000partial — see note
cpanel-watchbun run --filter @buntime/cpanel dev (build-watcher emitting to apps/cpanel/dist/)no — pair with running runtime
plugins-watchbun run --filter '@buntime/plugin-*' dev (build-watchers emitting to each plugins/*/dist/)no — pair with running runtime

The launch file mirrors the pattern from the sibling zomme monorepo (<thing>-dev for full apps, <thing>-watch for build-only watchers); the entries make these commands addressable by name to harness/IDE integrations.

Common workflows:

  • “Iterate on everything” → buntime-dev.
  • “Iterate on runtime code only, UI/plugins are stable” → runtime-dev (build cpanel/plugins once first).
  • “Iterate on cpanel UI while runtime stays up” → run buntime-dev (or runtime-dev) in one terminal + cpanel-watch in another. Refresh the browser to see UI changes.
  • “Iterate on a single plugin” → bun run --filter @buntime/plugin-<name> dev directly + POST /api/plugins/reload after each rebuild (no launch entry; one-off per plugin).

The .env file in buntime/ configures the runtime and core plugins:

Terminal window
# Runtime
RUNTIME_PLUGIN_DIRS=/path/to/external-plugins
RUNTIME_WORKER_DIRS=/path/to/buntime-apps:/path/to/edge-functions
# plugin-gateway (app shell)
GATEWAY_SHELL_DIR=/path/to/functions/app-shell
GATEWAY_SHELL_EXCLUDES=cpanel

Important rules:

  • RUNTIME_WORKER_DIRS and RUNTIME_PLUGIN_DIRS point to parents, not to individual apps/plugins. The loader scans direct children.
  • Separator is : (PATH style). Commas do not work.
  • Core plugins from the monorepo (plugins/*) are automatically loaded via node_modules when the runtime runs in dev mode — no need to add plugins/ to RUNTIME_PLUGIN_DIRS.
  • External plugins without dist/plugin.js are silently ignored.

Plugins outside the monorepo (in other repos) load via RUNTIME_PLUGIN_DIRS. For simultaneous hot-reload:

Terminal window
# Terminal 1 — runtime + cpanel + core plugins
cd /path/to/buntime
bun dev
# Terminal 2 — external plugin in watch mode
cd /path/to/external-plugins/plugin-foo
bun dev
# Terminal 3 — another external plugin
cd /path/to/external-plugins/plugin-bar
bun dev

For a one-time build without watch:

Terminal window
cd /path/to/external-plugins/plugin-foo
bun run build
ModeCommandUse caseSize
Devbun devHot reload, debugging, source maps
Bundlebun run dist/index.tsProduction-like, requires Bun~1.5 MB
Compiled./dist/buntimeStandalone, no Bun required~130 MB

Hot reload + source maps. Plugins load from node_modules. Slower startup.

Terminal window
cd apps/runtime
bun dev

Bundles the runtime but requires Bun to run:

Terminal window
cd apps/runtime
bun run build
bun run dist/index.ts

Output in dist/: index.ts (~1.3 MB) + wrapper.ts (~23 KB).

Standalone binary with everything embedded (Bun + core plugins):

Terminal window
cd apps/runtime
bun run build:bin
./dist/buntime

Configuration via env vars or a .env file in the execution directory:

Terminal window
RUNTIME_WORKER_DIRS=/apps RUNTIME_PLUGIN_DIRS=/plugins ./dist/buntime

Comparison:

FeatureDevBundleCompiledDocker
Hot reloadYesNoNoYes (dev profile)
Requires BunYesYesNoNo
Size~1.5 MB + Bun~130 MB~132 MB
Core pluginsnode_modulesEmbeddedEmbeddedEmbedded

Two profiles: dev (hot reload, source mounted) and prod (compiled binary).

Terminal window
# Hot reload with source mounted
docker-compose --profile dev up
# Production image
docker-compose --profile prod up
# Force rebuild
docker-compose --profile dev up --build
# Background
docker-compose --profile dev up -d
# Logs
docker-compose --profile dev logs -f buntime
# Shell into container
docker exec -it buntime sh
# Stop and remove volumes
docker-compose --profile dev down -v
ContainerLocalPurpose
/build/packages./packagesSource hot reload
/build/apps./appsSource hot reload
/build/plugins./pluginsSource hot reload
/data/.apps./appsCore apps (image symlink)
/data/.plugins./pluginsCore plugins
/data/apps${RUNTIME_WORKER_DIRS} or ./tmp/appsExternal apps
/data/plugins${RUNTIME_PLUGIN_DIRS} or ./tmp/pluginsExternal plugins
NODE_ENV: development
PORT: 8000
RUNTIME_API_PREFIX: /_
RUNTIME_LOG_LEVEL: debug
RUNTIME_PLUGIN_DIRS: /data/.plugins:/data/plugins
RUNTIME_WORKER_DIRS: /data/.apps:/data/apps
RUNTIME_POOL_SIZE: 10
DATABASE_LIBSQL_URL: http://libsql:8080
GATEWAY_SHELL_DIR: /data/apps/example-spa

Runtime dependency (the Turso/LibSQL integration points to http://libsql:8080):

PortUse
8880:8080HTTP API
8881:5001gRPC (replication)

SQLD_DISABLE_AUTH: "true"dev only. In production, use a token via DATABASE_LIBSQL_AUTH_TOKEN or LIBSQL_TOKEN.

Terminal window
docker-compose --profile dev logs buntime
lsof -i :8000 # check if the port is in use
Terminal window
docker-compose --profile dev ps
curl http://localhost:8880/health
  1. Confirm that volumes under /build/* are mounted
  2. Confirm NODE_ENV=development
  3. On macOS/Windows with Docker Desktop, the file watcher may be limited by inotify — restart the service
Terminal window
sudo chown -R $USER:$USER ./tmp

Symptom: plugin does not appear in GET /api/plugins. Common causes:

  1. dist/plugin.js does not exist — run bun run build inside the plugin
  2. manifest.yaml is missing or has no name field
  3. RUNTIME_PLUGIN_DIRS is pointing to the individual plugin instead of its parent
  4. Build was updated but the runtime was not restarted

The plugin-resource-tenant plugin is fatal if this env var is not set. Define it in the root .env or disable the plugin (enabled: false in manifest.yaml).

Systemd (running the compiled binary on a VM)

Section titled “Systemd (running the compiled binary on a VM)”
/etc/systemd/system/buntime.service
[Unit]
Description=Buntime Runtime
After=network.target
[Service]
Type=simple
User=buntime
Group=buntime
WorkingDirectory=/opt/buntime
ExecStart=/opt/buntime/buntime
Restart=always
RestartSec=5
Environment=PORT=8000
Environment=RUNTIME_WORKER_DIRS=/opt/buntime/apps
Environment=RUNTIME_LOG_LEVEL=info
[Install]
WantedBy=multi-user.target
Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now buntime
sudo systemctl status buntime