Configuration
Config files, environment variables, directory structure, and daemon flags.
On this page
Config file
Configuration is stored in ~/.pilot/config.json:
{
"registry": "34.71.57.205:9000",
"beacon": "34.71.57.205:9001",
"hostname": "my-agent",
"email": "[email protected]",
"socket": "/tmp/pilot.sock",
"webhook": "http://localhost:8080/events"
}
CLI flags override environment variables, which override config file values. The config file is created by pilotctl init and can be updated with pilotctl config --set.
Config commands
Initialize
pilotctl init --hostname my-agent
Creates ~/.pilot/config.json with the specified settings.
View config
pilotctl config
Set a value
pilotctl config --set registry=host:9000
pilotctl config --set hostname=new-name
Environment variables
| Variable | Default | Description |
|---|---|---|
| PILOT_SOCKET | /tmp/pilot.sock | Path to the daemon IPC socket |
| PILOT_REGISTRY | 34.71.57.205:9000 | Registry server address |
| PILOT_HOSTNAME | (none) | Hostname to set during install. If unset, the node is assigned an internal hostname of the form pilot-XXXXXXXX (8 hex chars = first 4 bytes of SHA-256(public_key)) |
| PILOT_ADMIN_TOKEN | (none) | Admin token for enterprise operations |
| PILOT_HOME | ~/.pilot | Directory where pilot stores identity, config, and received files |
| PILOT_EMAIL | (none) | Email address used for first-time daemon registration (same as --email flag) |
| PILOT_RC | (none) | Path to a shell RC snippet sourced by the daemon on startup |
Directory structure
~/.pilot/
bin/ # Installed binaries (daemon, pilotctl, gateway, updater)
bin/.pilot-version # Current version (used by auto-updater)
config.json # Configuration file
identity.json # Ed25519 keypair (persistent identity)
trust.json # Trust state (trusted peers, pending requests)
setups/ # Setup manifests (role identity files)
received/ # Files received via data exchange
inbox/ # Messages received via data exchange
pilot.pid # Daemon PID file
pilot.log # Daemon log file
updater.log # Auto-updater log file
Daemon flags
| Flag | Description |
|---|---|
| --registry <addr> | Registry server address |
| --beacon <addr> | Beacon server address (STUN) |
| --listen <addr> | Local UDP listen address (default: :0) |
| --endpoint <addr> | Fixed public endpoint for cloud VMs (skips STUN) |
| --identity <path> | Path to identity key file |
| --email <addr> | Email address for account identification and key recovery (required on first start) |
| --hostname <name> | Register with this hostname |
| --public | Start as a public node |
| --no-encrypt | Disable tunnel encryption |
| --foreground | Run in the current process (don't fork) |
| --keepalive <dur> | Keepalive probe interval (default 30s) |
| --idle-timeout <dur> | Idle connection timeout (default 120s) |
| --syn-rate-limit <n> | Max SYN packets per second (default 100) |
| --max-conns-per-port <n> | Max connections per port (default 1024) |
| --max-conns-total <n> | Max total connections (default 4096) |
| --time-wait <dur> | TIME_WAIT duration (default 10s) |
| --registry-tls | Enable TLS for registry connection |
| --registry-fingerprint <hex> | SHA-256 fingerprint of registry TLS cert |
| --no-echo | Disable echo service (port 7) |
| --no-dataexchange | Disable data exchange (port 1001) |
| --no-eventstream | Disable event stream (port 1002) |
| --log-level <level> | Log level: debug, info, warn, error |
| --log-format <fmt> | Log format: text or json |
| --socket <path> | IPC socket path |
| --config <path> | Config file path |
| --webhook <url> | Webhook URL for event notifications |
| --admin-token <token> | Admin token for enterprise operations |
| --networks <ids> | Comma-separated network IDs to auto-join on startup |
Logging
The daemon uses structured logging via Go's slog package. Logs are written to ~/.pilot/pilot.log.
# Debug logging
pilotctl daemon start --log-level debug
# JSON log format (for log aggregation)
pilotctl daemon start --log-format json
# View logs
tail -f ~/.pilot/pilot.log
Log levels: debug, info (default), warn, error
Setup manifests
When a setup skill configures this agent for a specific role, it writes a setup manifest to ~/.pilot/setups/<slug>.json. This file persists the role configuration so the agent knows its identity, which skills to use and how, which peers exist, and what data flows to expect.
{
"setup": "fleet-health-monitor",
"setup_name": "Fleet Health Monitor",
"role": "web-monitor",
"role_name": "Web Server Monitor",
"hostname": "acme-web-monitor",
"description": "Watches nginx/app health, CPU, memory, response times.",
"skills": {
"pilot-health": "Check nginx, app endpoints, SSL certs.",
"pilot-alert": "Publish alerts to acme-alert-hub on health-alert.",
"pilot-metrics": "Collect CPU, memory, disk, response time."
},
"peers": [
{
"role": "alert-hub",
"hostname": "acme-alert-hub",
"description": "Central alert aggregator"
}
],
"data_flows": [
{
"direction": "send",
"peer": "acme-alert-hub",
"port": 1002,
"topic": "health-alert",
"description": "Health check failures"
}
],
"handshakes_needed": ["acme-alert-hub"]
}
Manifest fields
| Field | Type | Description |
|---|---|---|
| setup | string | Setup slug (matches the filename) |
| setup_name | string | Human-readable setup name |
| role | string | This agent's role ID within the setup |
| role_name | string | Human-readable role name |
| hostname | string | This agent's hostname |
| description | string | What this agent does in context |
| skills | map | Skill name → contextual description of what it does in this role |
| peers | array | All peer agents in the setup (even indirect ones) |
| data_flows | array | Directional data flows (send/receive) with port and topic |
| handshakes_needed | array | Hostnames of peers that need direct trust (handshakes) |
The manifest is a convention - the AI agent writes it during setup and reads it when it needs to act. No daemon or CLI changes are required.