Skip to content

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

bash
# 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 PATH

Cargo

bash
cargo install ifm-cli

Homebrew

bash
brew install ifmprotocol/tap/ifm

Global Options

bash
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 version

Commands

ifm init — Initialize Node

Create identity and configuration for a new node.

bash
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-bootstrap

Output:

Generated identity: 12D3KooWabc123...
Config written to: ./config.toml
Identity stored at: ./data/identity.key

ifm connect — Connect to Network

Establish connection to the IFM mesh network.

bash
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 60

Output:

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.

bash
ifm disconnect

EXAMPLES:
  ifm disconnect

ifm tune — Join a Frequency

Tune to a frequency (join a channel).

bash
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 3

Output:

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.

bash
ifm leave <FREQUENCY>

EXAMPLES:
  ifm leave 91.700
  ifm leave chat.general

ifm broadcast — Send Message

Broadcast a message to all peers on a frequency.

bash
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 file

ifm send — Direct Message

Send a direct message to a specific peer.

bash
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 json

ifm speak — Voice Transmission

Start/stop voice transmission on a frequency.

bash
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 dB

ifm mute — Stop Voice

Stop voice transmission.

bash
ifm mute

EXAMPLES:
  ifm mute

ifm scan — Discover Frequencies

Scan for active frequencies on the network.

bash
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 --json

Output:

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 frequencies

ifm peers — List Connected Peers

Show peers on current or specific frequency.

bash
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 --json

Output:

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 time

ifm stats — Node Statistics

Display node statistics and health info.

bash
ifm stats [OPTIONS]

OPTIONS:
  --json              Output as JSON
  --watch             Continuous update (like top)

EXAMPLES:
  ifm stats
  ifm stats --json
  ifm stats --watch

Output:

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").

bash
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/cli implements the full plane: --serve / --off turn 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|metrics honor --json for scripting.

EXAMPLES:

bash
# 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 --off

Output (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-v1

JS 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 ms

Discovery (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:

bash
# 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 10

Output (select):

* relay1_K8k29c…  score=0.711 rtt=12ms
  relay1_7xQp2a…  score=0.402 rtt=38ms

When 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).

bash
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 stations

Station 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:

bash
# 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 --live

Output (announce):

✓ announced station ifm1_WbZBAzqe_ECd7tCyclc8R-66kMZcWgxYjW2KsoC8CPk
  IFM News — live
  channels: main:Main

Output (list):

ifm1_WbZBAzqe…  IFM News  [LIVE] live
    location: Berlin

1 station(s)

ifm monitor — Real-time Packet Monitor

Monitor packet flow in real-time.

bash
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.

bash
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 list

ifm identity — Identity Management

Manage node identity.

bash
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 qr

Output (show):

Identity
========

Peer ID:     12D3KooWabc123def456ghi789jkl012mno345pqr678stu901
Public Key:  z12D3KooWabc123def456ghi789jkl012mno345pqr678stu901
Display:     Enzo
Created:     2024-01-15 10:30:45 UTC

ifm config — Configuration Management

View and modify configuration.

bash
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 validate

ifm plugin — Plugin Management

Manage plugins.

bash
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.wasm

ifm bootstrap — Run Bootstrap Node

Start a bootstrap node (for network operators).

bash
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-bootstrap

ifm version — Show Version

bash
ifm version [OPTIONS]

OPTIONS:
  --json    Output as JSON

EXAMPLES:
  ifm version
  ifm version --json

Output:

ifm-cli 0.1.0 (protocol v1)
Rust: 1.75.0
Build: 2024-01-15T10:30:45Z
Git: abc123def

Shell Completion

Bash

bash
ifm completion bash > /etc/bash_completion.d/ifm
# Or source directly
source <(ifm completion bash)

Zsh

bash
ifm completion zsh > ~/.zsh/completions/_ifm
# Add to .zshrc: fpath=(~/.zsh/completions $fpath)

Fish

bash
ifm completion fish > ~/.config/fish/completions/ifm.fish

PowerShell

powershell
ifm completion powershell | Out-String | Invoke-Expression
# Add to profile

Environment Variables

VariableDescriptionDefault
IFM_CONFIGConfig file path./config.toml
IFM_DATA_DIRData directory./data
IFM_IDENTITYIdentity key path$IFM_DATA_DIR/identity.key
IFM_LOG_LEVELLog level (trace, debug, info, warn, error)info
IFM_LOG_FORMATLog format (text, json)text
IFM_MANIFEST_URLDeployed rendezvous manifest URL (remote mode entry point)http://ifm-rendezvous.fly.dev/bootstrap.ifm.json
IFM_LANSet to enable LAN mode (mDNS entry, no rendezvous)unset
NO_COLORDisable colors-

Exit Codes

CodeMeaning
0Success
1General error
2Invalid arguments
3Not connected
4Not tuned to frequency
5Peer not found
6Frequency not found
7Invalid encryption key
8Timeout
9Permission denied
10Storage error
11Audio device error
12Plugin error
13Config error
14Identity error

Scripting Examples

Send Alert on Frequency

bash
#!/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)"
}
EOF

Monitor and Log

bash
#!/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
done

Auto-tune on Startup

bash
#!/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.local

Health Check

bash
#!/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 0

Configuration File (config.toml)

See Configuration Reference for full details.

toml
[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 = 20

Man Pages

bash
# Install man pages (Linux/macOS)
sudo ifm manpage | sudo tee /usr/local/share/man/man1/ifm.1 > /dev/null
man ifm

Troubleshooting

"No peers found"

bash
# 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

bash
# Linux: Add user to audio group
sudo usermod -a -G audio $USER

# macOS: Grant microphone permission in System Preferences

"Identity already exists"

bash
# Force reinitialize
ifm init --force
# Or use different data dir
ifm --data-dir ./other-data init

Connection timeout

bash
# Increase timeout
ifm connect --timeout 60

# Check firewall - need UDP 4001 for QUIC
sudo ufw allow 4001/udp

  • ifm --help — Show all commands
  • ifm <command> --help — Show command-specific help
  • ifm version — Show version info

Released under the MIT License.