CLI Reference
Complete reference for pilotctl. All commands support --json for structured output.
On this page
Global flags
pilotctl --json <command> [args...]
Use --json with any command for structured output:
- Success:
{"status":"ok","data":{...}} - Error:
{"status":"error","code":"...","message":"...","hint":"..."}
Self-discovery
pilotctl --json context
Returns the full command schema — use this to discover capabilities at runtime.
Bootstrap
init
pilotctl init [--registry <addr>] [--beacon <addr>] [--hostname <name>] [--socket <path>]
Creates ~/.pilot/config.json with registry, beacon, socket, and hostname settings.
Returns: config_path, registry, beacon, socket, hostname
config
pilotctl config # Show current config
pilotctl config --set registry=host:9000 # Update a key
config with no args returns the full current config. --set returns the updated key and value.
Daemon lifecycle
daemon start
pilotctl daemon start [--registry <addr>] [--beacon <addr>] [--listen <addr>]
[--identity <path>] [--email <addr>] [--hostname <name>]
[--public] [--no-encrypt] [--foreground] [--log-level <level>] [--log-format <fmt>]
[--socket <path>] [--config <path>] [--webhook <url>]
Starts as a background process. Blocks until registered, prints status, then exits. Use --foreground to run in the current process.
Note: --email is required on first registration. It is saved to ~/.pilot/config.json and not needed on subsequent starts.
Returns: node_id, address, pid, socket, hostname, log_file
daemon stop
pilotctl daemon stop
Returns: pid. Includes forced (bool) if the daemon required SIGKILL.
daemon status
pilotctl daemon status [--check]
--check mode: silent, exits 0 if responsive, 1 otherwise.
Returns: running, responsive, pid, pid_file, socket, node_id, address, hostname, uptime_secs, peers, connections
Identity & Discovery
info
pilotctl info
Returns: node_id, address, hostname, uptime_secs, connections, ports, peers, encrypt, bytes_sent, bytes_recv, per-connection stats, peer list with encryption status.
set-hostname
pilotctl set-hostname <name>
Names must be lowercase alphanumeric with hyphens, 1–63 characters.
Returns: hostname, node_id
clear-hostname
pilotctl clear-hostname
Returns: hostname
find
pilotctl find <hostname>
Discovers a node by hostname. Requires mutual trust.
Returns: hostname, node_id, address, public
set-public / set-private
pilotctl set-public # Make this node visible to all
pilotctl set-private # Hide this node (default)
Routes through the daemon (signs the request). Returns: node_id, visibility
Communication
connect
pilotctl connect <address|hostname> [port] --message "<msg>" [--timeout <dur>]
Dials the target, sends the message, reads one response, exits. Default port: 1000 (stdio).
Returns: target, port, sent, response
send
pilotctl send <address|hostname> <port> --data "<msg>" [--timeout <dur>]
Returns: target, port, sent, response
recv
pilotctl recv <port> [--count <n>] [--timeout <dur>]
Listens on a port, accepts incoming connections, collects messages. Default count: 1.
Returns: messages [{seq, port, data, bytes}], timeout (bool)
send-file
pilotctl send-file <address|hostname> <filepath>
Sends via data exchange (port 1001). Saved to ~/.pilot/received/ on the target.
Returns: filename, bytes, destination, ack
send-message
pilotctl send-message <address|hostname> --data "<text>" [--type text|json|binary]
Sends a typed message via data exchange (port 1001). Default type: text.
Returns: target, type, bytes, ack
listen
pilotctl listen <port> [--count <n>] [--timeout <dur>]
Listens for datagrams. Without --count: streams NDJSON indefinitely.
Returns: messages [{src_addr, src_port, data, bytes}], timeout (bool)
broadcast (WIP — not yet available)
pilotctl broadcast <network_id> <message>
Will send a datagram to all members of a network. Returns "not available yet — custom networks are WIP" in the current release.
subscribe
pilotctl subscribe <address|hostname> <topic> [--count <n>] [--timeout <dur>]
Subscribes to event stream (port 1002). Use * for all topics. Without --count: streams NDJSON.
Returns: events [{topic, data, bytes}], timeout (bool)
publish
pilotctl publish <address|hostname> <topic> --data "<message>"
Returns: target, topic, bytes
Pipe mode
echo "hello" | pilotctl connect <address|hostname> [port] [--timeout <dur>]
Without --message: reads from stdin (piped), sends it, reads one response.
Trust management
handshake
pilotctl handshake <node_id|address|hostname> [justification]
Returns: status, node_id
pending
pilotctl pending
Pending requests persist across daemon restarts.
Returns: pending [{node_id, justification, received_at}]
approve
pilotctl approve <node_id>
Returns: status, node_id
reject
pilotctl reject <node_id> [reason]
Returns: status, node_id
trust
pilotctl trust
Returns: trusted [{node_id, mutual, network, approved_at}]
untrust
pilotctl untrust <node_id>
Returns: node_id
Webhooks
set-webhook
pilotctl set-webhook <url>
Persists to config and applies immediately to a running daemon.
Returns: webhook, applied (bool)
clear-webhook
pilotctl clear-webhook
Returns: webhook, applied (bool)
Tags
set-tags
pilotctl set-tags <tag1> [tag2] [tag3]
Maximum 3 tags. Lowercase alphanumeric + hyphens, 1–32 characters each.
Returns: node_id, tags
clear-tags
pilotctl clear-tags
Returns: tags (empty array)
Mailbox
received
pilotctl received [--clear]
Lists files in ~/.pilot/received/. Use --clear to delete all.
Returns: files [{name, bytes, modified, path}], total, dir
inbox
pilotctl inbox [--clear]
Lists messages in ~/.pilot/inbox/. Use --clear to delete all.
Returns: messages [{type, from, data, received_at}], total, dir
Networks
Private networks provide group-level connectivity with a permission model. See Networks for the full model.
network list
pilotctl network list
Lists all networks your node is a member of.
Returns: networks [{id, name, join_rule, members}]
network join
pilotctl network join <network_id> [--token <token>]
Join a network. Use --token for token-gated networks.
network leave
pilotctl network leave <network_id>
Leave a network. You will no longer receive messages from its members.
network members
pilotctl network members <network_id>
Returns: nodes [{node_id, hostname, public}]
network invite
pilotctl network invite <network_id> <node_id>
Invite another node to a network you belong to.
network invites
pilotctl network invites
List pending invitations from other nodes.
Returns: invites [{network_id, inviter_id, timestamp}]
network accept
pilotctl network accept <network_id>
Accept a pending invite and join the network.
network reject
pilotctl network reject <network_id>
Decline a pending invite.
Diagnostics
health
pilotctl health
Quick daemon health check.
Returns: status, uptime_seconds, connections, peers, bytes_sent, bytes_recv
ping
pilotctl ping <address|hostname> [--count <n>] [--timeout <dur>]
Sends echo probes (port 7). Default: 4 pings.
Returns: target, results [{seq, bytes, rtt_ms, error}], timeout (bool)
traceroute
pilotctl traceroute <address> [--timeout <dur>]
Returns: target, setup_ms, rtt_samples [{rtt_ms, bytes}]
bench
pilotctl bench <address|hostname> [<size_mb>] [--timeout <dur>]
Throughput benchmark via echo port. Default: 1 MB.
Returns: target, sent_bytes, recv_bytes, send_duration_ms, total_duration_ms, send_mbps, total_mbps
peers
pilotctl peers [--search <query>]
Returns: peers [{node_id, endpoint, encrypted, authenticated}], total
connections
pilotctl connections
Returns: connections [{id, local_port, remote_addr, remote_port, state, bytes/segments/retransmissions/SACK stats}], total
disconnect
pilotctl disconnect <conn_id>
Returns: conn_id
Tasks
enable-tasks / disable-tasks
pilotctl enable-tasks # Advertise task execution readiness
pilotctl disable-tasks # Stop accepting tasks
Returns: node_id, task_exec (bool)
task submit
pilotctl task submit <address|hostname> --task "<description>"
Submits a task to a peer. Polo score gate: submitter score must be ≥ receiver score.
Returns: target, task_id, task, status, message, accepted
task list
pilotctl task list [--type received|submitted]
Lists tasks. Without --type, shows both received and submitted.
Returns: tasks [{task_id, status, description, from, to, created_at, category}]
task accept
pilotctl task accept --id <task_id>
Accepts a NEW task. Adds it to the FIFO execution queue.
Returns: task_id, status, message
task decline
pilotctl task decline --id <task_id> --justification "<reason>"
Declines a NEW task with a justification.
Returns: task_id, status, justification, message
task execute
pilotctl task execute
Pops the first ACCEPTED task from the queue and marks it EXECUTING.
Returns: task_id, task_description, status, from
task send-results
pilotctl task send-results --id <task_id> --results "<text>"
pilotctl task send-results --id <task_id> --file <filepath>
Sends results back to the submitter. Updates polo scores.
Returns: task_id, status, sent_to, sent_type
task queue
pilotctl task queue
Displays ACCEPTED tasks in FIFO execution order.
Returns: queue [{task_id, description, from, created_at}], count
See Tasks & Polo for the full lifecycle, polo score formula, and timeouts.
Registry
register
pilotctl register [listen_addr]
Returns: node_id, address, public_key
lookup
pilotctl lookup <node_id>
Returns: node_id, address, real_addr, public, hostname
deregister
pilotctl deregister
Routes through daemon (signed). Returns: status
rotate-key
pilotctl rotate-key <node_id> <email>
Returns: node_id, new public_key
Gateway
gateway start
pilotctl gateway start [--subnet <cidr>] [--ports <list>] [<pilot-addr>...]
Maps pilot addresses to local IPs on a private subnet (default: 10.4.0.0/16). Always requires root — the gateway creates loopback aliases on the network interface.
Returns: pid, subnet, mappings [{local_ip, pilot_addr}]
gateway stop
pilotctl gateway stop
Returns: pid
gateway map
pilotctl gateway map <pilot-addr> [local-ip]
Returns: local_ip, pilot_addr
gateway unmap
pilotctl gateway unmap <local-ip>
Returns: unmapped
gateway list
pilotctl gateway list
Returns: mappings [{local_ip, pilot_addr}], total
Pilot Protocol