name: dev-workflow description: Development workflow for everything-dev projects using bos dev, bos start, and the Module Federation runtime. Use when starting dev servers, debugging hot reload, or understanding the service-descriptor architecture. metadata: sources: "packages/everything-dev/src/service-descriptor.ts,packages/everything-dev/src/orchestrator.ts,packages/everything-dev/src/dev-logs.ts,packages/everything-dev/src/dev-session.ts"
everything-dev Development Workflow
Starting Development
# Typical: start development (host mode auto-detected)
bos dev
# Isolate work
bos dev --api remote # UI only
bos dev --ui remote # API only
bos dev # Full local (rarely needed)
Port Assignments
| Service | Port | URL |
|---|---|---|
| host | 3000 | http://localhost:3000 |
| api | 3001 | http://localhost:3001 |
| auth | 3002 | http://localhost:3002 |
| ui | 3003 | http://localhost:3003 |
| ui-ssr | 3004 | http://localhost:3004 |
| plugins | 3010+ | http://localhost:3010+ (incremental — one per plugin in config order) |
Service-Descriptor Architecture
The orchestrator builds a ServiceDescriptorMap from bos.config.json. Each descriptor defines:
key— service identifier (host, ui, api, auth, plugin:*)source—"local"or"remote"(determines if process is spawned or URL is probed)port/defaultPort— TCP port for local servicesreadinessPath— HTTP path for readiness probes (e.g.,/health,/remoteEntry.js)readyPatterns/errorPatterns— Regexes matched against stdout/stderr
The orchestrator:
- Spawns local services via
bun run devin each package directory - Probes remote services via HTTP GET to their readiness path
- Tracks process state: pending → starting → ready → error
- Writes logs to
.bos/logs/{service}.log
Hot Reload
- UI changes: Rsbuild HMR — instant at :3003, no rebuild
- API changes: Rspack HMR — instant at :3001, no rebuild
- Auth / Plugin changes: No HMR — require full restart (
bos kill && bos dev) - SSR (ui-ssr): No HMR — restart required after UI changes
- Config changes: Require host restart (
bos kill && bos dev)
Contract Sync & Type Generation
Plugin types are auto-generated from bos.config.json via bos types gen:
bos types gen # Regenerate ui/src/lib/api-types.gen.ts and api/src/lib/plugins-types.gen.ts
When it auto-runs:
bun install(postinstall hook)bun typecheckbos devstartupbos build,bos deploy,bos publishbos pluginAdd/bos pluginRemove
How plugin types are resolved:
local:plugins/<name>→ readssrc/contract.tsdirectly from disk- Remote URL → fetches contract types from the deployed plugin's manifest
- Missing local path with no URL → skipped with a warning
Source of truth: bos.config.json. If a plugin is listed there, its routes appear on ApiContract. If removed, TypeScript catches stale usage.
After hand-editing bos.config.json: Run bos types gen or restart bos dev to pick up changes.
Runtime Config Loading
The host reads BOS_RUNTIME_CONFIG at startup (resolved from bos.config.json by the CLI). ConfigService is an immutable Effect Layer — every service is built from that one snapshot.
Override for testing: Set BOS_RUNTIME_CONFIG env var to a JSON string or file path to bypass config loading from disk. Useful for testing with different configs without modifying bos.config.json.
On page refresh:
- Browser re-fetches HTML shell from host
- Host injects current config into
window.__RUNTIME_CONFIG__ - Module Federation container re-initializes from fresh
remoteEntry.js
This means a new deployment requires a host restart to pick up new URLs.
Resolved Config (.bos/bos.resolved-config.json)
bos dev and bos build write the fully-merged config to .bos/bos.resolved-config.json (gitignored). This file includes _resolved metadata with env, timestamp, and extends chain.
bos.config.json is NOT modified during dev. Only bos publish --deploy, bos plugin publish/add/remove, and bos sync write to bos.config.json.
Build configs (rsbuild/rspack) read from .bos/bos.resolved-config.json first, falling back to bos.config.json. This allows slim child configs with extends to work correctly — the merged parent+child config is what the build sees.
Debugging
bos ps # List running processes + ports
bos status # Check remote health
bos info # Show current configuration
ls .bos/logs/ # Available log files
cat .bos/logs/api.log # API process logs
Port Conflicts
If a port is already in use, the local service fails to start. Check what's on the port:
lsof -i :3003 # Check what is using port 3003
Kill the conflicting process and retry, or stop the existing bos dev session first.
Stale PID file
If bos kill doesn't run cleanly (e.g., terminal was closed), stale PIDs in .bos/pids.json can block restart:
rm .bos/pids.json # Clear stale PID tracking
bos dev # Start fresh
API not responding
bos ps— is API running?.bos/logs/api.log— startup errors?curl http://localhost:3001/remoteEntry.js— is the entry accessible?
UI not loading
- Check browser console for Module Federation errors
bos.config.json— isapp.ui.developmentcorrect?- Clear browser cache and hard reload (Cmd+Shift+R)
- Verify UI SSR restart if using SSR
Module Federation errors
- Verify shared dependency versions match across package.json files
- Clear browser cache (Cmd+Shift+R)
- Check
bos.config.jsonURLs are accessible
Production Mode
bos start --no-interactive # All remotes, production URLs
bos start --env staging --no-interactive # Staging environment
bos start --account foo.near --domain bar.com # Load specific config
Process Management
bos ps # Show PID, name, port, started time
bos kill # Graceful SIGTERM → SIGKILL
bos kill --force # Immediate SIGKILL
Process tracking uses .bos/pids.json.