Management CLI: <tt>prf-mgmt</tt>

prf-mgmt is the host-side tool that talks to PacketRF nodes. It is the only management front-end the project ships, and it is intended to be the comfortable, day-to-day way to operate a device. There is no telnet, no proprietary GUI, no hidden side channel: every management operation goes through the same authenticated CoAP/CBOR command tree, and prf-mgmt is what speaks it on the host side.

This page is a tour. If you are bootstrapping a fresh device for the first time, Quick Start is the right place to be. If you want the operational manual — what to configure, in what order, for an actual NPR deployment — that is in PacketRF Operating Guide.

What it is

prf-mgmt is a Python 3.11+ CLI built on top of a small library that implements the PacketRF control protocol — request envelope encoding in CBOR, COSE-signed writes against the device's rotating nonce, response signature verification against a local trust store, schema discovery, and so on. The library is also what host-side automation (scenario scripts, hardware-in-the-loop tests) uses internally.

What you see at the command line is mostly a wrapper that:

  1. opens a transport — local USB serial framing, or CoAP UDP — based on the --uri you give it,
  2. encodes your request,
  3. signs it with one of your local admin keys if the operation requires authentication,
  4. parses the response, optionally verifies the device's response signature against the trusted-device store,
  5. prints something readable.

There are two transports today and the tool does not care which one you use. The same /system/status, the same /interface/list, the same config writes — only the --uri changes.

Installing it

Three reasonable installation paths, listed roughly in order of convenience for different audiences.

From a release wheel (recommended for users)

The release artifacts on GitHub include a Python wheel named packetrf_mgmt-<version>-py3-none-any.whl. The clean way to install it is with pipx, which puts the tool in its own isolated environment and exposes it on your $PATH:

pipx install ./packetrf_mgmt-<version>-py3-none-any.whl

If you prefer to install directly from a published asset URL:

pipx install "packetrf-mgmt @ https://github.com/slintak/PacketRF/releases/download/v<version>/packetrf_mgmt-<version>-py3-none-any.whl"

Or in a regular virtualenv if that fits your habits better:

python -m venv .venv
. .venv/bin/activate
python -m pip install ./packetrf_mgmt-<version>-py3-none-any.whl

After install, prf-mgmt --help should return a usage summary.

From repository sources (developer workflow)

The host-side code lives under tools/mgmt/. The fastest way to get an interactive shell from a source checkout is:

make mgmt

That target runs uv sync --project tools/mgmt and starts an interactive prf-mgmt shell with the local serial URI auto-detected. Single commands without entering the shell:

uv run --project tools/mgmt prf-mgmt --help

The convention used in the rest of the documentation is to write plain prf-mgmt … commands. If you are running from sources, prepend uv run --project tools/mgmt and they are otherwise identical.

The two transports

--uri selects the transport:

  • serial:/dev/ttyACM0 — local USB serial management framing. Use this for first-boot bootstrap and for benchwork without an IP path to the device.
  • coap://192.168.42.1 — CoAP over UDP, port 5683. This is the normal transport once the device is on the network. It works over any interface the device exposes — USB CDC-NCM, Ethernet, or even over the NPR radio link itself.

The serial transport is point-to-point with one device. The CoAP transport is plain UDP and you can talk to several devices in sequence by changing the URI; nothing keeps state between calls.

If you forget to pass --uri, the tool either prompts you (in interactive shell mode) or prints an error pointing you at it.

Admin keys

PacketRF requires authenticated control writes, and the authentication is done with Ed25519 keys held on the host. The first key on a fresh device is installed during bootstrap; afterwards, prf-mgmt uses it (or any other admin key) to sign write requests.

Generate a key — once, not once per device:

prf-mgmt admin-key generate default

The name (default) is a local alias. You can have many. Keys are stored under ~/.config/packetrf/. That directory is your admin credential. Treat it the way you would treat ~/.ssh: do not lose it, do not commit it to git, do not paste it into a chat asking for help.

To use a specific admin key in a command:

prf-mgmt --uri coap://192.168.42.1 --admin-key default \
         /interface/np2/set callsign=OKnABC-PRF

The --admin-key flag is only required for write requests. Read-only paths (/system/status, /interface/list, /interface/<iface>/config without arguments, /schema) work without it.

The command tree

The command paths in prf-mgmt are the same paths the firmware publishes through /schema — slash-separated, exactly as they appear on the wire. There are no shortened CLI verbs; what you type at the prompt is what hits the device.

The convention to keep in mind:

  • read paths usually end in /status (live runtime data) or /config (configured values, no arguments),
  • write paths usually end in /set and take key=value arguments,
  • shared system endpoints live under /system/*,
  • per-interface endpoints under /interface/<iface>/*,
  • crypto and bootstrap endpoints under /crypto/*.

The exact authoritative listing is whatever prf-mgmt /schema returns from the running device. The shape below is stable enough to plan from.

FamilyPurposeExamples
/system/*Health, telemetry, reboot, schema id/system/status, /system/mem, /system/reboot
/interface/*Per-interface status and configuration/interface/list, /interface/np2/status, /interface/np2/set
/crypto/*Device public key, keyring, bootstrap install/crypto/device, /crypto/bootstrap/install
/schemaActive command tree of the running firmware/schema
admin-keyLocal admin key store on the host (no device contact)admin-key generate, admin-key list
script, shellRun scenario files / enter an interactive REPLscript foo.mgmt, shell
bootstrapConvenience wrapper for /crypto/bootstrap/installbootstrap 1000

The last three rows do not start with a slash because they are not device-side paths; they are host-side commands implemented entirely by prf-mgmt. Everything that is a device-side path looks like its on-wire form.

A handful of useful invocations to keep handy:

# Health check across the device
prf-mgmt --uri coap://192.168.42.1 /system/status
prf-mgmt --uri coap://192.168.42.1 /system/mem

# What interfaces are up, in what mode, with what addresses
prf-mgmt --uri coap://192.168.42.1 /interface/list

# Drill into the NPR side
prf-mgmt --uri coap://192.168.42.1 /interface/np2/status
prf-mgmt --uri coap://192.168.42.1 /interface/np2/config

# Edit a config key (note: /set, not /config)
prf-mgmt --uri coap://192.168.42.1 --admin-key default \
         /interface/np2/set modulation_id=22

# Get the device public key — useful when adding it to a host
# trust store, or when comparing what the device reports against
# what your host already trusts.
prf-mgmt --uri coap://192.168.42.1 /crypto/device

# Clean reboot
prf-mgmt --uri coap://192.168.42.1 --admin-key default /system/reboot

Interactive shell

prf-mgmt shell opens a REPL that holds the URI and admin-key selection between commands. It is the most pleasant way to work with a single device for any length of time:

$ prf-mgmt --uri coap://192.168.42.1 --admin-key default shell
prf> /system/status
…
prf> /interface/np2/status
…
prf> /interface/np2/set modulation_id=22
…

The shell understands the same commands as the non-interactive form and supports tab completion driven by the device's published schema.

Scenario scripts

Repetitive configuration — the kind you do every time you set up a master, or every time you bring a slave back from a factory reset — fits naturally into a small script. PacketRF ships a handful of example scenarios under scenarios/:

  • scenarios/dump-all-configs.mgmt
  • scenarios/configure-us0-from-np2-dhcp.mgmt

A scenario is a plain text file:

  • one command per line,
  • # introduces a comment, including inline at the end of a line,
  • blank lines are ignored,
  • execution stops on the first error.

Run one with:

prf-mgmt --uri coap://192.168.42.1 --admin-key default \
         script scenarios/dump-all-configs.mgmt

make exposes a couple of common scenarios as named targets, which can be useful for keyboard automation:

make bootstrap CODE=0110 ADMIN_KEY=default
make mgmt-cmd CMD="/system/status"

Response signing and trust

When the device has identity available, it signs responses as COSE_Sign1 and includes a kid (the device's key identifier) in the protected headers. prf-mgmt can verify those signatures against a host-side trusted-device store. If the device is unknown to your host, the tool will say so — that is by design, the same way SSH says "the authenticity of host can't be established" the first time you connect.

During the very first bootstrap, response signing is usually unverified — your host has no prior trust anchor for the device yet. That is expected. Add the device key to your host trust store after bootstrap to verify signed responses afterwards.

Troubleshooting first-day issues

A short list of things that bite people on day one and what to do about them.

  • **prf-mgmt: command not found** after a pipx install: your shell has not picked up the pipx bin path yet. Run pipx ensurepath and start a new shell.
  • No serial device shows up: check the serial path under /dev/. On Linux a freshly bootstrapped device is usually /dev/ttyACM0. If your user is not in the right group (dialout on most distros), opening it will fail with a permission error.
  • CoAP commands time out but serial works: confirm the device's IP from interface list over serial, and check that your host's routing actually goes through the right interface. The factory USB address is 192.168.42.1, but if you have multiple PacketRF devices on USB simultaneously they all want the same address — that is a host-side conflict, not a device fault.
  • Write fails with nonce_required or nonce_stale: the device rotated the nonce while you were typing. Just retry — the tool fetches the current nonce automatically before signing.
  • Write fails with unauthorized: the admin key you are using is not in the device's keyring with the admin flag. Either pick a different --admin-key, or add this key through an existing admin session.

Where to look next