Files
MeshTerm/docs/cli.md
T
Jean-Pierre MartineauandClaude Opus 5 4a91845651 A manual for the command line, and two rules it caught us breaking
docs/cli.md documents every command and option, what each one prints, and
what it returns -- with the output conventions and the exit-status table
up front, since those are the two things a script is written against.
Every command, option and flag in it was checked against the running app;
the sample output is captured from the simulator rather than typed out.

Writing it turned up two places the CLI still did the thing the last
commit was about. A destructive command refused for want of --yes printed
its refusal in red on *stdout* and exited 1: a colour and a sentence that
is not the command's answer, in whatever was reading the command's answer.
A missing confirmation is a bad invocation, so it now goes through the
parser like any other -- nothing on stdout, the reason on stderr, exit 2.

The README keeps its cookbook and its summary of the conventions, and
points at the manual for the rest.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 01:17:26 -04:00

30 KiB

The MeshTerm command line

MeshTerm has two front ends over one codebase. The menu — what you get by running meshterm with no arguments — is a full-screen session meant to be read by a person. The CLI is meant to be read by awk.

This is the manual for the second one: what it prints, what it returns, and every command it answers to.


Running it

meshterm [GLOBAL OPTIONS] COMMAND [ARGS]

With no command, MeshTerm launches the interactive menu instead. Global options go before the command:

Option What it does
-p, --profile NAME Use a named device profile from config.toml.
--port PORT Serial port to connect to (COM5, /dev/ttyACM0), overriding the profile.
--ble ADDRESS Bluetooth address of a companion; selects the BLE transport.
--ble-pin PIN Pairing PIN, if the Bluetooth companion asks for one.
--tcp HOST[:PORT] Network address of a TCP companion; selects the TCP transport. Default port 5000.
--mock Use the built-in simulator instead of real hardware. Nothing transmits.
--db PATH Use this SQLite database instead of ~/.meshterm/meshterm.db.
--json Machine-readable output. Only devices and tx-optimize honour it; everything else is already parseable as plain text.
-q, --quiet Suppress console logging entirely (the log file still records).
--platform NAME Force the UI flavour (regular|picocalc) instead of detecting it.

Commands that need a radio open one, do their work, and close it. Commands that only read stored history (records) or MeshTerm's own state (preferences, about) need no device at all and work with nothing attached.

One transmission per invocation. A trace transmits exactly once — repeaters penalise, and can blacklist, nodes that burst traffic. To sample more, run the command again with your own pacing between runs.


Output conventions

The CLI prints like a standard Unix utility, and every rule below exists so its output can be piped somewhere without being cleaned up first.

No colour. Not a hue, not a bold, not a dim — stdout carries no escape sequence at all, whether or not it is a terminal. A colour that survives into a file is noise in it.

No wrapping. A record is a line. Wrapping would put half a record's fields under the wrong headings, so nothing folds: a long line runs off the right and your terminal (or less -S, or your pipe) decides what to do about it.

No frames. No borders, no boxes, no rules, no titles, no legends. The command you typed is the title.

Listings are an uppercase header line followed by space-aligned records, the shape ps and df print. Numeric columns right-align.

$ meshterm contacts
NAME              TYPE      HEARD                      PKTS  KEY
"Alice"           node      2026-09-07T19:58:54-04:00  12    d4e5f6a700000000000000000000000000000000000000000000000000000000
"Yagi-Repeater"   repeater  2026-09-07T19:58:53-04:00  97    a1b2c3d400000000000000000000000000000000000000000000000000000000

Node names are quoted. A name can hold a space, a comma, even a quote, so a bare name is not one field — it is however many fields the name happens to split into. Quotes and backslashes inside a name are escaped the ordinary way ("He said \"hi\""), so a quoted value reads back unambiguously.

Key/value blocks are a key, the gutter, and the rest of the line as its value — the shape sysctl -a prints. There is no header, and the value is not quoted: a line has exactly two fields, so the value is whatever follows the key.

$ meshterm info
name              MockCompanion
public_key        0000000000000000000000000000000000000000000000000000000000000000
role              companion
battery_v         4.10
uptime_s          93784
noise_floor_dbm   -110

A get prints the bare value alone, ready for $(...):

$ meshterm config get tx_power
20

Paths are quoted node names, each with its hash in parentheses outside the quotes, joined by a bare comma — the same comma --path takes:

"MockCompanion" (00),"Yagi-Repeater" (a1),"Alice" (d4),"Yagi-Repeater" (a1),"MockCompanion" (00)

Your own node is a hop like any other, named and hashed — never a ★. The hash is there because the CLI has no colour: on screen a route's hops are told apart by their key-derived hues, and in plain text the hash is what carries that identity. It is also what joins a route line to the per-hop table underneath it.

Times are absolute local ISO-8601 to the second — 2026-09-07T18:22:41-04:00 — never 3h ago. A relative age is for someone watching a screen; a script wants something it can sort and subtract.

- is the one token for nothing — absent, unknown, or not applicable. You learn it once; there is no —, no n/a, no never, no empty cell.

stdout is the answer; everything else is stderr. Errors print as meshterm: what went wrong. Progress bars draw on stderr too, and draw nothing at all when stderr is not a terminal. So meshterm contacts > contacts.txt puts contacts in the file and any complaint on your screen.


Exit status

The return value is half the report.

Code Meaning
0 Success.
1 Failure with no more specific code — a bad value, an unreadable file, an unhandled fault.
2 Usage error: an unknown flag, a missing argument, a value the parser rejected.
3 No companion device could be selected: none attached, none matching the connection flags, or the choice was ambiguous. Nothing was transmitted.
4 A device was reached but the operation failed — a command error, a timeout, a link lost mid-run. Retrying is reasonable.
5 The command completed and there was nothing to report: an empty list, a target that never answered, a conversation with no messages. stdout is empty. This is not an error.

The table is printed under meshterm --help as well.

5 is the one worth building on. grep conflates "found nothing" with "worked", and a caller that has to count output lines to tell an empty mesh from a full one is parsing when it could be branching:

if meshterm contacts > contacts.txt; then
    echo "$(($(wc -l < contacts.txt) - 1)) contacts"      # minus the header
elif [ $? -eq 5 ]; then
    echo "no contacts yet"
else
    echo "could not reach the radio" >&2
fi

3 and 4 split the failures a retry might fix from the ones it never will:

meshterm trace --target Alice
case $? in
  0) echo "reachable" ;;
  5) echo "no reply — the walk ran, nothing came home" ;;
  3) echo "no radio attached" >&2; exit 1 ;;
  4) echo "radio trouble — worth retrying" >&2; exit 1 ;;
  *) echo "failed" >&2; exit 1 ;;
esac

Command reference

Finding a device

meshterm devices

List every attached serial device and in-range Bluetooth companion. Opens no radio — it only enumerates what is attached or advertising.

Option What it does
--ble / --no-ble Include a Bluetooth LE scan. On by default; skipping it saves a few seconds.
$ meshterm devices --no-ble
TARGET  TRANSPORT  NAME                          HARDWARE                 MESHCORE  SERIAL            ACTIVE
COM12   serial     "USB Serial Device (COM12)"   "Adafruit"               maybe     D030D2CCD00F08EB  no
COM16   serial     "USB Serial Device (COM16)"   "Adafruit"               maybe     D8D7D4BB5E4546E0  no
COM1    serial     "Communications Port (COM1)"  "(Standard port types)"  no        -                 no

TARGET is what --port and --ble take, verbatim. MESHCORE is three-valued and stays that way: yes only once a connection has proved the device speaks the protocol, maybe for a USB vendor ID that suggests a LoRa board or a bridge chip, no for anything else — a vendor ID is a hint, and the column would be lying if it rounded one up.

Returns 5 when nothing is found.


This node

meshterm info

The connected companion's live status: which radio this is, and how it is doing.

$ meshterm info
name              MockCompanion
public_key        0000000000000000000000000000000000000000000000000000000000000000
role              companion
model             MeshCore Simulator
firmware          mock mock
battery_v         4.10
storage_used_kb   128
storage_total_kb  1024
clock             2026-09-08T01:05:09-04:00
clock_drift_s     -125
uptime_s          93784
noise_floor_dbm   -110
last_rssi_dbm     -62
last_snr_db       +9.5
tx_air_s          42
rx_air_s          360
packets_sent      210
packets_received  1234
receive_errors    3

The unit is in the key, so nothing has to be pulled back out of prose. A reading the firmware does not answer for is absent rather than -: a missing key says "this device does not report it", where a dash would claim it reported nothing.

What the radio is set to is config show's answer, not this one.

meshterm config

View and change every device setting. With no subcommand it runs show.

Subcommand What it does
show Print every setting as key value.
get KEY Print one setting's value, bare.
set KEY VALUE Change one setting.
backup PATH Write every setting to a TOML file.
restore PATH [--dry-run] Apply settings from a TOML backup. --dry-run prints the plan and changes nothing.
custom KEY VALUE Set an experimental custom variable.
channel INDEX NAME [--secret HEX] Configure a channel slot (see also the channels group).
advert [--flood] Broadcast an advertisement. Zero-hop unless --flood.
advert-cadence HOURS [--flood] How often to auto-advertise in the background. 0 disables.
share Print this node's contact card as a meshcore:// URI.
sync-clock Set the device clock from this computer.
export-key [--out PATH] Export the private key. Sensitive.
import-key KEY_HEX --yes Import a private key, overwriting this node's identity.
reboot --yes Reboot the device.
factory-reset --yes Erase all data and reset to defaults.
$ meshterm config show
name                 MockCompanion
adv_lat              0.0
adv_lon              0.0
device_pin           ••••••
radio_freq           869.618
radio_bw             62.5
radio_sf             8
radio_cr             5
tx_power             20
manual_add_contacts  false
flood_scope          ""
adv_loc_policy       0

show names each setting by the key get and set take, and prints a value they will take back — an enum's number, not the reader's label; "" for an empty string; - for something the firmware never reported. So a line read out of show can be typed straight back in:

$ meshterm config set radio_sf 9
$ meshterm config get radio_sf
9

The pairing PIN stays masked here, because this is the whole-device dump — the thing that gets redirected into a file and pasted into a bug report. Name it deliberately with meshterm config get device_pin.

Custom variables are namespaced custom.* in the output, since they have no spec and config set will not take them (use config custom).

Destructive operations are gated behind --yes rather than a prompt, so nothing surprising happens in a script. Without it the command is refused as a usage error — nothing on stdout, the reason on stderr, exit 2.


The mesh around you

meshterm contacts

The contacts your device knows.

Option What it does
-s, --sort ORDER heard (default), name, or packets.
$ meshterm contacts --sort name
NAME              TYPE      HEARD                      PKTS  KEY
"Alice"           node      2026-09-07T19:58:54-04:00  12    d4e5f6a700000000000000000000000000000000000000000000000000000000
"Local-Repeater"  repeater  2026-09-07T19:58:53-04:00  48    b2c3d4e500000000000000000000000000000000000000000000000000000000

TYPE is the node's advertised role in words — node, repeater, room, sensor, or unknown. PKTS is how many packets passive monitoring has overheard from it. KEY is the full public key, never elided: a truncated key is not something you can hand back to --to or --path.

This lists contacts only. Your own node is not a contact — meshterm info reports it, in far more detail than a row could hold.

Returns 5 when the device knows no contacts yet.

meshterm monitor

Capture overheard packets in the foreground for a bounded window, then summarise it. Transmits nothing; it only listens. Recording to history is always on anyway — this adds the live view.

Option What it does
-s, --seconds N How long to capture. 0 (the default) runs until Ctrl-C.
$ meshterm monitor --seconds 3
TIME  NODE  NAME  SNR_DB  RSSI_DBM  LAT  LON
2026-09-08T01:07:25-04:00  a1b2c3d4  "Yagi-Repeater"  +7.0  -101  45.50190  -73.56740
2026-09-08T01:07:25-04:00  c3d4e5f6  "Observer-Bot"  +4.9  -93  -  -

NODE      NAME              PKTS  MEDIAN_SNR_DB  BEST_SNR_DB  RSSI_DBM  LAST_HEARD
c3d4e5f6  "Observer-Bot"    54    +5.2           +12.4        -108      2026-09-08T01:07:33-04:00
a1b2c3d4  "Yagi-Repeater"   48    +5.1           +12.8        -100      2026-09-08T01:07:33-04:00

Two blocks, separated by a blank line. The stream is a header and then a record per packet as it arrives; it cannot be column-aligned, because the widths are not known until it ends, so its fields are gutter-separated and the name carries its quotes. The summary is the aggregate the stream cannot give — a count, a median, a best per node — most recently heard first.

Returns 5 when the window heard nothing.

meshterm records

The record-setting walks every trace has been scored against. Reads the database; needs no device and never transmits.

Option What it does
-c, --category ID One discipline: long_haul, far_point, long_leg, grand_tour, clean_trail, thin_thread, big_loop.
-w, --width N Only records set at this per-hop hash width (1, 2, or 4).
$ meshterm records --category long_haul --width 2
CATEGORY   WIDTH  SCORE  UNIT  RECORDED                   VERSION  ROUTE
long_haul  2      273.0  km    2026-08-17T18:14:28-04:00  0.2.8    "Yagi-Repeater" (a1b2),"Alice" (d4e5),"Yagi-Repeater" (a1b2)
long_haul  2      112.0  km    2026-09-03T17:46:10-04:00  0.2.8    "Local-Repeater" (b2c3),"Alice" (d4e5),"Local-Repeater" (b2c3)

SCORE is a bare number and UNIT is its own column, so the scores in a column are comparable. A Longest-distance score prefixed >= is a lower bound: some hop on that walk has no known position, so the distance is a floor rather than a measurement.

Records are kept per hash width, because the width bounds both a walk's maximum length and its collision odds — boards at different widths are measuring different games.

Returns 5 when no records match.


Messaging

meshterm chat

Subcommand What it does
send TEXT --to NAME Send a direct message.
send TEXT --channel N Broadcast on a channel slot.
history [--to NAME | --channel N] [--limit N] Print a conversation's stored transcript. Default limit 50.
list Every channel and contact with its unread count and last message.
listen [-s SECONDS] [--debug] Tail inbound messages live.

Exactly one of --to and --channel is required on send and history.

$ meshterm chat send "on my way" --to Alice
acked  yes

A direct message prints its acked state, which is the one thing the send does not already tell you — the radio accepted it either way, and whether the peer answered is a separate fact. A channel broadcast prints nothing: there is no acknowledgement on a channel, so the exit status is the whole answer.

$ meshterm chat history --to Alice
TIME                       DIRECTION  PEER     SNR_DB  TEXT
2026-09-08T01:07:41-04:00  out        "Alice"  -       on my way
2026-09-08T01:09:02-04:00  in         "Alice"  +6.4    see you there

DIRECTION is in or out; PEER is always the other party. TEXT is last and unquoted — it is the rest of the line, and a message body is the one field that can hold absolutely anything.

$ meshterm chat list
CONVERSATION      KIND     UNREAD  LAST_TIME                  LAST_TEXT
"Public"          channel  0       -                          -
"Alice"           direct   2       2026-09-07T19:58:54-04:00  see you there

listen prints a header and then a record per message as it arrives, the same shape monitor's stream takes. --debug routes the message-pull logging to stderr, for working out whether messages are being pulled from the companion at all.

history, list and listen return 5 when there is nothing to report.

meshterm channels

Subcommand What it does
list The configured channel slots.
add INDEX NAME [--secret HEX] Add a channel. A leading # makes it public (the firmware derives the key from the name); otherwise it is private, with a random key unless you give one.
join INDEX NAME SECRET Join a channel from its name and 32-hex-character key.
import INDEX URL Import a meshcore://channel/add link.
share INDEX Print a slot's share link.
clear INDEX --yes Clear a slot, removing the channel from the device.
$ meshterm channels list
SLOT  NAME        TYPE     HASH
0     "Public"    public   8f
1     "brigade"   private  2c

share prints the meshcore:// URI alone. (The menu draws a QR code beside it; redirected into a file that is a block of block characters wrapped around the one thing that is actually the answer.)

clear is gated behind --yes because a private channel's key is lost with the slot unless it is saved elsewhere.

list returns 5 when no slots are configured.

meshterm courier

A store-and-forward outbox: queue a message for a contact that is not reachable right now, and it goes out the moment the contact is next heard — or at a time you name.

Subcommand What it does
queue CONTACT TEXT… [--at HH:MM] Queue a message. --at holds it until the next occurrence of that local time.
list The outbox: waiting entries then finished ones.
send ID Force one delivery attempt now, skipping the "wait until heard" check.
cancel ID Remove a waiting entry.
clear Drop every finished (delivered / given-up) entry.
$ meshterm courier queue Alice "ping me when you are back" --at 18:30
id  10

$ meshterm courier list
ID  STATE      NODE       SCHEDULED                  FINISHED                   TEXT
10  waiting    "Alice"    2026-09-08T18:30:00-04:00  -                          ping me when you are back
8   delivered  "Bob"      -                          2026-08-11T18:10:17-04:00  Courier test!

queue prints the entry's id, which is the one fact you have to keep: it is what send and cancel take. An entry with no SCHEDULED time goes as soon as the contact is heard.

$ meshterm courier send 10
outcome  delivered

outcome is one of delivered, no ack, gave up, unknown contact, busy, gone.

The sending is done by a running interactive session's courier; a queued message sits in the outbox until one runs.

list returns 5 on an empty outbox; cancel and clear return 5 when there was nothing to act on.


Tracing

meshterm trace

Walk the path to a target once and report what came back.

Option What it does
-t, --target NAME Required. Target node name or key prefix.
-p, --path SPEC Force a route: comma-separated contact names and/or hex key prefixes, mixed freely (3d,f2,3d). Omit it and the device routes.
$ meshterm trace --target Alice
target      Alice
path        auto
success     yes
hops        3
min_snr_db  +2.6
rtt_ms      459
route       "MockCompanion" (00),"Yagi-Repeater" (a1),"Alice" (d4),"MockCompanion" (00)

HOP  FROM  TO  SNR_DB
0    00    a1  +6.0
1    a1    d4  +2.6
2    d4    00  +5.1

Two blocks. The first is what the walk did, route among the facts. The second is a record per hop, naming its two ends by the hash rather than repeating the names: the route line above is where the names are, and the hash is what joins the two blocks. path reads auto when the device routed it — every real value there is comma-separated hex.

A trace that never came home is not a failure of the command: the radio transmitted and the walk ran. It reports success no and returns 5.

meshterm trace-path

The other half of tracing: no target, just a route you compose by hand — out and back whichever way you choose. It only has to end within earshot of this node.

Option What it does
-p, --path SPEC Required. The whole walk, comma-separated.
$ meshterm trace-path --path "a1,d4,a1"
target      -
path        a1,d4,a1
success     yes
hops        4
min_snr_db  +2.0
rtt_ms      458
route       "MockCompanion" (00),"Yagi-Repeater" (a1),"Alice" (d4),"Yagi-Repeater" (a1),"MockCompanion" (00)

HOP  FROM  TO  SNR_DB
0    00    a1  +6.0
1    a1    d4  +2.0
2    d4    a1  +2.4
3    a1    00  +6.0

target is - because a path walk has none. Walks record under a sentinel so they stay out of the target picker's history.

meshterm tx-optimize

Sweep a remote node's transmit power against a target and pick the lowest level that still gets through reliably.

Option What it does
-p, --path SPEC Required. Forced path ending at the target (Repeater,Target, or 3d,f2). The hop before the target is the node being tuned.
-n, --samples N Traces per TX level. Default 3.
--step N Coarse sweep step. Default 3.
--min N / --max N Bound the sweep (else the tx_opt_min / tx_opt_max preferences).
--password TEXT Admin password for the tuned node; else the remembered one, else prompted.
--apply / --no-apply Set the winner on the node. On by default.
$ meshterm tx-optimize --path "Yagi-Repeater,Alice" --samples 5
tuning_node      Yagi-Repeater
target           Alice
path             a1,d4
optimal_tx_dbm   22
target_snr_db    +4.1
reliability      1.00
previous_tx_dbm  27
applied          yes

TX_DBM  TARGET_SNR_DB  SUCCESSES  SAMPLES
    18           -1.2          2       5
    21           +2.8          5       5
    22           +4.1          5       5

The winner comes first because it is what you asked for; the per-level records follow so the choice can be checked against the measurements it was made from. This transmits many times (paced by the trace_cooldown_s preference) — it is the one command that is not a single transmission.

Returns 5 when no trace reached the target at any level: nothing was measured, and the node was left at its original power.


Other nodes

meshterm repeater-admin

Send one command to a remote repeater or room server over the mesh and print its reply.

meshterm repeater-admin NODE COMMAND... [--password TEXT]
Argument / option What it does
NODE The remote contact's name.
COMMAND... The text command to send, as the node's own CLI spells it.
--password TEXT Admin password; else the one remembered from an interactive login.
$ meshterm repeater-admin Yagi-Repeater get name
Yagi-Repeater

The reply is printed as the node sent it — its own text, and the whole answer. A node that does not answer is not a failure (the command may well have landed), but there is nothing to report, so it returns 5.

Logging in happens automatically from the remembered password; run the interactive flow once to store one, or pass --password. A refused login clears the saved password and fails with 4.


MeshTerm itself

meshterm preferences

How MeshTerm behaves, as opposed to how the radio is configured. Reads nothing from the companion, transmits nothing, and works with no device attached.

Subcommand What it does
show Every preference, its value, and its built-in default.
get KEY One preference's value, bare.
set KEY VALUE Change one preference.
reset --yes Return every preference to its default.
$ meshterm preferences show
PREFERENCE                   VALUE                                 DEFAULT
trace_cooldown_s             5                                     5
flood_advert_cooldown_s      5                                     60
map_view_fraction            0.5                                   0.5
history_days                 365                                   365

Values print in the form preferences set accepts back — no unit suffix on a number, on/off for a boolean. Where VALUE differs from DEFAULT, this install has an override.

Overrides live in ~/.meshterm/preferences.yaml, which lists only what you have changed; delete a line and the default takes over again.

meshterm about, about-author, discord, support

The four written pages, printed as plain text. about is what MeshTerm is and the terms it ships under; about-author is who wrote it; discord is the community invite; support is what keeps it going.

$ meshterm discord
Join the Discord
  Questions, ideas, bug reports, and mesh talk.

  • https://discord.gg/AZwe5Uvb3S

The menu draws a QR code beside each link; the scripted face prints the link alone.

meshterm platform

A diagnostic for which UI flavour a given invocation resolves to, and why.

$ meshterm platform
platform           regular
platform_source    default
flag               -
env                -
device_tree_model  -
icons              yes
icons_source       no-console

icons is a separate question from the flavour, and the usual reason a Windows session looks plainer than the screenshots.

meshterm specimen

Print the visual-language specimen — every mark, icon, colour scale and fold on one card.

This is the one command that keeps its colour, and it builds its own themed console to do it. That is deliberate: the colour is the output. It is the font-and-palette acceptance card on the PicoCalc console, and with --platform picocalc it previews that flavour from a desktop. A monochrome specimen would test nothing.


Recipes

Watch a node and shout if it goes quiet. trace returning 5 means the walk ran and nothing came home.

#!/usr/bin/env bash
target=${1:?usage: watch NODE}
meshterm trace --target "$target" > /dev/null
status=$?          # capture it first: `if ! cmd` would have reset $? to 0
if [ "$status" -eq 5 ]; then
    echo "$target did not answer" | mail -s "mesh alert" me@example.com
fi

Nightly config archive, keeping the path the command actually wrote:

out=$(meshterm config backup "$HOME/mesh/$(date +%F).toml") && echo "archived $out"

config backup prints the file it wrote, bare and one per line, so the path comes back to the caller.

Fields out of a listing. Names are quoted, so a CSV-aware reader is the safe way in; awk works when you split on the quotes rather than on spaces.

# every repeater's key
meshterm contacts | awk 'NR > 1 && $0 ~ /repeater/ { print $NF }'

# names alone, quotes stripped
meshterm contacts | awk -F'"' 'NR > 1 { print $2 }'

One value into a variable:

sf=$(meshterm config get radio_sf)
[ "$sf" -lt 9 ] && meshterm config set radio_sf 9

Capture a window of traffic to a file, with the progress noise left on the terminal:

meshterm monitor --seconds 300 > /var/log/mesh-$(date +%s).tsv

Sample a trace politely. A trace transmits exactly once per invocation by design; pace the repeats yourself:

for i in $(seq 5); do
    meshterm trace --target Alice --path "3d,f2,3d"
    sleep "$(meshterm preferences get trace_cooldown_s)"
done

Queue for someone who is offline, then chase it later:

id=$(meshterm courier queue Alice "call me" | awk '{print $2}')
# ... later ...
meshterm courier send "$id"

Cron-friendly quiet: --quiet suppresses console logging entirely, leaving only the command's own output and any error line.

*/30 * * * * meshterm --quiet --profile yagi config advert --flood

What has no command

Some features have no scripted face, and that is the honest answer rather than a degraded one. Each of these is a live picture — its meaning is where things sit on a grid, how they move, and what colour they are — and none of that survives being turned into records.

Feature Why not, and what to use instead
Map A drawing of braille cells whose nodes are told apart by colour. Stripped of colour to match the rest of the CLI it would be unreadable; left coloured it could not be piped anywhere useful. meshterm contacts lists the same nodes, coordinates and all.
Dashboard A live overview that repaints every second. meshterm monitor captures the same traffic as records.
Live feed Every packet as it arrives, newest first, with a viewer behind each row. meshterm monitor is the scripted tail.
Watchtower A background sentinel over starred nodes; it exists to interrupt a session. Build the same alarm from meshterm trace's exit status (see Recipes).
Time machine Braille charts over a switchable window. The underlying history is in the database --db points at.
Mesh walk An evidence graph walked one node at a time. meshterm records and meshterm trace cover the walks it is built from.

Everything else in the menu has a command, listed above.