Flow

Configuration

Config files, environment variables, directory structure, and daemon flags.

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

VariableDefaultDescription
PILOT_SOCKET/tmp/pilot.sockPath to the daemon IPC socket
PILOT_REGISTRY34.71.57.205:9000Registry 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~/.pilotDirectory 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

FlagDescription
--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
--publicStart as a public node
--no-encryptDisable tunnel encryption
--foregroundRun 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-tlsEnable TLS for registry connection
--registry-fingerprint <hex>SHA-256 fingerprint of registry TLS cert
--no-echoDisable echo service (port 7)
--no-dataexchangeDisable data exchange (port 1001)
--no-eventstreamDisable 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

FieldTypeDescription
setupstringSetup slug (matches the filename)
setup_namestringHuman-readable setup name
rolestringThis agent's role ID within the setup
role_namestringHuman-readable role name
hostnamestringThis agent's hostname
descriptionstringWhat this agent does in context
skillsmapSkill name → contextual description of what it does in this role
peersarrayAll peer agents in the setup (even indirect ones)
data_flowsarrayDirectional data flows (send/receive) with port and topic
handshakes_neededarrayHostnames 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.