CLI Reference

All 28 commands, flags, output formats, and gotchas

Every command supports --help for exhaustive flag listings. This page documents subcommands, key flags, and gotchas you won’t find in --help.

API legend: I = Integration API (API key). L = Session API (API key on UniFi OS, or username/password). H = Works in any mode, enriched when session HTTP access exists.

πŸ”—Commands

CommandAliasAPIDescription
devicesdev, dHManage adopted and pending devices
clientsclHManage connected clients and DHCP reservations
networksnet, nIManage networks and VLANs
wifiwIManage WiFi broadcasts (SSIDs)
firewallfwMixedManage firewall policies, zones, and groups
natLManage NAT policies (masquerade, SNAT, DNAT)
aclIManage ACL rules
dnsIManage DNS policies (local records)
traffic-listsIManage traffic matching lists
hotspotIManage hotspot vouchers
vpnMixedView VPN inventory, session site-to-site, remote-access, and client VPN records, OpenVPN helpers, connections, WireGuard peers, magic site-to-site configs, and VPN settings
eventsLView and stream events
alarmsLManage alarms
statsLQuery statistics and reports
sitesLManage sites
adminLAdministrator management
systemsysMixedSystem operations and info
settingsLRead and write site-level settings sections
topologytopoHShow network topology tree
dpiMixedDPI reference data and control
radiusIView RADIUS profiles
wansIView WAN interfaces
countriesIList available country codes
cloudCloudQuery the Site Manager fleet (consoles, sites, devices, ISP, SD-WAN)
configLocalManage CLI configuration
completionsLocalGenerate shell completions
apiLRaw API passthrough (GET/POST/PUT/PATCH/DELETE any endpoint)
tuiHLaunch the real-time terminal dashboard

List commands default to 25 rows. Pass --all or --limit 200 for complete results.

πŸ”—Devices

unifly devices list                             # All adopted devices
unifly devices list --filter "state.eq('Online')"  # Filter by status
unifly devices get <ID|MAC>                     # Device details
unifly devices pending                          # Devices awaiting adoption
unifly devices adopt <MAC>                      # Adopt a pending device
unifly devices remove <ID|MAC>                  # Unadopt a device
unifly devices restart <ID|MAC>                 # Restart
unifly devices locate <MAC> --on true           # Flash LED (--on false to stop)
unifly devices port-cycle <ID|MAC> <PORT>       # Power-cycle a PoE port
unifly devices stats <ID|MAC>                   # Real-time device stats
unifly devices upgrade <MAC>                    # Trigger firmware upgrade
unifly devices provision <MAC>                  # Force re-provision config
unifly devices speedtest                        # WAN speed test (gateway only)
unifly devices tags                             # List device tags

Gotchas: restart, locate, upgrade, provision, speedtest, and port-cycle require Session API access. list and get work with any auth mode but return richer data when session HTTP access exists (client count, uplink MAC).

πŸ”—Switch Ports (config-as-code)

unifly devices ports <ID|MAC>                   # Current port config
unifly devices ports <ID|MAC> --with-clients    # Annotate with connected clients
unifly devices ports-export <ID|MAC>            # Export overrides as JSONC
unifly devices ports-export <ID|MAC> --all      # Include every port
unifly devices port-set <ID|MAC> 5 --mode access --native-vlan IoT
unifly devices port-set <ID|MAC> -F ports.jsonc # Apply a JSONC file
unifly devices port-set <ID|MAC> 5 --reset      # Back to controller defaults

Port indices are 1-based, matching the controller’s wire format. port-set -F accepts a JSONC payload (comments and trailing commas allowed) with splice semantics: ports not listed keep their existing override, and a per-port "reset": true removes that port’s override entirely. --with-clients adds connection annotations, and on ports-export it prepends // last-seen <timestamp>: <mac> comment lines for git-diff drift detection. See Switch Ports for the full workflow and payload schema.

πŸ”—Clients

unifly clients list                             # Connected clients
unifly clients list --type wireless             # Filter by type
unifly clients find "ring-doorbell"             # Search by name, IP, or MAC
unifly clients get <MAC>                        # Client details
unifly clients reservations                     # All DHCP reservations
unifly clients set-ip <MAC> --ip 10.0.10.50    # Create DHCP reservation
unifly clients set-ip <MAC> --ip 10.0.10.50 --network <ID>  # Scoped to network
unifly clients remove-ip <MAC>                  # Remove DHCP reservation
unifly clients block <MAC>                      # Block from connecting
unifly clients unblock <MAC>                    # Unblock
unifly clients kick <MAC>                       # Force reconnection
unifly clients authorize <MAC> --minutes 60     # Authorize guest access
unifly clients unauthorize <MAC>                # Revoke guest access
unifly clients forget <MAC>                     # Remove from client history
unifly clients roams <MAC>                      # Roaming history for a client
unifly clients wifi <MAC>                       # WiFi experience details for a client

Gotchas: list returns enriched data in Hybrid mode (traffic bytes, hostname, wireless, VLAN). block/unblock/kick/forget and DHCP reservation commands require Session API.

πŸ”—Networks

unifly networks list                            # All networks/VLANs
unifly networks get <ID>                        # Full network details
unifly networks create --name "IoT" --management gateway --vlan 20 --ipv4-host "10.0.20.1/24"
unifly networks create -F network.json          # Create from JSON file
unifly networks update <ID> --enabled false
unifly networks delete <ID>
unifly networks refs <ID>                       # What depends on this network?

Gotchas: list returns summary data without ipv4Configuration. Use get for full config. refs is the only pre-delete dependency check; use it before deleting.

πŸ”—WiFi

unifly wifi list                                # All SSIDs
unifly wifi get <ID>                            # SSID details
unifly wifi create --name "Guest" --network <ID> --security wpa2-personal --passphrase "..."
unifly wifi create -F wifi.json                 # Create from JSON file
unifly wifi update <ID> --enabled false
unifly wifi delete <ID>
unifly wifi neighbors                           # Scan nearby APs (RF environment)
unifly wifi channels                            # Channel utilization analysis

Gotchas: Serde defaults to PascalCase for enums in --from-file JSON. Use "Wpa2Personal" not "wpa2_personal". The --security flag on the CLI accepts kebab-case (wpa2-personal). neighbors and channels are read-only observability commands that query Session API data.

πŸ”—Firewall

πŸ”—Policies

unifly firewall policies list
unifly firewall policies get <ID>
unifly firewall policies create --name "Block IoT" --action block \
  --source-zone <ID> --dest-zone <ID>
unifly firewall policies create -F policy.json
unifly firewall policies update <ID> -F policy.json
unifly firewall policies patch <ID> --enabled false    # Quick toggle
unifly firewall policies patch <ID> --logging true     # Toggle logging
unifly firewall policies delete <ID>
unifly firewall policies reorder --source-zone <ID> --dest-zone <ID> --get
unifly firewall policies reorder --source-zone <ID> --dest-zone <ID> --set <ID1,ID2,...>

Gotchas: patch is the fast path for toggling enabled/logging only. Use update for other fields. reorder with --get shows current order; --set applies a new order. First-match wins, so ordering matters.

πŸ”—Zones

unifly firewall zones list
unifly firewall zones get <ID>
unifly firewall zones create --name "IoT Zone" --networks <ID1,ID2>
unifly firewall zones create -F zone.json
unifly firewall zones update <ID> --networks <ID1,ID2>
unifly firewall zones delete <ID>

πŸ”—Groups

unifly firewall groups list
unifly firewall groups list --type port-group
unifly firewall groups get <ID>
unifly firewall groups create --name "Web Ports" --type port-group --members "80,443,8000-8002"
unifly firewall groups create --name "IoT Nets" --type address-group --members "10.0.30.0/24"
unifly firewall groups update <ID> --members "80,443"
unifly firewall groups delete <ID>

Gotchas: groups use the Session API (rest/firewallgroup), not Integration; an API key on UniFi OS is sufficient. Types: port-group (default), address-group, ipv6-address-group. The external_id UUID in group responses is what firewall policies reference. Policy create/update resolve group names for you via --src-port-group / --dst-port-group / --src-address-group / --dst-address-group flags (or dst_port_group / dst_address_group shorthand fields in --from-file JSON).

πŸ”—NAT

unifly nat policies list
unifly nat policies get <ID>
unifly nat policies create --name "Masquerade" --type masquerade --interface-id <ID>
unifly nat policies create -F nat.json
unifly nat policies update <ID> --name "New Name" --enabled true
unifly nat policies delete <ID>

Use nat policies update <ID> to modify an existing rule. Pass any combination of --name, --type, --enabled, address/port flags, or --from-file. Only the specified fields are changed.

NAT types: masquerade (outgoing interface address), source (explicit rewrite), destination (port forwarding/DNAT). NAT routes through the Session v2 API: an API key on UniFi OS is sufficient, and session-only profiles work too (nat policies list populates from the session refresh snapshot). Only pure-Integration setups without session HTTP access cannot manage NAT.

πŸ”—ACL

unifly acl list
unifly acl get <ID>
unifly acl create --name "Block printer" --rule-type ipv4 --action block \
  --source-zone <ID> --dest-zone <ID>
unifly acl create -F acl.json
unifly acl update <ID> -F acl.json
unifly acl delete <ID>
unifly acl reorder --get                        # Current order
unifly acl reorder --set <ID1,ID2,...>          # Apply new order

πŸ”—DNS

unifly dns list
unifly dns get <ID>
unifly dns create --record-type a --domain "nas.home" --value "10.0.10.5"
unifly dns create -F dns.json
unifly dns update <ID> -F dns.json
unifly dns delete <ID>

Supported record types: a, aaaa, cname, mx, txt, srv, forward. The --record-type values are lowercase; uppercase A is rejected by argument parsing. Table output displays the familiar short uppercase names (A, AAAA, …).

πŸ”—Traffic Lists

unifly traffic-lists list
unifly traffic-lists get <ID>
unifly traffic-lists create --name "Ad servers" --list-type ipv4 --items "1.2.3.4,5.6.7.8"
unifly traffic-lists create -F list.json
unifly traffic-lists update <ID> -F list.json
unifly traffic-lists delete <ID>

List types: ports, ipv4, ipv6. Referenced by firewall policies, NAT, and ACLs.

πŸ”—Events

unifly events list                              # Recent events (last 24h)
unifly events list --within 4                   # Events from last 4 hours
unifly events list --limit 100                  # More results
unifly events watch                             # Live event feed (WebSocket)
unifly events watch --types Device              # Filter by category
unifly events watch --types Device,Client       # Multiple categories

The --types flag accepts EventCategory values (case-insensitive): Device, Client, Network, System, Admin, Firewall, Vpn, Unknown.

--types takes category names, not EVT_* glob patterns. Use Device not EVT_SW_*.

πŸ”—Statistics

unifly stats site                               # Site-level stats
unifly stats device                             # Per-device bandwidth
unifly stats client                             # Per-client stats
unifly stats gateway                            # Gateway stats (WAN, uptime)
unifly stats dpi                                # DPI application breakdown
unifly stats dpi --group-by by-cat              # Group by category
unifly stats gateway --interval 5m              # High-resolution data
unifly stats site --interval daily              # Long-term trends

Supported intervals: 5m (high resolution), hourly (default), daily, monthly.

πŸ”—Hotspot

unifly hotspot list
unifly hotspot get <ID>
unifly hotspot create --name "Day Pass" --count 10 --minutes 1440
unifly hotspot delete <ID>
unifly hotspot purge --filter "status.eq('EXPIRED')"  # Bulk delete

πŸ”—Admin

unifly admin list                               # List site administrators
unifly admin invite --name "Alex" --email "alex@example.com" --role admin
unifly admin revoke <ADMIN_ID>                  # Positional, not --email
unifly admin update <ADMIN_ID> --role readonly

Gotcha: revoke takes a positional admin ID, not an email flag.

πŸ”—Alarms

unifly alarms list                              # All alarms
unifly alarms list --unarchived                 # Active alarms only
unifly alarms archive <ID>                      # Archive one alarm
unifly alarms archive-all                       # Archive everything

πŸ”—DPI

unifly dpi apps                                 # List known applications (Integration)
unifly dpi categories                           # List known categories (Integration)
unifly dpi status                               # Current DPI state (Session)
unifly dpi enable                               # Turn on DPI (Session)
unifly dpi disable                              # Turn off DPI (Session)

πŸ”—System

unifly system info                              # Application version (Integration)
unifly system health                            # Site health summary (Session)
unifly system sysinfo                           # Controller system info (Session)
unifly system backup create                     # Create backup
unifly system backup list                       # List backups
unifly system backup download <FILENAME>        # Download backup
unifly system backup delete <FILENAME>          # Delete backup
unifly system reboot                            # Reboot hardware (UDM only)
unifly system poweroff                          # Power off hardware (UDM only)

reboot and poweroff are destructive and require confirmation (-y to skip).

πŸ”—VPN

unifly vpn servers                              # List VPN servers (Integration)
unifly vpn tunnels                              # List site-to-site tunnels (Integration)
unifly vpn status                               # Live IPsec tunnel status
unifly vpn health                               # VPN subsystem health
unifly vpn site-to-site list                    # List site-to-site VPN records
unifly vpn site-to-site get <ID>                # Inspect one site-to-site VPN record
unifly vpn site-to-site create -F vpn.json      # Create a site-to-site VPN
unifly vpn site-to-site update <ID> -F vpn.json # Update a site-to-site VPN
unifly vpn site-to-site delete <ID>             # Delete a site-to-site VPN
unifly vpn remote-access list                   # List remote-access VPN servers
unifly vpn remote-access get <ID>               # Inspect one remote-access VPN server
unifly vpn remote-access create -F vpn.json     # Create a remote-access VPN server
unifly vpn remote-access update <ID> -F vpn.json # Update a remote-access VPN server
unifly vpn remote-access suggest-port           # Suggest available OpenVPN ports
unifly vpn remote-access download-config <ID>   # Download an OpenVPN client config
unifly vpn remote-access delete <ID>            # Delete a remote-access VPN server
unifly vpn clients list                         # List configured VPN clients
unifly vpn clients get <ID>                     # Inspect one configured VPN client
unifly vpn clients create -F vpn.json           # Create a configured VPN client
unifly vpn clients update <ID> -F vpn.json      # Update a configured VPN client
unifly vpn clients delete <ID>                  # Delete a configured VPN client
unifly vpn connections list                     # List VPN client connections
unifly vpn connections get <ID>                 # Inspect one VPN client connection
unifly vpn connections restart <ID>             # Restart one VPN client connection
unifly vpn peers list [SERVER_ID]               # List WireGuard peers, optionally by server
unifly vpn peers get <SERVER_ID> <ID>           # Inspect one WireGuard peer
unifly vpn peers create <SERVER_ID> -F peer.json # Create a WireGuard peer
unifly vpn peers update <SERVER_ID> <ID> -F peer.json # Update a WireGuard peer
unifly vpn peers delete <SERVER_ID> <ID>        # Delete a WireGuard peer
unifly vpn peers subnets                        # List subnets already used by peers
unifly vpn magic-site-to-site list              # List magic site-to-site VPN configs
unifly vpn magic-site-to-site get <ID>          # Inspect one magic site-to-site VPN config
unifly vpn settings list                        # List VPN-related site settings
unifly vpn settings get teleport                # Inspect one VPN setting
unifly vpn settings set teleport --enabled true # Toggle a VPN setting
unifly vpn settings patch peer-to-peer -F peer.json   # Apply a JSON payload

Gotchas: servers and tunnels are read-only Integration API inventory; everything else is Session-backed and works with an API key on UniFi OS. Create and update for site-to-site, remote-access, clients, and peers are payload-driven: build the JSON with --from-file (see the examples/ templates). Sensitive material such as WireGuard private keys and IPsec pre-shared keys is redacted in both get and create output; reconstruct those fields explicitly in update payloads if the controller requires them unchanged. The full walkthrough lives on the VPN page.

πŸ”—Settings

unifly settings list                            # All site setting sections
unifly settings get dpi                         # One section
unifly settings set dpi enabled true            # Patch one field
unifly settings set usg --data '{"mss_clamp": "auto"}'  # Merge a JSON object
unifly settings export                          # Full JSON dump of every section

Site-level settings live in Session API setting sections. set performs a read-modify-write of the whole section, and get masks x_-prefixed secret fields in table mode (-o json shows everything). Session-gated: needs an API key on UniFi OS or session credentials. Details on the Site Settings page.

πŸ”—Cloud (Site Manager)

unifly cloud hosts                              # Consoles visible to the API key
unifly cloud sites                              # Sites across the fleet
unifly cloud devices                            # Devices across all consoles
unifly cloud devices --host <ID>                # Scope to one console
unifly cloud isp                                # ISP metrics
unifly cloud sdwan                              # SD-WAN configs
unifly cloud switch <SITE>                      # Point the cloud profile at a site

cloud talks directly to the Site Manager fleet API at api.ui.com with a Site Manager API key; no controller connection is involved. With auth_mode = "cloud", regular Integration-backed commands (networks list, firewall policies list, …) tunnel through the cloud connector to one console. Set up with unifly config cloud-setup; the full story is on the Cloud & Site Manager page.

πŸ”—Other Commands

unifly topology                                 # Network tree visualization
unifly radius profiles                          # List RADIUS profiles
unifly wans list                                # List WAN interfaces
unifly sites list                               # List sites
unifly sites create --name "Branch Office"      # Create site
unifly sites delete <NAME>                      # Delete site
unifly countries                                # Country codes for WiFi regulatory

πŸ”—Raw API

Escape hatch for any controller endpoint. Routes through the Session client with automatic CSRF handling.

unifly api api/s/default/stat/sitedpi                    # GET a session endpoint
unifly api v2/api/site/default/nat                       # GET a v2 endpoint
unifly api api/s/default/stat/stadpi -m POST -d '{"type":"by_app"}'  # POST
unifly api api/s/default/set/setting/teleport -m PUT -d '{"enabled":true}'      # PUT
unifly api integration/v1/sites/<site-id>/hotspot/vouchers/<id> -m DELETE       # DELETE

πŸ”—Configuration

unifly config init                              # Interactive setup wizard
unifly config cloud-setup                       # Guided Site Manager (cloud) profile
unifly config show                              # Show resolved config
unifly config set auth_mode hybrid              # Set a config value
unifly config set-password                      # Store password in keyring
unifly config set-password --profile office     # For a specific profile
unifly config profiles                          # List profiles (* = active)
unifly config use <PROFILE>                     # Switch default profile

Valid config set keys: controller, site, auth_mode, api_key, api_key_env, host_id, host_id_env, username, insecure, timeout, ca_cert. auth_mode accepts integration, session, hybrid, or cloud (legacy is normalized to session).

πŸ”—--from-file / -F

Most create/update commands accept -F <file.json> to read the request body from a JSON file. This is the preferred approach for complex payloads.

Accepted by: networks, wifi, firewall policies, firewall zones, firewall groups, nat policies, acl, dns, traffic-lists, vpn site-to-site, vpn remote-access, vpn clients, vpn peers, vpn settings patch, and devices port-set (JSONC for switch port config-as-code).

JSONC is accepted everywhere: comments and trailing commas are stripped before parsing.

unifly networks create -F network.json
unifly firewall policies create -F policy.json

See examples/ for payload templates.

πŸ”—List Filtering (--filter)

--filter on list commands is evaluated client-side and supports exactly one expression, with three operators:

unifly devices list --filter "state.eq('Online')"
unifly clients list --filter "name.contains('ring')"
unifly networks list --filter "vlan.in('20','30','40')"

Field paths address the JSON output shape (dot notation for nesting). An unparseable expression matches nothing and exits 0, so a silent empty result usually means a typo in the filter, not an empty collection.

The full server-side Integration filter DSL (neq, gt/lt, startswith, &&/||) applies only to hotspot purge --filter, which passes the expression to the controller.

πŸ”—Capturing Created IDs

Create commands print the created entity on stdout in the requested output format, with the human confirmation line on stderr. That makes ID capture a one-liner:

NET_ID=$(unifly networks create --name "IoT" --vlan 30 \
  --management gateway --ipv4-host "10.0.30.1/24" -o json | jq -r '.id')

# -o plain emits just the new ID
ZONE_ID=$(unifly firewall zones create --name "IoT Zone" -o plain)

sites create is the exception: the controller returns no record to print. VPN create output has sensitive fields (private keys, PSKs) redacted, same as get.

πŸ”—Global Flags

-p, --profile <NAME>     Controller profile to use
-c, --controller <URL>   Controller URL (overrides profile)
-s, --site <SITE>        Site name or UUID
-o, --output <FORMAT>    Output: table, json, json-compact, yaml, plain
-k, --insecure           Accept self-signed TLS certs (--insecure=false forces verification)
-v, --verbose            Increase verbosity (-v, -vv, -vvv)
-q, --quiet              Suppress non-error output
-y, --yes                Skip confirmation prompts
    --timeout <SECS>     Request timeout (default 30, profiles may override)
    --color <MODE>       Color: auto, always, never
    --no-cache           Force fresh login (bypass session cache)
    --api-key <KEY>      Integration API key (one-shot override)

--insecure is tri-state: absent defers to the profile and [defaults], -k / --insecure accepts self-signed certificates, and --insecure=false forces verification no matter what the config says. The explicit value requires the equals form (--insecure false does not parse). --timeout has no baked-in flag default; when the flag and UNIFI_TIMEOUT are absent, the profile’s timeout wins, then [defaults], then the built-in 30 seconds.

πŸ”—Output Formats

FormatFlagBest For
Table-o tableHuman reading (default)
JSON-o jsonScripting, agent use
Compact JSON-o json-compactLine-oriented processing, pipes
YAML-o yamlConfig-style output
Plain-o plainIDs for xargs pipelines
# Pipe plain IDs into another command
unifly clients list -o plain | xargs -n1 unifly clients get

πŸ”—Next Steps