IFM CLI Reference
Overview
The ifm command-line interface provides a Unix-like tool for interacting with the IFM network. Designed for scripting, automation, and direct terminal use.
Installation
Pre-built Binaries
# Linux/macOS
curl -fsSL https://github.com/ifmprotocol/ifm/releases/latest/download/ifm-$(uname -s)-$(uname -m).tar.gz | tar xz
sudo mv ifm /usr/local/bin/
# Windows (PowerShell)
irm https://github.com/ifmprotocol/ifm/releases/latest/download/ifm-windows-x64.zip | Expand-Archive
# Add to PATHCargo
cargo install ifm-cliHomebrew
brew install ifmprotocol/tap/ifmGlobal Options
ifm [GLOBAL_OPTIONS] <COMMAND> [COMMAND_OPTIONS]
GLOBAL_OPTIONS:
-c, --config <PATH> Config file path (default: ./config.toml or ~/.config/ifm/config.toml)
-d, --data-dir <PATH> Data directory (default: ./data or ~/.local/share/ifm)
-v, --verbose Verbose output
-q, --quiet Suppress non-error output
--json Output as JSON
--no-color Disable colored output
-h, --help Show help
-V, --version Show versionCommands
ifm init — Initialize Node
Create identity and configuration for a new node.
ifm init [OPTIONS]
OPTIONS:
-n, --name <NAME> Display name for this node
-f, --force Overwrite existing identity
--no-bootstrap Disable bootstrap peers
--no-lan Disable local discovery
EXAMPLES:
ifm init
ifm init --name "Enzo's Radio"
ifm init --force --no-bootstrapOutput:
Generated identity: 12D3KooWabc123...
Config written to: ./config.toml
Identity stored at: ./data/identity.keyifm connect — Connect to Network
Establish connection to the IFM mesh network.
ifm connect [OPTIONS]
OPTIONS:
-b, --bootstrap <ADDR> Additional bootstrap peer (multiaddr)
--timeout <SECONDS> Connection timeout (default: 30)
--wait-peers <N> Wait for at least N peers (default: 1)
EXAMPLES:
ifm connect
ifm connect --bootstrap /ip4/1.2.3.4/udp/4001/quic-v1/p2p/12D3KooW...
ifm connect --wait-peers 5 --timeout 60Output:
Connecting to network...
Bootstrap: bootstrap.ifm.network:4001 ✓
DHT: 247 peers discovered
Connected to 12 peers
GossipSub: subscribed to 0 topics
Ready!ifm disconnect — Disconnect from Network
Gracefully disconnect from the mesh.
ifm disconnect
EXAMPLES:
ifm disconnectifm tune — Join a Frequency
Tune to a frequency (join a channel).
ifm tune <FREQUENCY> [OPTIONS]
ARGUMENTS:
FREQUENCY Human-readable frequency (e.g., "91.700", "chat.general", "private.team")
OPTIONS:
-k, --key <KEY> Encryption key for protected frequency (base64)
-w, --wait-peers <N> Wait for N peers before returning (default: 1)
-t, --timeout <SECONDS> Timeout (default: 10)
--listen Stay tuned and listen for messages (implies --wait-peers 0)
EXAMPLES:
ifm tune 91.700
ifm tune chat.general
ifm tune private.team --key "base64secret=="
ifm tune 91.700 --listen
ifm tune music.lofi --wait-peers 3Output:
Tuning to 91.700...
Topic ID: 0xabcdef123456...
Discovered 8 peers
Connected to 5 peers
Subscribed to GossipSub topic
Sent HELLO, received 3 WELCOME
Tuned! (5 peers)ifm leave — Leave a Frequency
Leave a frequency you're tuned to.
ifm leave <FREQUENCY>
EXAMPLES:
ifm leave 91.700
ifm leave chat.generalifm broadcast — Send Message
Broadcast a message to all peers on a frequency.
ifm broadcast <MESSAGE> [OPTIONS]
ARGUMENTS:
MESSAGE Text to broadcast (use - for stdin)
OPTIONS:
-f, --frequency <FREQ> Target frequency (default: primary tuned frequency)
-t, --type <TYPE> Payload type: text, json, file (default: text)
--compress / --no-compress Enable/disable compression (default: auto)
EXAMPLES:
ifm broadcast "Hello, IFM!"
ifm broadcast "Hello" --frequency 91.700
echo "Hello" | ifm broadcast -
ifm broadcast '{"type":"status","value":42}' --type json
ifm broadcast @file.txt --type fileifm send — Direct Message
Send a direct message to a specific peer.
ifm send <PEER_ID> <MESSAGE> [OPTIONS]
ARGUMENTS:
PEER_ID Target peer ID (e.g., 12D3KooW...)
MESSAGE Text to send (use - for stdin)
OPTIONS:
-t, --type <TYPE> Payload type: text, json, file (default: text)
EXAMPLES:
ifm send 12D3KooWabc123 "Private message"
ifm send 12D3KooWabc123 '{"cmd":"ping"}' --type jsonifm speak — Voice Transmission
Start/stop voice transmission on a frequency.
ifm speak [OPTIONS]
OPTIONS:
-f, --frequency <FREQ> Frequency to speak on (default: primary)
--vad / --no-vad Voice activity detection (default: on)
--bitrate <KBPS> Target bitrate (default: auto)
--duration <SECONDS> Auto-stop after N seconds
--device <ID> Audio input device ID
--list-devices List available input devices
EXAMPLES:
ifm speak
ifm speak --frequency 91.700
ifm speak --duration 30
ifm speak --list-devices
ifm speak --device "USB Microphone"Output (interactive):
Speaking on 91.700... (Ctrl+C to stop)
Input: "USB Microphone"
Bitrate: auto (Opus)
VAD: enabled
Peers: 3 listening
[===== ] -12 dBifm mute — Stop Voice
Stop voice transmission.
ifm mute
EXAMPLES:
ifm muteifm scan — Discover Frequencies
Scan for active frequencies on the network.
ifm scan [OPTIONS]
OPTIONS:
-l, --local Include local (mDNS) discovery
-d, --dht Include DHT discovery (default: both)
-t, --timeout <SECONDS> Scan timeout (default: 5)
--json Output as JSON
EXAMPLES:
ifm scan
ifm scan --local --timeout 10
ifm scan --jsonOutput:
Scanning frequencies...
91.700 public 23 peers "General Chat"
chat.general public 12 peers "Main Discussion"
music.lofi public 45 peers "Lo-fi Beats" 🎵
private.team protected 3 peers (encrypted)
weather.tokyo public 1 peer "Tokyo Weather"
sensor.temp public 8 peers "Temperature Sensors"
Found 6 frequenciesifm peers — List Connected Peers
Show peers on current or specific frequency.
ifm peers [OPTIONS]
OPTIONS:
-f, --frequency <FREQ> Show peers on specific frequency
--json Output as JSON
EXAMPLES:
ifm peers
ifm peers --frequency 91.700
ifm peers --jsonOutput:
Peers on 91.700 (5):
12D3KooWabc123... "Enzo" 45ms voice,chat ✓
12D3KooWdef456... "RadioBot" 12ms chat,file ✓
12D3KooWghi789... (anonymous) 89ms voice ✓
12D3KooWjkl012... "Mobile" 156ms chat ✓
12D3KooWmno345... "Server" 8ms chat,file ✓
Legend: ✓ = connected, RTT = round-trip timeifm stats — Node Statistics
Display node statistics and health info.
ifm stats [OPTIONS]
OPTIONS:
--json Output as JSON
--watch Continuous update (like top)
EXAMPLES:
ifm stats
ifm stats --json
ifm stats --watchOutput:
IFM Node Statistics
===================
Identity: 12D3KooWabc123... (Enzo)
Uptime: 2h 34m 12s
Status: Connected
Network:
Peers: 47 connected
Bootstrap: 3/3 healthy
DHT: 1,247 peers in routing table
GossipSub: 12 topics subscribed
Traffic:
Packets sent: 15,234
Packets recv: 18,567
Bytes sent: 4.2 MB
Bytes recv: 5.1 MB
Packets dropped: 12 (duplicates)
Resources:
Memory: 42 MB / 64 MB limit
CPU: 3.2%
File descriptors: 142 / 1024
Frequencies:
91.700 5 peers 1,234 msgs
chat.general 12 peers 567 msgs
music.lofi 3 peers (voice)ifm relay — Relay Pool & Metrics
Manage the shared, station-agnostic, frequency-agnostic relay pool — no relay is ever bound to a frequency or station; listeners resolve the closest hop (peer, then nearest relay, then the station's origin) automatically (spec §"Relay").
ifm relay <SUBCOMMAND> [OPTIONS]
SUBCOMMANDS:
config Show this node's relay configuration
config --serve Serve as a relay (join the shared pool; native core)
config --off Stop serving every frequency (leave the relay pool)
status Show the live relay pool with round-trip times
metrics Relay traffic and pool metrics
announce Sign + broadcast a relay announcement (discovery plane)
select Score known relays for this node and print the best
ARGUMENTS:
RELAY Native core: 64-hex IFM node id (first 8 chars from `ifm relay status`).
JS CLI: the relay's id or ws URL from `ifm relay status` (e.g. `relay-8790`).Topology: a relay is station-agnostic, frequency-agnostic infrastructure — it does not care who connects or what it carries, and it is never attached to any frequency or station. Any station transmits through any relay in the shared pool. Path choice is P2P-first and quality-driven (spec §19a): the Path Manager scores every candidate path — direct peers, alternate peers, and the pool's relays — from measured round-trip time, jitter, loss, bandwidth, hops, and stability, and the best-scoring path carries the media stream. A relay therefore enters the path automatically whenever its measured quality beats the direct path (e.g. Station → Relay → Listener at 45 ms vs a degraded Station → A → B → Listener at 80 ms) — even while P2P still works — and leaves when P2P recovers. Direct peer-to-peer transmission is the default when no relay is reachable or none scores better. Any listener can extend coverage by serving as a relay too.
crates/cliimplements the full plane:--serve/--offturn this node into a pool relay. The WebSocket hub (relay.mjs --serve) serves the browser demo mesh; the native CLI's relay plane is independent of it.
relay config|status|metricshonor--jsonfor scripting.
EXAMPLES:
# Become a relay (native core — joins the shared pool)
ifm relay config --serve
# Show the pool and live round-trip times
ifm relay status
# Leave the pool
ifm relay config --offOutput (status):
relay: enabled
relay pool (2):
2cda775f rtt 12 ms /ip4/127.0.0.1/udp/4002/quic-v1
a1b2c3d4 rtt 38 ms /ip4/127.0.0.1/udp/4003/quic-v1JS CLI output is pool-shaped (the demo hub speaks URLs, not multiaddrs):
relay: connected
relay pool (1):
RELAY ID URL RTT
relay-8790 192.168.100.98:8790 0 msDiscovery (announce / select): relays advertise signed metadata (region, protocols, capacity, bandwidth, latency, price — spec §17–§18 of docs/protocol/discovery.md) over the discovery plane, and listeners score them per preference:
# Advertise this node as a relay (independent of pool serving)
ifm relay announce --region eu --bandwidth "1 Gbps" --latency 5
# Rank known relays for this node; best first, * marks the selection
ifm relay select --region eu --protocol quic --max-price 10Output (select):
* relay1_K8k29c… score=0.711 rtt=12ms
relay1_7xQp2a… score=0.402 rtt=38msWhen no relay is live/eligible the command reports the spec §19 fallback: transmit directly to peers.
ifm station — Station Discovery
Announce this node as a station, list discovered stations, or search them (zero-config local discovery; spec docs/protocol/discovery.md §4–§14).
ifm station <SUBCOMMAND> [OPTIONS]
SUBCOMMANDS:
announce <NAME> Sign + broadcast this node as a station
--status live|offline Presence status (default live)
--channel id:name Channel (repeatable)
--endpoint URL Endpoint (repeatable)
--meta key=value Searchable metadata (repeatable, e.g. location=Berlin)
list List known stations
--query TEXT Free-text filter (name / id / channel)
--live Only LIVE stations
search Structured search (spec §13)
--query/--location/--language/--category/--genre/--country/--region
--live Only LIVE stationsStation IDs are key-derived (ifm1_ + BLAKE3 of the station's Ed25519 key), stable across network changes, and every record is signed — listeners reject tampered or mismatched records (§14). Announcements are re-broadcast on a 30s heartbeat and persist under the node's data dir (station.json), so ifm station list sees them across invocations.
EXAMPLES:
# Announce "IFM News" with channels and search metadata
ifm station announce "IFM News" --channel main:Main --meta location=Berlin --meta genre=news
# Discover stations on the LAN (zero-config)
ifm station list
# Find live news stations in Berlin
ifm station search --location Berlin --genre news --liveOutput (announce):
✓ announced station ifm1_WbZBAzqe_ECd7tCyclc8R-66kMZcWgxYjW2KsoC8CPk
IFM News — live
channels: main:MainOutput (list):
ifm1_WbZBAzqe… IFM News [LIVE] live
location: Berlin
1 station(s)ifm monitor — Real-time Packet Monitor
Monitor packet flow in real-time.
ifm monitor [OPTIONS]
OPTIONS:
-f, --frequency <FREQ> Filter by frequency
-t, --type <TYPE> Filter by payload type
--follow Follow new packets (default)
--count <N> Show last N packets and exit
--json Output as JSON lines
EXAMPLES:
ifm monitor
ifm monitor --frequency 91.700
ifm monitor --type voice --count 100
ifm monitor --json | jq .Output:
ifm file — File Transfer
Send or receive files.
ifm file <SUBCOMMAND> [OPTIONS]
SUBCOMMANDS:
send <FILE> [FREQUENCY] Send file to frequency
receive <FILE_ID> [OUTPUT] Receive file by ID
list List pending/active transfers
OPTIONS (send):
-f, --frequency <FREQ> Target frequency
--chunk-size <BYTES> Chunk size (default: 65536)
--encrypt Encrypt with frequency key
EXAMPLES:
ifm file send photo.jpg 91.700
ifm file send document.pdf --frequency chat.general --encrypt
ifm file receive abc123... output.pdf
ifm file listifm identity — Identity Management
Manage node identity.
ifm identity <SUBCOMMAND> [OPTIONS]
SUBCOMMANDS:
show Show current identity
export [PATH] Export identity (private key)
import <PATH> Import identity
regenerate Generate new identity (DANGEROUS)
qr Show identity as QR code
OPTIONS:
--format <FORMAT> Output format: pem, base58, hex, json (default: base58)
EXAMPLES:
ifm identity show
ifm identity export --format pem > identity.pem
ifm identity import ./identity.pem
ifm identity regenerate --force
ifm identity qrOutput (show):
Identity
========
Peer ID: 12D3KooWabc123def456ghi789jkl012mno345pqr678stu901
Public Key: z12D3KooWabc123def456ghi789jkl012mno345pqr678stu901
Display: Enzo
Created: 2024-01-15 10:30:45 UTCifm config — Configuration Management
View and modify configuration.
ifm config <SUBCOMMAND> [OPTIONS]
SUBCOMMANDS:
show Show current config (merged)
get <KEY> Get config value
set <KEY> <VALUE> Set config value
reset <KEY> Reset to default
edit Open config in $EDITOR
validate Validate config file
EXAMPLES:
ifm config show
ifm config get network.bootstrap
ifm config set network.lan true
ifm config set gossip.fanout 8
ifm config edit
ifm config validateifm plugin — Plugin Management
Manage plugins.
ifm plugin <SUBCOMMAND> [OPTIONS]
SUBCOMMANDS:
list List loaded plugins
load <PLUGIN> Load plugin (path or name)
unload <PLUGIN_ID> Unload plugin
install <URL/PATH> Install plugin from npm/local
remove <PLUGIN_ID> Remove installed plugin
EXAMPLES:
ifm plugin list
ifm plugin load ./my-plugin.wasm
ifm plugin load @ifm/plugin-whiteboard
ifm plugin unload whiteboard
ifm plugin install https://plugins.ifm.network/whiteboard.wasmifm bootstrap — Run Bootstrap Node
Start a bootstrap node (for network operators).
ifm bootstrap [OPTIONS]
OPTIONS:
-p, --port <PORT> Listen port (default: 4001)
-k, --key <PATH> Identity key file
--no-quic Disable QUIC
--no-relay Disable circuit relay
--max-peers <N> Max connections (default: 1000)
--data-dir <PATH> Data directory
EXAMPLES:
ifm bootstrap
ifm bootstrap --port 4001 --key ./bootstrap.key
ifm bootstrap --max-peers 5000 --data-dir /var/lib/ifm-bootstrapifm version — Show Version
ifm version [OPTIONS]
OPTIONS:
--json Output as JSON
EXAMPLES:
ifm version
ifm version --jsonOutput:
ifm-cli 0.1.0 (protocol v1)
Rust: 1.75.0
Build: 2024-01-15T10:30:45Z
Git: abc123defShell Completion
Bash
ifm completion bash > /etc/bash_completion.d/ifm
# Or source directly
source <(ifm completion bash)Zsh
ifm completion zsh > ~/.zsh/completions/_ifm
# Add to .zshrc: fpath=(~/.zsh/completions $fpath)Fish
ifm completion fish > ~/.config/fish/completions/ifm.fishPowerShell
ifm completion powershell | Out-String | Invoke-Expression
# Add to profileEnvironment Variables
| Variable | Description | Default |
|---|---|---|
IFM_CONFIG | Config file path | ./config.toml |
IFM_DATA_DIR | Data directory | ./data |
IFM_IDENTITY | Identity key path | $IFM_DATA_DIR/identity.key |
IFM_LOG_LEVEL | Log level (trace, debug, info, warn, error) | info |
IFM_LOG_FORMAT | Log format (text, json) | text |
IFM_MANIFEST_URL | Deployed rendezvous manifest URL (remote mode entry point) | http://ifm-rendezvous.fly.dev/bootstrap.ifm.json |
IFM_LAN | Set to enable LAN mode (mDNS entry, no rendezvous) | unset |
NO_COLOR | Disable colors | - |
Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Invalid arguments |
| 3 | Not connected |
| 4 | Not tuned to frequency |
| 5 | Peer not found |
| 6 | Frequency not found |
| 7 | Invalid encryption key |
| 8 | Timeout |
| 9 | Permission denied |
| 10 | Storage error |
| 11 | Audio device error |
| 12 | Plugin error |
| 13 | Config error |
| 14 | Identity error |
Scripting Examples
Send Alert on Frequency
#!/bin/bash
# alert.sh - Send alert message
FREQ="alerts"
MSG="⚠️ Server disk usage at 95%"
ifm broadcast "$MSG" --frequency "$FREQ" --type json <<EOF
{
"type": "alert",
"level": "critical",
"message": "$MSG",
"source": "$(hostname)",
"timestamp": "$(date -Iseconds)"
}
EOFMonitor and Log
#!/bin/bash
# monitor.sh - Log all messages to file
ifm monitor --json | while IFS= read -r line; do
echo "$(date -Iseconds) $line" >> ifm-monitor.log
doneAuto-tune on Startup
#!/bin/bash
# startup.sh - Connect and join default frequencies
ifm connect --wait-peers 3
ifm tune 91.700
ifm tune chat.general
ifm tune weather.localHealth Check
#!/bin/bash
# health.sh - Exit with error if node unhealthy
STATS=$(ifm stats --json)
PEERS=$(echo "$STATS" | jq '.network.peers')
UPTIME=$(echo "$STATS" | jq '.uptime')
if [ "$PEERS" -lt 3 ]; then
echo "CRITICAL: Only $PEERS peers connected"
exit 2
fi
echo "OK: $PEERS peers, uptime ${UPTIME}s"
exit 0Configuration File (config.toml)
See Configuration Reference for full details.
[node]
name = "enzo"
storage = "./data"
relay = true
connections = 128
[network]
bootstrap = true
lan = true
quic = true
webrtc = true
[gossip]
ttl = 16
fanout = 6
[audio]
sample_rate = 48000
channels = 1
frame_ms = 20Man Pages
# Install man pages (Linux/macOS)
sudo ifm manpage | sudo tee /usr/local/share/man/man1/ifm.1 > /dev/null
man ifmTroubleshooting
"No peers found"
# Check bootstrap connectivity
ifm connect --bootstrap /ip4/bootstrap.ifm.network/udp/4001/quic-v1/p2p/12D3KooWBootstrap1
# Enable LAN discovery
ifm config set network.lan true"Permission denied" on audio
# Linux: Add user to audio group
sudo usermod -a -G audio $USER
# macOS: Grant microphone permission in System Preferences"Identity already exists"
# Force reinitialize
ifm init --force
# Or use different data dir
ifm --data-dir ./other-data initConnection timeout
# Increase timeout
ifm connect --timeout 60
# Check firewall - need UDP 4001 for QUIC
sudo ufw allow 4001/udpRelated Commands
ifm --help— Show all commandsifm <command> --help— Show command-specific helpifm version— Show version info