Skip to main content

Serve Command

The sf serve command starts the Stoneforge orchestrator server and web dashboard in a single process.

Usage

sf serve [options]

Options

--port
number
default:"3457"
Port to listen on
--host
string
default:"localhost"
Host to bind to
--db
string
default:".stoneforge/stoneforge.db"
Path to SQLite database file

Examples

# Start on default port (3457)
sf serve

# Start on custom port
sf serve --port 8080

# Bind to all interfaces
sf serve --host 0.0.0.0

# Use custom database path
sf serve --db /path/to/stoneforge.db

Output

[orchestrator] Smithy server running at http://localhost:3457
The process will continue running until you stop it with Ctrl+C.

What Gets Started

When you run sf serve, Stoneforge starts:

1. HTTP API Server

RESTful API for all orchestrator operations:
  • Agent API (/api/agents/*) — Register, start, stop agents
  • Task API (/api/tasks/*) — Create, list, update tasks
  • Daemon API (/api/daemon/*) — Control dispatch daemon
  • Merge API (/api/merge-requests/*) — Manage merge requests
  • Channel API (/api/channels/*) — Agent communication

2. WebSocket Server

Real-time updates for:
  • Agent session output (terminal streaming)
  • Task status changes
  • Message notifications
  • Dispatch events

3. Web Dashboard

React SPA served at the root URL (http://localhost:3457):
  • Activity — Live agent output, system status
  • Tasks — Kanban boards, list views, filtering
  • Agents — Registration, session management
  • Merge Requests — Review queue
  • Inbox — Message triage
  • Documents — Shared knowledge base
  • Metrics — Task throughput, agent efficiency

4. Director Panel

Always-available right sidebar with interactive terminal for the Director agent.

Initial Setup Workflow

After starting the server for the first time:
# 1. Start server
sf serve

# 2. Open dashboard
open http://localhost:3457

# 3. In another terminal, register agents
sf agent register director --role director
sf agent register worker-1 --role worker
sf agent register merge-steward --role steward --focus merge

# 4. Start the director (via dashboard or CLI)
sf agent start <director-id>

# 5. Start the dispatch daemon
sf daemon start

# 6. Communicate with director via Director Panel

Server Architecture

The sf serve command runs a combined HTTP + WebSocket server built with:
  • Bun runtime (or Node.js)
  • React 19 for the web UI
  • Hono HTTP framework
  • WebSocket for real-time updates
  • SQLite for state management
┌─────────────────────────────────────────────────┐
│              sf serve (port 3457)               │
├─────────────────────────────────────────────────┤
│                                                 │
│  HTTP API                    WebSocket          │
│  ├── /api/agents             ├── /ws            │
│  ├── /api/tasks              └── (connections)  │
│  ├── /api/daemon                                │
│  ├── /api/merge-requests                        │
│  └── /api/channels                              │
│                                                 │
│  Web Dashboard (React SPA)                      │
│  ├── / (Activity, Inbox, Editor)                │
│  ├── /tasks (Tasks, MRs, Plans, Workflows)      │
│  ├── /agents (Agents, Stewards, Pools, Graph)   │
│  ├── /messages (Messages, Documents)            │
│  └── /metrics (Analytics)                       │
│                                                 │
│  Director Panel (right sidebar)                 │
│  └── Interactive terminal for director agent    │
│                                                 │
└─────────────────────────────────────────────────┘

Production Deployment

For production deployment, consider:

Bind to Public Interface

sf serve --host 0.0.0.0 --port 3457

Use a Reverse Proxy

Nginx example:
server {
  listen 80;
  server_name stoneforge.example.com;

  location / {
    proxy_pass http://localhost:3457;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

Run as a System Service

Systemd unit file (/etc/systemd/system/stoneforge.service):
[Unit]
Description=Stoneforge Orchestrator
After=network.target

[Service]
Type=simple
User=stoneforge
WorkingDirectory=/opt/stoneforge
ExecStart=/usr/local/bin/sf serve --host 0.0.0.0
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
# Enable and start
sudo systemctl enable stoneforge
sudo systemctl start stoneforge

# Check status
sudo systemctl status stoneforge

Docker Deployment

Dockerfile:
FROM oven/bun:1

WORKDIR /app

# Install Stoneforge
RUN bun install -g @stoneforge/smithy

# Initialize workspace
RUN sf init

EXPOSE 3457

CMD ["sf", "serve", "--host", "0.0.0.0"]
# Build and run
docker build -t stoneforge .
docker run -p 3457:3457 -v $(pwd)/.stoneforge:/app/.stoneforge stoneforge

Environment Variables

The server respects these environment variables:
  • STONEFORGE_DB — Database path (default: .stoneforge/stoneforge.db)
  • PORT — Server port (overridden by --port)
  • HOST — Bind host (overridden by --host)

Health Check Endpoint

The server exposes a health check endpoint:
curl http://localhost:3457/health
Response:
{
  "status": "ok",
  "timestamp": "2026-03-02T15:30:00Z",
  "uptime": 3600,
  "version": "1.0.0"
}

Troubleshooting

Port Already in Use

# Check what's using the port
lsof -i :3457

# Use a different port
sf serve --port 8080

Cannot Connect to Database

# Verify database exists
ls -la .stoneforge/stoneforge.db

# Reinitialize if needed
sf init

Web Assets Not Loading

# Rebuild web assets
cd ~/workspace/source/apps/smithy-web
pnpm build

# Restart server
sf serve

Daemon Commands

Start the dispatch daemon after the server is running

Agent Commands

Register and start agents once the server is ready

Build docs developers (and LLMs) love