Daemon Management
The OpenFang daemon is the core service that runs the kernel, manages agents, and provides the HTTP API and web dashboard.
Starting the Daemon
openfang start
Start the OpenFang daemon (kernel + API server).
openfang start [--config < PAT H > ]
Options:
Option Description --config <PATH>Path to a custom config file (overrides ~/.openfang/config.toml)
Behavior:
Checks if a daemon is already running; exits with an error if so
Boots the OpenFang kernel:
Loads configuration from ~/.openfang/config.toml
Initializes SQLite database
Loads persisted agents
Connects to configured MCP servers
Starts background tasks
Starts the HTTP API server on the configured address (default: 127.0.0.1:4200)
Writes daemon.json to ~/.openfang/ for daemon discovery
Blocks until interrupted with Ctrl+C
Example Output:
$ openfang start
OpenFang Agent OS v0.1.0
Starting daemon...
[ok] Kernel booted (groq/llama-3.3-70b-versatile)
[ok] 50 models available
[ok] 3 agent ( s ) loaded
API: http://127.0.0.1:4200
Dashboard: http://127.0.0.1:4200/
Provider: groq
Model: llama-3.3-70b-versatile
hint: Open the dashboard in your browser, or run ` openfang chat`
hint: Press Ctrl+C to stop the daemon
The daemon runs in the foreground by default. For background operation, use a process manager like systemd, pm2, or run in a screen/tmux session.
Starting with Custom Config
openfang start --config /path/to/custom-config.toml
Docker Configuration
When running in Docker, bind to 0.0.0.0 to allow external connections:
# config.toml
api_listen = "0.0.0.0:4200"
Or use the environment variable:
OPENFANG_LISTEN = 0.0.0.0:4200 openfang start
Stopping the Daemon
openfang stop
Stop the running daemon gracefully.
Behavior:
Reads daemon.json to locate the daemon
Sends POST /api/shutdown to the daemon
Waits up to 5 seconds for graceful shutdown
If daemon doesn’t stop, force-kills via PID
Removes daemon.json
Example Output:
$ openfang stop
[ok] Daemon stopped
If the daemon doesn’t respond within 5 seconds, it will be force-killed using kill -9 (Unix) or taskkill /F (Windows).
Stopping from the Same Terminal
If you started the daemon in the foreground, simply press Ctrl+C:
$ openfang start
# ... daemon running ...
^C
OpenFang daemon stopped.
Checking Daemon Status
openfang status
Show the current kernel/daemon status.
Options:
Option Description --jsonOutput machine-readable JSON for scripting
Behavior:
If daemon is running : Queries GET /api/status and displays:
Agent count
Provider and model
Uptime
API URL
Data directory
List of active agents
If no daemon is running : Boots an in-process kernel and shows persisted state with a warning
Example Output (Daemon Running):
$ openfang status
OpenFang Status
Daemon: running
API: http://127.0.0.1:4200
Provider: groq
Model: llama-3.3-70b-versatile
Agents: 3
Uptime: 2h 15m
Data: ~/.openfang/
Active Agents:
- coder (a1b2c3d4-...)
- assistant (e5f6g7h8-...)
- researcher (i9j0k1l2-...)
Example Output (No Daemon):
$ openfang status
[ ! ] Warning: Daemon is not running
hint: Start it with: openfang start
Showing persisted state:
Provider: groq
Model: llama-3.3-70b-versatile
Agents: 3 (not running )
JSON Output
$ openfang status --json
{
"daemon_running" : true ,
"api_url" : "http://127.0.0.1:4200",
"provider" : "groq",
"model" : "llama-3.3-70b-versatile",
"agent_count" : 3,
"uptime_seconds" : 8100,
"data_dir" : "/home/user/.openfang",
"agents" : [
{ "id" : "a1b2c3d4-...", "name": "coder", "state": "idle"},
{ "id" : "e5f6g7h8-...", "name": "assistant", "state": "processing"},
{ "id" : "i9j0k1l2-...", "name": "researcher", "state": "idle"}
]
}
Scripting with JSON:
# Check if daemon is running
if openfang status --json | jq -e '.daemon_running' > /dev/null ; then
echo "Daemon is up"
fi
# Get agent count
AGENT_COUNT = $( openfang status --json | jq '.agent_count' )
echo "Running agents: $AGENT_COUNT "
Health Checks
openfang health
Quick daemon health check.
Example Output:
$ openfang health
[ok] Daemon is healthy
API: http://127.0.0.1:4200
JSON Output:
$ openfang health --json
{ "status" : "healthy", "api_url": "http://127.0.0.1:4200"}
openfang health performs a lightweight check (just the HTTP health endpoint), while openfang status provides comprehensive system information.
Diagnostic Checks
openfang doctor
Run comprehensive diagnostic checks on the OpenFang installation.
openfang doctor [--json] [--repair]
Options:
Option Description --jsonOutput results as JSON for scripting --repairAttempt to auto-fix issues (prompts for confirmation)
Checks Performed:
OpenFang directory - ~/.openfang/ exists
.env file - exists and has correct permissions (0600 on Unix)
Config TOML syntax - config.toml parses without errors
Daemon status - whether a daemon is running
Port availability - if daemon is not running, checks if port 4200 is free
Stale daemon.json - leftover file from a crashed daemon
Database file - SQLite magic bytes validation
Disk space - warns if less than 100MB available (Unix only)
Agent manifests - validates all .toml files in ~/.openfang/agents/
LLM provider keys - checks env vars for all providers, performs live validation
Channel tokens - format validation for Telegram, Discord, Slack tokens
Config consistency - checks that api_key_env references match actual env vars
Rust toolchain - rustc --version
Example Output:
$ openfang doctor
OpenFang Diagnostics
[ok] OpenFang directory exists
[ok] .env file exists (permissions: 0600 )
[ok] config.toml syntax is valid
[ok] Daemon is running (http://127.0.0.1:4200)
[ok] Database file is valid
[ok] 125GB disk space available
[ok] 3 agent manifests validated
[ok] GROQ_API_KEY: valid
[warn] ANTHROPIC_API_KEY: not set
[ok] Telegram token format valid
[ok] Config references match environment
[ok] Rust 1.75.0
Summary: 11 checks passed, 1 warning
Auto-Repair Mode
$ openfang doctor --repair
OpenFang Diagnostics
[ ! ] OpenFang directory missing
[ ? ] Create ~/.openfang/? (y/n): y
[ok] Created ~/.openfang/
[ ! ] Stale daemon.json detected (PID 1234 not running )
[ ? ] Remove daemon.json? (y/n): y
[ok] Removed stale daemon.json
[ok] Database file is valid
...
--repair mode will prompt before making any changes. It can create missing directories, remove stale files, and fix file permissions.
Gateway Commands
The gateway subcommand provides an alternative interface to daemon management:
openfang gateway start # Same as: openfang start
openfang gateway stop # Same as: openfang stop
openfang gateway status # Same as: openfang status
Dashboard Access
openfang dashboard
Open the web dashboard in the default browser.
Behavior:
Requires a running daemon
Opens the daemon URL (e.g. http://127.0.0.1:4200/) in the system browser
Copies the URL to the system clipboard
Example Output:
$ openfang dashboard
[ok] Opening dashboard at http://127.0.0.1:4200/
[ok] URL copied to clipboard
The dashboard is an Alpine.js single-page application served directly by the daemon.
Daemon Auto-Detection Details
The CLI uses a two-step mechanism to detect a running daemon:
Step 1: Read daemon.json
On startup, the daemon writes ~/.openfang/daemon.json:
{
"listen_addr" : "127.0.0.1:4200" ,
"pid" : 12345 ,
"started_at" : "2025-03-06T10:30:00Z"
}
The CLI reads this file to discover the daemon’s listen address.
Step 2: Health Check
The CLI sends GET http://<listen_addr>/api/health with a 2-second timeout:
$ curl -s http://127.0.0.1:4200/api/health
{ "status" : "ok" }
If the health check succeeds, the daemon is considered running.
Fallback to In-Process Mode
If either step fails (no daemon.json, stale file, health check timeout), the CLI falls back to in-process mode for commands that support it.
Commands that require a daemon:
workflow commands
trigger commands
channel test/enable/disable
dashboard
These will exit with an error and a helpful message if no daemon is found.
Troubleshooting
Daemon Won’t Start
Port Already in Use:
$ openfang start
[ ! ] Error: Address already in use ( port 4200 )
hint: Another process is using port 4200. Check with: lsof -i :4200
Solutions:
Kill the process using port 4200
Change the port in config.toml: api_listen = "127.0.0.1:4201"
Database Locked:
$ openfang start
[ ! ] Error: Database is locked
hint: Another OpenFang instance may be running
Solutions:
Check for other OpenFang processes: ps aux | grep openfang
Remove stale lock: rm ~/.openfang/data/openfang.db-shm
Config Parse Error:
$ openfang start
[ ! ] Error: Failed to parse configuration
hint: Check your config.toml syntax: openfang config show
Solutions:
Validate TOML syntax with openfang doctor
Restore default config: rm ~/.openfang/config.toml && openfang init --quick
Daemon Won’t Stop
$ openfang stop
[ ! ] Daemon did not respond, force-killing...
[ok] Daemon stopped ( forced )
This happens when the daemon is unresponsive. The CLI will automatically force-kill it.
Stale daemon.json
If the daemon crashes, daemon.json may be left behind:
$ openfang doctor --repair
[ ! ] Stale daemon.json detected ( PID 1234 not running )
[ ? ] Remove daemon.json ? ( y/n ): y
[ok] Removed stale daemon.json
Production Deployment
Systemd Service (Linux)
Create /etc/systemd/system/openfang.service:
[Unit]
Description =OpenFang Agent OS
After =network.target
[Service]
Type =simple
User =openfang
WorkingDirectory =/home/openfang
Environment = "GROQ_API_KEY=gsk_..."
ExecStart =/usr/local/bin/openfang start
Restart =on-failure
RestartSec =10
[Install]
WantedBy =multi-user.target
Enable and start:
sudo systemctl enable openfang
sudo systemctl start openfang
sudo systemctl status openfang
Docker Compose
version : '3.8'
services :
openfang :
image : openfang/openfang:latest
environment :
- GROQ_API_KEY=gsk_...
- OPENFANG_LISTEN=0.0.0.0:4200
ports :
- "4200:4200"
volumes :
- openfang-data:/home/openfang/.openfang
restart : unless-stopped
volumes :
openfang-data :
PM2 (Node.js Process Manager)
pm2 start openfang --name openfang-daemon -- start
pm2 save
pm2 startup
Next Steps
Agent Commands Learn how to create and manage agents
Configuration Configure providers, models, and channels