Commands¶
beebo is a single Typer application. Along with the global transport options (-u/--usb, -b/--ble, -t/--tcp) described in Install and Connect, there is a set of subcommands (status, settings, admin, ota, trace, discover, contacts, messages, neighbors, rxlog, monitor, check, clock, config, analyze, ...) that act on whichever node is connected. The same global flags are reused by every subcommand, so once a transport is chosen it stays consistent across the whole session.
Every command and option is listed in the CLI Reference, which is generated from the command line itself. Some commands have a page of their own:
| Command | Documented in |
|---|---|
settings |
Settings |
monitor |
Monitoring |
check |
Health Check |
analyze, rxlog --compare |
Analysis |
ota, admin ... transport |
Update and Service a Node |
battery |
Battery State and Calibration |
measure |
RF Experiments |
Overview¶
Running beebo --help on its own lists the global transport options and every top-level command:
$ beebo --help
Usage: beebo [OPTIONS] COMMAND [ARGS]...
CLI for Heltec ESP32-S3 V4.3 MeshCore Beebo Nodes.
╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --ble -b ADDRESS Connect via BLE to ADDRESS ('scan' to discover).│
│ --tcp -t HOST Connect via TCP to HOST[:port]. │
│ --usb -u PORT Connect via USB serial PORT. │
│ --raw -r Force the plain-text CommonCLI protocol instead │
│ of the companion binary protocol. │
│ --log-level -l LEVEL Logging level: DEBUG, INFO, WARNING, ERROR, │
│ CRITICAL. [default: WARNING] │
│ --profile / --no-profile Enable CLI level command profiling. │
│ --interactive -i Open a 'beebo() -> ' prompt; `connect` and │
│ `release` manage the device session explicitly. │
│ --version -v Show version and exit. │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ admin Remote node administration authorization and commands. │
│ advert Send a direct or flood advert. │
│ analyze Offline analysis of downloaded data. │
│ battery Battery monitoring and management. │
│ channels Manage a companion's group channels and the shared channels.json. │
│ check Health status and service quality dashboard. │
│ clock Show the device's time and drift from host, or set it explicitly. │
│ config Save, list, diff, and apply named device configurations. │
│ connect Connect the -i session's device (only inside -i). │
│ contacts Show or refresh the local contact cache. │
│ discover Probe the mesh for nodes and show responders type and SNR. │
│ measure RF bench measurements: noise floor, BW sweep, TX-power curves. │
│ messages Download pending messages, or send a new one. │
│ monitor Health and service monitoring management and dashboard. │
│ neighbors List and manage the node's direct neighbors. │
│ ota Upload a firmware image to the node over the air. │
│ profile Command runtime and latency profiling. │
│ reboot Reboot the node and synchronize time. │
│ region Region management for repeater flood scoping. │
│ release Disconnect the -i session's device (only inside -i). │
│ run Curated and user-provided use-case scripts. │
│ rxlog Capture received packets and summarize their SNR / RSSI. │
│ settings Show or set a node preference by dotted path. │
│ status Runtime node, radio, resource status. │
│ trace Trace the path to a target, printing each hop's SNR. │
│ traffic Inject flood group traffic on a channel. │
╰──────────────────────────────────────────────────────────────────────────────╯
Host CLI and node console¶
The beebo command line runs on a computer. The node also answers a text console, in the
beebo-cli channel and the CLI screen of a MeshCore app and on USB, so a phone alone can
check and tune a node. The console uses the words of the command line, so the same name does
the same thing in both places. This table lists every command and where it runs.
A reply on the app's CLI screen is cut at 160 characters; the beebo-cli channel splits a
longer one into up to four parts. The console answers in plain text: no tables, charts or
files, which stay on the host.
| Command | Host CLI | Node console | Node form and limits |
|---|---|---|---|
settings |
yes | yes | settings <path> [value], settings, settings <branch>. The paths with a plain value: trial, routing, radio, FEM, battery, node and board settings. The composite settings (radio.lora.*, coordinates, regions), secrets, console.* and the --reboot option are host only; monitor.* is the monitor capture command on the node |
status, status node, status radio, status resources |
yes | yes | one line each; bare status is the three lines |
check |
yes | partly | QoS and SoH verdicts with the CLI's bands and wording; the battery, tuning and settings checks are host only |
config check |
yes | no | |
monitor |
yes | yes | capture state and ring fill |
monitor status, ... health, ... service, ... rates |
yes | yes | the host prints the Health Status, Service Status and Service Rates tables; the node prints name=value lines of the counters that are not zero |
monitor start, monitor stop, monitor clear |
yes | yes | |
monitor capture [leaf on\|off] |
yes | yes | leaves enabled, rx, tx, radio, env, batt, tuning, event (also setting, command, route, debug, the same bit) and path |
monitor events |
yes | no | |
monitor tuning trial, ... start [switch...\|all], ... stop |
yes | yes | repeater role. start enables the named switches and turns the trial on, as on the host. The other trial subcommands are the settings routing.tuning.trial.* paths |
monitor tuning trial * |
yes | no | the other trial subcommands (profile, enable, values, score, block_size_s, ...) are the settings routing.tuning.trial.* paths |
monitor tuning, monitor tuning adaptive |
yes | no | the adaptive settings are settings paths |
monitor pull, monitor decode, monitor list, monitor debug, monitor watch, monitor plot * |
yes | no | records, charts and streams |
analyze * |
yes | no | works on downloaded files |
battery state [state] |
yes | yes | reads, or forces the charge classifier to charging, discharging, charged, plugged or unknown (a test aid, RAM-only, refused while battery.present is no) |
battery calibrate |
yes | yes | battery calibrate <volts> applies the voltmeter reading at once, on the node and on the host. On the host, without a reading it asks for one |
clock |
yes | yes | the node prints its own time; drift against the host, setting a time and --boot need the host |
reboot |
yes | yes | |
advert flood, advert direct |
yes | yes | flood reaches the whole mesh, direct (zero-hop) only the nodes in radio range. The node's bare advert floods, the stock meaning; on the host a bare advert is direct. Use the explicit forms |
neighbors |
yes | yes | repeater role: the node lists its live table, as neighbors peek does on the host |
neighbors peek, neighbors forget, neighbors discover |
yes | yes | repeater role: peek lists the live table, forget <hex> prunes one entry (the host also takes names and comma lists), discover [-t type]... sends the request and the answers appear in neighbors peek (the host also has --resolve, --timeout, --passive) |
neighbors ping, probe, poke, resolve, promote, pull, update, remove |
yes | no | the probes wait for replies, the rest keep files on the host |
region tree, region allow, region deny, region put, region remove, region save, region def |
yes | yes | repeater role, the node's own region command |
profile, profile clear |
yes | no | |
ota |
yes | no | the upload is the host's job; start ota on the node opens the receiver |
admin *, discover, trace |
yes | no | active mesh requests |
channels *, contacts *, messages *, traffic * |
yes | no | the app handles channels, contacts and messages |
config * |
yes | no | files and prompts on the host |
measure *, rxlog, run * |
yes | no | bench tools and scripts |
connect, release |
yes | no | the host session |
ver |
no | yes | firmware version and build date |
The older text commands (get, set, ver, reboot, clock, region, ...) keep working on the
node. Phone Feed shows the console in use.
Interactive mode and completion¶
Add -i/--interactive to connect once and open a beebo(<name>) -> prompt instead of running a single command: every line typed there is dispatched over that same connection (history and tab completion via prompt_toolkit), until Ctrl-D or exit/quit disconnects. beebo run (curated scripts shipped in the package, plus anything dropped in scripts_dir, default ~/.beebo/scripts — see beebo run --list) is built the same way every other command is, so a script run from inside -i reuses the live connection automatically; the same script also runs standalone (e.g. cron'd on a Raspberry Pi) without going through beebo at all.
Beebo supports shell autocompletion out of the box (standard Typer --install-completion, for bash/zsh/fish) — run it once and tab-completion covers every command and option:
$ beebo --install-completion
bash completion installed in /home/<user>/.bash_completions/beebo.sh
Completion will take effect once you restart the terminal
That installed script only wires up completion for the literal beebo
command, though -- symlinking a device alias (ln -s $(which beebo)
gatto picks up its own ~/.beebo/nodes/gatto/profile.toml) doesn't get tab
completion for free, since Click derives the completion trigger from
sys.argv[0]'s basename (_GATTO_COMPLETE for a gatto symlink, not
_BEEBO_COMPLETE). Run --install-completion again through each alias
you use and Typer generates that alias's own correctly-named file the
same way:
$ gatto --install-completion
bash completion installed in /home/<user>/.bash_completions/gatto.sh
Node status and control¶
Each command has its own --help. For example, status:
$ beebo status --help
Usage: beebo status [OPTIONS] COMMAND [ARGS]...
Runtime node, radio, resource status.
╭─ Options ────────────────────────────────────────────────────────────────────╮
│ --timing Print per-command round-trip latency to diagnose which │
│ query dominates. │
│ --help -h Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────╯
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ node Identity (name, role, model, version, build, transport), uptime, │
│ battery, MCU temp. │
│ radio Noise floor, last RSSI/SNR, TX/RX airtime. │
│ resources Heap/PSRAM/flash usage, MCU temp, contacts, pending messages, │
│ MonRing state. │
╰──────────────────────────────────────────────────────────────────────────────╯
Running beebo status with no subcommand prints the node, radio and resources sections (packet counters are under beebo monitor status) against our example companion node:
$ beebo status
Node
╭────────────┬─────────────────────────────────────╮
│ Name │ Beebo │
│ Role │ companion │
│ Model │ Heltec V4.3 Headless │
│ Version │ 1.18.0.beebo.1.0 │
│ Build │ 22 Sep 2026 │
│ Device ID │ f8:5b:1b:be:d1:ec │
│ Transport │ tcp │
│ WiFi RSSI │ -58 dBm │
│ Uptime │ 6h 49m 38s │
│ PWR Supply │ 4.400 V ⚡ Plugged │
│ MCU Temp │ 50.9 °C │
│ SoH │ 100.0% │
╰────────────┴─────────────────────────────────────╯
Radio
╭─────────────┬─────────╮
│ Noise Floor │ -85 dBm │
│ Last RSSI │ -99 dBm │
│ Last SNR │ -9.2 dB │
│ TX Airtime │ 1 s │
│ RX Airtime │ 3057 s │
╰─────────────┴─────────╯
Resources
╭──────────┬─────────────────────────────────────╮
│ Memory │ █████████████████░░░ (512 kB) │
│ PSRAM │ ██████████░░░░░░░░░░ (2.0 MB) │
│ Storage │ ██████████████░░░░░░ (16.0 MB) │
│ Time │ █░░░░░░░░░░░░░░░░░░░ (100%) │
│ Busy │ rx 4.10% / tx 0.02% / lx 0.31% / │
│ │ sys 1.20% / idle 94.37% │
│ Loop │ 41,200/s, max 12ms │
│ Contacts │ 350 │
│ Messages │ 255 awaiting read │
│ MonRing │ 14,800 / 65,536 records (capturing) │
╰──────────┴─────────────────────────────────────╯
beebo status node (or radio, resources) prints just one section. Packet counters and the drop/fault totals are under beebo monitor status (health, service or rates prints one table).
reboot— reboot the node and synchronize its clock. No options.advert flood,advert direct— send a self advert to the whole mesh, or zero-hop to the nodes in radio range. A bareadvertsends a direct one.clock— showDevice/Sourcefrom the connection's own auto-sync (see Auto Time Sync) with no extra round trip;clock TIMEsets the device clock to an explicit epoch instead;--bootforces an immediate corrective reboot if the device is found ahead (the RTC cannot go backwards).ota <firmware.bin>— upload a firmware image over the air (see Update and Service a Node for the full procedure, chunking, and progress display).--priority/--no-prioritycontrols whether the node skips radio dispatch during the transfer (every transport; on by default).
Battery¶
How the state is derived, and how to calibrate the ADC, is on Battery State and Calibration.
battery state reports the raw BATT_STATE_* classifier value from BattTrend.h alongside the rendered symbol, separately from status node, since the two can disagree while a trend is settling:
$ beebo battery --help
Usage: beebo battery [OPTIONS] COMMAND [ARGS]...
Battery monitoring and management.
╭─ Commands ───────────────────────────────────────────────────────────────────╮
│ state Voltage, the raw BATT_STATE_* classifier state from BattTrend.h, │
│ and the symbol `status node` would render. Give VALUE to force │
│ the state instead of just reading it. │
│ calibrate Measure Vbat with a voltmeter and calibrate board.adc.multiplier. │
╰──────────────────────────────────────────────────────────────────────────────╯
battery calibrate reads the node's currently-reported voltage and board.adc.multiplier, asks for a real voltmeter reading at the Vbat JST pigtail (defaulting to 4.2V, the V4.3 regulator's charge setpoint, which a fully charged battery sits at — accepting the default recalibrates against the reported-vs-expected gap with no meter in hand, so charge the battery fully and set board.battery.present to yes first), and solves for the new multiplier linearly. Given the reading as an argument (battery calibrate 4.18) it applies it at once, as the node console does; --yes/-y skips the prompts for scripted/cron use. It's also the first beebo run use-case script (beebo run calibrate-vbat, same command either way) and doubles as a standalone script — see beebo run --list.
Identity and saved configurations¶
Identity management lives under beebo config, alongside the rest of the
node-identity and profile management (beebo config --help lists all of these).
config identity— show the device's current identity (public key), or replace it withimport FILE, or save it withexport [FILE]/save. WithoutFILE,export(and itssaveshorthand) writes toBEEBO_ROOT/nodes/<node>/identity.json, the node's own directory in the config fs layout ($BEEBO_ROOTis~/.beeboby default).generate [FILE]creates a brand new Ed25519 keypair purely locally (no device connection) and saves it the same way — pair it with a separateimport FILEto apply it to a device. Replacing the identity invalidates every contact's cached shared secret on the device and changes the hash the node is known by on the mesh — existing peers see it as a new, unrecognized node until they re-hear its advert. The table below lists the subcommands.
| Command | Example | What it does |
|---|---|---|
config identity |
beebo config identity |
Print the connected device's current public key and name. |
config identity export [FILE] [--role ROLE] |
beebo config identity export --role repeater |
Save the device's keypair to FILE (default BEEBO_ROOT/nodes/<node>/identity.json). |
config identity save [--role ROLE] |
beebo config identity save |
Shorthand for export with no FILE. |
config identity import FILE [--role ROLE] [--yes] |
beebo config identity import backup.json |
Replace the device's identity with a saved keypair. |
config identity generate [FILE] [--role ROLE] |
beebo config identity generate --role companion |
Generate a brand-new keypair locally (no device connection) and save it. |
config create ROLE NAME [--copy EXISTING] |
beebo config create repeater gatto |
Generate a fresh named identity purely locally, under nodes/NAME/. |
config switch NAME [--yes] |
beebo -t gatto config switch gatto |
Apply a saved named identity to the connected board (import keypair + set name + role-switch-if-needed + reboot, atomic). |
config list [KIND] |
beebo config list nodes |
List saved configs, templates, backups and/or nodes (named identities). |
config delete KIND NAME [--role ROLE] [--yes] |
beebo config delete node old-name |
Delete one saved config, template, backup or node. |
config show NAME [PATH] |
beebo config show gatto repeater.radio |
Print a saved configuration's values (offline), optionally narrowed to a settings path. |
config pull [NAME] [PATHS...] [--role ROLE] [--factory] |
beebo config pull |
Snapshot the live device's settings into a named file (default <node>-<role>); --factory also writes verified firmware defaults as a validation template. |
config diff [NAME] [PATHS...] [--role ROLE] |
beebo config diff |
Compare a saved configuration against the live device. |
config push [NAME] [PATHS...] [--role ROLE] [--confirm] |
beebo config push |
Apply a saved configuration to the live device (--confirm asks per changed setting). |
config onboard [SAVE_AS] [--against TEMPLATE] [--default] |
beebo config onboard |
Guided first-time setup, prompting through each templated setting. |
config check [--role ROLE] [--against TEMPLATE] [--fix] |
beebo config check |
Validate live settings against a template's [ranges]/[defaults] (default factory), optionally auto-fixing. |
config backup [NAME] [--note TEXT] |
beebo config backup |
Password-gated snapshot of every secret (WiFi/repeater/guest passwords) plus settings, to devices/<board>/recovery/. |
config recover NAME |
beebo config recover 2026-08-20T10-00-00 |
Restore a device from a prior config backup snapshot. |
--role companion|repeater|all on pull, diff, push and check targets that role's persisted settings without switching board.node.role. PATHS are dotted settings-path prefixes (for example board repeater.routing) restricting what is captured, compared or applied; when given, NAME must be given first.
Guided setup and saved configurations¶
Once connected over USB or BLE (WiFi needs its credentials first, from the app or the command line, see Install and Connect), the fastest way to configure a fresh device
is beebo config onboard — a guided, question-driven wizard that
walks through node name, role (companion/repeater), a LoRa region preset,
the repeater admin password (forced if it's still the firmware's public
default), and WiFi/TCP provisioning, defaulting every question to the
device's current value so it's also safe to re-run later as a review:
$ beebo -u /dev/ttyACM0 config onboard
beebo onboard -- guided setup. Press Enter to keep the current value;
safe to re-run on an already-configured device.
Node name [beebo]: gatto
Node role [companion/repeater] (companion): repeater
Set a LoRa region preset? (current: (custom)) [y/n]: n
The repeater admin password is still the firmware's built-in default --
that default is public and known, so this isn't optional.
New repeater.admin.password: ********
Confirm new repeater.admin.password: ********
Set a guest password too? [y/n]: n
Enable WiFi (TCP transport)? [y/n]: y
WiFi SSID [myssid]: myssid
Set/change the WiFi password? [y/n]: y
New companion.node.wifi.password: ********
Confirm new companion.node.wifi.password: ********
Setup complete.
Save this as a named configuration? [y/n]: y
Configuration name: home-repeater
Saved as 'home-repeater': 41 setting(s) captured, 2 secret(s) skipped.
That last save step is the other half of beebo config: a saved
name captures the whole (role-filtered) settings tree and can later be
compared or re-applied to any device —
$ beebo -t gatto config diff home-repeater # what's changed since?
$ beebo -t gatto config push home-repeater # push it back
$ beebo -t gatto config check # sanity/completeness check-up
$ beebo config list # every saved configuration
NAME is optional on pull/diff/push -- it defaults to
<node_name>-<role>, built from whatever device you're connected to.
config push only writes settings that actually differ, batched
into a single flash write where the firmware supports it, and offers to
reboot at the end only if something it changed actually needs one.
config check is the settings-only half of beebo check — unset
owner info, a LoRa setup matching no known preset, a still-default admin
password, that sort of thing — worth running before handing a repeater off.
beebo check adds the live health verdicts (delivery, battery, tuning).
The wizard drives the same one-setting-at-a-time beebo settings commands
shown in Settings — use those directly for scripting, or for
anything the wizard doesn't ask about (beebo settings --help covers the full
tree).
Regions¶
| Command | Example | What it does |
|---|---|---|
region tree |
gatto region tree |
Show the region hierarchy (green = flood-allowed, red = flood-denied, ★ = home). |
region put NAME [PARENT] |
gatto region put pnw |
Define a region, or re-parent an existing one. |
region remove NAME |
gatto region remove pnw |
Remove a region (must have no children). |
region allow NAME |
gatto region allow pnw |
Allow flood traffic tagged with this region to be relayed. |
region deny NAME |
gatto region deny pnw |
Deny (stop relaying) flood traffic tagged with this region. |
region def SEGMENTS |
gatto region def "west pnw|pdx wa|kls or wv,sle" |
Bulk-define a region subtree in one round trip. |
region save |
gatto region save |
Explicitly persist the region tree (every other subcommand already auto-persists). |
beebo settings repeater.node.region.home (home region) and
repeater.node.region.default (default region) are reached through
Settings, not region — region itself only manages the
RegionMap tree/flood-policy structure.
Mesh discovery and routing¶
discover [filter]— probe the mesh for nodes and show each responder's type and link SNR.filternarrows by node type (all, an int mask, or a comma list ofcli/rep/room/sens);--timeoutsets how long to wait for stragglers,--fullrequests full 32-byte public keys instead of prefixes.
$ beebo discover rep,room --timeout 8
trace <target> — trace the path to a target (contact name, public-key hex prefix, or a raw path) and print each hop's SNR.
- neighbors — the node's own RAM-only table of everything heard via a zero-hop advert (CMD_GET_NEIGHBORS), independent of the saved contact list — useful because auto-add is usually off on a busy mesh, so a real immediate neighbor often isn't a saved contact yet. Subcommands: discover (send a direct advert, wait, then list what was heard), pull (re-query the table, merge it into neighbors.json and list the merged view), peek (the live RAM table only, without the cache), resolve <id> (request a neighbor's name/owner string), probe <id> (zero-hop reachability check of one neighbor), promote <id> (save a neighbor as a node contact), remove <id> (delete a previously promoted contact), forget <id> (prune an entry from the neighbor table itself, RAM-only, mirrors the text CLI's neighbor.remove), plus ping and poke (see below). beebo contacts refresh also merges these neighbors into the resolver cache and promotes fresh ones automatically.
- contacts — list (offline, from the local contacts.json cache) or refresh (contacts refresh, re-queries the node and merges) the contact list, with heavy filtering (--name, --hash, --type, --neighbors, --active/--inactive, --located, --near KM, --collisions) and sort/group options for large meshes. contacts active <target> (or --off) flags a cached node reachable/unreachable by hand; contacts remove <name|hash>... deletes contacts from the node (--all removes every one, --yes skips the prompt), including ones that are not direct neighbors; contacts free-1b lists unused 1-byte hash prefixes, handy when hand-picking a distinguishable node name. Backs the neighbor-name resolution used by rxlog, discover, trace, and others.
beebo neighbors update — complete partial neighbors from a node directory¶
A neighbor heard only through a control or relayed packet is saved in neighbors.json with just a 1-3 byte key prefix, no name and no location. beebo neighbors update completes those entries from a mesh node directory, the directory.json downloaded from cascadiamesh.org and placed in $BEEBO_ROOT/mesh/. It is offline and never connects to a device.
An entry is completed only when its prefix matches exactly one node in the whole directory (a 1-byte prefix shared by several nodes never qualifies) and that node is within --max-km (default 100) of this node's own location. That location is recorded in neighbors.json (the self block) by beebo neighbors pull, which reads it from the node: the repeater's repeater.coords, or the companion's advertised location. A companion node also has it in contacts.json. Run neighbors pull once if update says the location is unknown, or give it explicitly with --origin LAT,LON. The name, type and location fill the blanks, and the key becomes the full 32-byte one. The proposals are shown in a table first, and nothing is written until you answer y:
$ gatto neighbors update
$ gatto neighbors update --max-km 30 --dry-run
$ gatto neighbors update --yes
--dry-run only prints the proposals and --yes applies them without asking. The table caption counts the entries that were skipped and why (ambiguous prefix, too far, not in the directory, no location in the directory).
beebo neighbors poke and beebo neighbors ping — single-peer, on-demand checks¶
rxlog --compare needs organic RX traffic to accumulate its samples, which can be slow against a quiet or distant neighbor. beebo neighbors poke and beebo neighbors ping get a data point on demand instead, useful for a quick manual before/after check against one specific direct neighbor around a manual beebo settings companion.fem.rxgain on|off toggle — both target a known direct (zero-hop) neighbor, resolved by name or public-key prefix against neighbors.json (run beebo neighbors pull first to populate/update it):
beebo neighbors poke <target> --pokes Nsends a direct-route round trip and asks the neighbor to report its own atomically-measured RSSI/SNR/noise-floor for the poke it just received, alongside our own reading of its reply — unlike a trace/ping round trip, which only ever reports SNR back to us, a poke tells us how well the other side is hearing us, and gives us a fresh RX reading of our own in the same exchange:
$ gatto neighbors poke beebo --pokes 5
beebo neighbors ping <target> --convergeruns repeated direct-trace round trips until the SNR mean statistically converges, tagging its output filename with the LNA state in force at the time (..._lna_on_.../..._lna_off_...) — run once per LNA state against the same peer and compare the two converged means directly.
Channels and messages¶
channels(companion only) —list,get,set IDX NAME,remove,send CHANNEL TEXT [--max-hops N],push,pullmanage the node's group-channel slots. A#namechannel derives its public secret; any other name needs--secret HEXor--random. Everysetrecords the channel in<root>/mesh/channels.json(mode 0600, keyed by name), whichpushwrites to a node andpullfills from one, so nodes share a private channel.--max-hops N(1-21; 0 = no limit) limits how many repeaters forward the message, whatever their own settings, by sending it with a pre-filled path.traffic send CHANNEL --rate N— injects fixed-size flood group messages at a constant rate per minute (--size,--durationor--count,--max-hops), so a quiet mesh still gives a tuned node the RX ratetuning.trial.min_pkt_raterequires.messages download/messages send—downloaddrains the full pending message backlog (CMD_SYNC_NEXT_MESSAGElooped until empty) across every channel and direct contact, saving to CSV or JSON (--format);send <target> <text>sends a direct message and reports whether it was ACK'd or timed out. Every message is tagged with the radio's rxgain/fem.rxgain at receive time and carries rxlog-comparable SNR/RSSI/path fields, so a backlog drain doubles as another source of LNA on/off data.traffic sustain [CHANNEL --rate N | --off]— companion only: the node itself sends flood group messages on a private channel, at random (Poisson-spaced) times and at most one every 2 s, only while the packets it hears per minute are below N, so a tuned repeater nearby keeps itstuning.trial.min_pkt_ratewithout a held connection. RAM-only: a reboot or role switch stops it. No arguments shows the state.
Monitoring and diagnostics¶
-
monitor— controls for the always-on background capture ring. With no subcommand it shows the ring's fill, capture state, window and packet totals, and an RX-conditions histogram. Its subcommands are below; Monitoring has the full record-kind and event-type reference. -
monitor status [health|service|rates]: the lifetime drop and fault counters plus the live RX, TX, CLI and idle time split. Bare, it prints three tables; a section name prints one. monitor start,monitor stop: resume or pause the capture (the same asmonitor.enabled on|off).monitor clearempties the ring.monitor capture [leaf] [on|off]: read or set which record kinds are captured:enabled,rx,tx,radio,env,batt,tuning,eventandpath.monitor events [name] [on|off]: a finer, RAM-only filter per event type.monitor pull: fetch the ring's raw records into a local per-node dataset, incremental by default.--fullrefetches everything,--clearempties the ring afterwards, and--to NAMEappends everything to one fileNAME.binwith its own resume cursor (read it back with--from NAMEondecodeandanalyze tuning trialoreffect).monitor listshows per-file and per-kind counts of what has been pulled.monitor decode: view and filter that dataset as a console table, or--saveit as CSV or JSON split per radio-config profile under~/.beebo/nodes/<node>/data/<radio_profile>/. See Analysis and In-Field LNA Comparison for how this feedsbeebo analyze.monitor tuning trialandmonitor tuning adaptive: the tuning session at a glance, below. All take--json, and the views write nothing to disk.
monitor tuning trial prints a state line (off, running a switch, waiting for RX traffic, idle), then per switch in run order its stored value, value list and status (running n/blocks plus the side of the running block, A or B in the A B B A order; next, waiting, queued, pending, decided, off). It also lists every trial the live ring holds, oldest first: A, B, the pairs used of those planned, N (the counts per block that set its noise: confirmed deliveries for the default score), the Change (mean ± SE per pair), Bounds (the decision interval at the pairs so far; adopt B when its lower end is above 0), Conf (the confidence that interval amounts to, to compare with confidence_pct), the Verdict (use A or use B) and the duration. Its subcommands:
start [SWITCH...|all]starts the sequence, and is refused while it is already on.stopturns it off and aborts a running trial.enable|disable SWITCH...|allchanges only the named switches' enable bits.values SWITCH [A,B,...]shows or sets a switch's value list (A, then up to three challengers, in the setting's own units);values default [SWITCH|all]resets lists.score [routed|delivered|received] [WEIGHT]shows or sets the score weights in tenths.profile(mainorexhaustive, see the setting trial),gain(min_gain_pct),confidence(confidence_pct),min_pkt_rate,block_countandblock_size_s(0 = planned from the node's traffic, see Automatic schedule), andcombined(on or off: one combined trial of the selected switches instead of one per switch) show or set the matching setting.- Every set and reset is refused while the trial is on:
stopit first.monitor tuning adaptiveshows the adaptive tuner's settings and the latest proposal per parameter. monitor debug/monitor watch— stream the firmware's live debug and monitor-ring events (transport connect/disconnect/lock, faults, ...);debugreplays the ring's current backlog first,watchshows only events from now on (see Diagnostics and Protocol Additions).monitor plot rssi— live chart of each received packet's RSSI per last-hop neighbor (every neighbor heard, or the--top Nmost heard, or-n HEXto pick) plus the noise floor, with a table of last RSSI, average over the window, best since the start, packets in the window and packets per minute for each neighbor, and a line with the total rate of all packets, updated per packet, and a level line at the best RSSI since the start; for placing an antenna.--spansets the rolling window the average and the rate cover (shorter reacts faster to antenna moves; the rate is over the time seen until the window is full);--gridadds a dim dotted grid and minor ticks where there is room.monitor plot tuning indicators [INDICATOR]...— live charts of the tuning indicators, the charts ofanalyze tuning indicators(Score, Routed, Delivered, Received, Neighbors, Busy, RSSI, SNR), drawn and updated likemonitor plot rssi: a dot at each measured point, the last--spanseconds (default 60),--gridfor a dotted grid, and a readout under the charts (now, average, min, max, point count, age and unit per line). Each chart title says what it measures and over how long, for exampleReceived: packets/min, trailing 15s: the rate is the packets heard in the last 15 s scaled to a minute, so it moves in steps of 4 per packet and falls back when traffic stops. It starts empty and fills as records arrive, likeplot rssi; once the first record has arrived the chart stays, and a node that hears nothing reads 0 a minute; Errors, Pool and CAD come from theroute_statsevent the firmware logs once a minute and only when a value changed, so Errors holds the last interval's rate (0 until the first) and Pool and CAD show-until one arrives; until a window has been watched, a rate is what was heard so far, scaled to a minute.--replayfills it from the ring first: the whole ring plays oldest first, minutes on a full one, with the chart following it forward in time until it reaches the present, so it only helps a long--span. Each line is a moving average: the indicator over the trailing--windowseconds (default 15; rates are per minute over it), with the definitions ofanalyze, evaluated on a regular time grid and at each event, with a dot at each event. It follows every event and steps back down as events leave the window, to 0 once none come. Names pick the charts as inanalyze(monitor plot tuning indicators received delivered; case and spaces ignored, a unique part of the name is enough,allfor every chart; default Score), and--score NAME=WEIGHT,...re-scores. Charts that do not fit the terminal are left out with a note. Ctrl-D or Ctrl-C quits.monitor plot tuning trial— live view of the setting trial, re-reading the monitor ring every 30 s (--every): the running block, its side (A or B) and time left, the A B B A strip, the paired statistics so far and a chart of A and B per pair. Follows the running trial, else the latest;--switch NAMEpins one, names aftertrialpick the charts: Score or indicators ofanalyze tuning indicators(monitor plot trial received delivered; case and spaces ignored, a unique part of the name is enough,allfor every chart). Ctrl-D or Ctrl-C quits.--score NAME=WEIGHT,...re-scores the trial with other score weights, as inanalyze tuning trial.profile— the command-latency profiling ring: merges the firmware's own per-command timing with the host-side round-trip log recorded when the global--profileflag is set, sorted/limited/filtered with--sort,--reverse,--limit;--rawprints the firmware's raw per-event timeline instead of the aggregated table.profile clearresets both rings.check— a one-shot health check-up: a per-indicator verdict (OK/INFO/PENDING/WARN/FAIL) covering QoS, RoS, SoH, the settings checks (TX power, RX/FEM gain, PIN, password, dedup window, ...), battery, and the dynamic-tuning optimizer's state (see Performance Tuning). Reads the monitor ring's live counters and latest resident snapshot the same waymonitor pulldoes — nothing new is captured, this just turns what's already being collected into a verdict per indicator instead of cross-referencing several commands by hand. See Health Report for what each indicator means and where its data comes from.multi_roleonly (no legacysimple_repeater/-requivalent).run— curated and user-provided use-case scripts (beebo run --list):calibrate-vbat,api-demo,api-sync-demo. They reuse the live connection under-i; the same logic is available to your own scripts through the Python API.
Remote mesh admin¶
admin <target> <action>— remote mesh-admin auth and repeater/room-server queries:login/logout/forget(credential lifecycle),cmd <text...>(run any admin CLI command remotely),cli <text...>(run a companion CLI command on a contact that allows it),cli-allow [on|off](show or set whether that contact may run CLI commands on this node),status/neighbors/telemetry/acl(authenticated queries),owner/regions/clock(anonymous, no login needed),mma <start> <end>(sensor/type-4 nodes only), andtransport [usb|ble|tcp [on|off]](see Admin Transport Control).
beebo admin <target> <action> [args...] authenticates against and
queries another node over the mesh (not the locally-connected one) —
target is a contact name or public-key hex prefix.
| Action | Example | What it does |
|---|---|---|
login [PASSWORD] |
beebo admin gatto login |
Log in (prompts for the password if omitted; caches it on success). |
logout |
beebo admin gatto logout |
Log out of an active admin session. |
forget |
beebo admin gatto forget |
Forget the locally cached password. |
cmd COMMAND... |
beebo admin gatto cmd "get radio" |
Run any admin text-CLI command remotely (see the text commands below) — requires an active login. |
status |
beebo admin gatto status |
Authenticated status query. |
neighbors |
beebo admin gatto neighbors |
Authenticated neighbor-table query. |
telemetry |
beebo admin gatto telemetry |
Authenticated telemetry query. |
acl |
beebo admin gatto acl |
Authenticated ACL (client login table) query. |
owner |
beebo admin gatto owner |
Anonymous owner-info query, no login needed. |
regions |
beebo admin gatto regions |
Anonymous region-list query, no login needed. |
clock |
beebo admin gatto clock |
Anonymous clock query, no login needed. |
mma START END |
beebo admin sensor1 mma 0 100 |
Min/max/avg sensor telemetry query (sensor/type-4 nodes only). |
transport [usb\|ble\|tcp [on\|off]] |
beebo admin gatto transport tcp off |
Show or set which transports the target accepts admin logins on (see Admin Transport Control). |
cmd self <command> runs <command> locally on the connected companion
node instead of relaying it to <target> over the mesh. It is the way to run a
command on the connected node from an app whose CLI screen is not available.
Status and telemetry rendering¶
beebo admin <target> status and ... telemetry render the raw core-stats/permission payloads as Rich tables with units instead of dumping hex or bare numbers — uptime is formatted human-readable, error-flag bitfields are decoded into named, colored fault labels, and the ACL permission byte is decoded into a colored admin/guest role label alongside the raw value (beebo/src/beebo/admin.py, beebo/src/beebo/node.py). Battery voltage is additionally paired with a charge-trend-aware state-of-charge estimate — see Battery State and Calibration.
admin ... cmd text commands¶
The stock text commands, kept for third-party apps and old scripts: what a MeshCore app or -r/--raw sends to
a node, and what beebo admin <target> cmd ... can send once logged in. The beebo command line and the node
console use one set of names, shown in the last column; use those.
$ beebo admin gatto login
$ beebo admin gatto cmd "get radio"
> 910.525,62.5,7,5
$ beebo admin gatto cmd "set tx 18"
ok
| Stock command | What it does | Same as |
|---|---|---|
reboot |
Reboot the device. | reboot |
clkreboot |
Reset RTC to a fixed date and reboot. | |
poweroff | shutdown |
Power off the device. | |
advert |
Send a flood advert. | advert flood |
advert.zerohop |
Send a zero-hop (local only) advert. | advert direct |
clock |
Show RTC time as HH:MM - D/M/Y UTC. |
clock |
clock sync |
Set RTC from this command's send time (cannot go backwards). | |
clock.epoch |
Show RTC time as bare epoch seconds (beebo-only). | |
time <epoch> |
Set RTC to <epoch> seconds (cannot go backwards). |
|
start ota |
Begin an OTA firmware update. | ota (host) |
ver |
Show firmware version and build date. | ver (node only) |
board |
Show board/manufacturer name. | |
neighbors |
Show the neighbor table. | neighbors peek |
neighbor.remove <pubkey-hex> |
Remove a neighbor by pubkey hex. | neighbors forget |
tempradio <freq> <bw> <sf> <cr> <mins> |
Apply temporary radio params for <mins> minutes. |
|
password <new> |
Change the admin password. | settings repeater.admin.password (host only, it prompts) |
clear stats |
Reset packet/radio stats counters. | |
get <key> |
Read a config setting (see Settings for the same values by dotted path). | settings <path> |
get transports |
Read usb/ble/tcp enable bits in one reply (beebo-only). | settings node.transport.usb\|ble\|tcp |
set <key> <value> |
Write a config setting. | settings <path> <value> |
region [<region>] |
Show or set the LoRa region. | region tree |
sensor list [<start>] |
List custom sensor settings. | |
sensor get <key> |
Read a custom sensor setting. | |
sensor set <key> <value> |
Write a custom sensor setting. | |
powersaving [on\|off] |
Show or set power-saving mode. | |
log start | log stop |
Enable/disable file logging. | |
log erase |
Erase the log file. | |
log |
Dump the log file (unauthenticated targets only). | |
stats-core | stats-radio | stats-packets |
Show stats counters (unauthenticated targets only). | status node, status radio, monitor status service |
gps [on\|off\|sync\|setloc\|advert [none\|share\|prefs]] |
GPS control (boards with GPS only). | |
gps diag |
Show GPS diagnostics, if available. | |
power |
Show battery and power-source status. | battery state (voltage and charge state) |
erase |
Erase the node's file system. USB serial text CLI only. | |
discover.neighbors |
Probe for neighbors. USB serial text CLI only. | neighbors discover |
monring.header |
Show the monitor ring's counters (beebo-only). | monitor status |
monring.clear |
Clear the monitor ring (beebo-only). | monitor clear |
get and set keys¶
get <key> and set <key> <value> take these keys. A key without a meaning below has the meaning of the same-named leaf in the Settings Reference; beebo settings is the preferred form, and these stay for scripts written for stock MeshCore.
| Key | Read | Write | Meaning |
|---|---|---|---|
adc.multiplier |
yes | yes | |
advert.interval |
yes | yes | Local (zero-hop) advert interval in minutes, 0 = off, up to 240. |
af |
yes | yes | |
agc.reset.interval |
yes | yes | |
allow.read.only |
yes | yes | on or off: allow read-only (guest) logins. |
ble |
yes | yes | |
bootloader.ver |
yes | Bootloader version. | |
bridge.baud |
yes | yes | Bridge build only. |
bridge.channel |
yes | yes | Bridge build only. |
bridge.delay |
yes | yes | Bridge build only. |
bridge.enabled |
yes | yes | Bridge build only. |
bridge.secret |
yes | yes | Bridge build only. |
bridge.source |
yes | yes | Bridge build only. |
bridge.type |
yes | Bridge build only. | |
cad |
yes | yes | |
direct.txdelay |
yes | yes | |
dutycycle |
yes | yes | |
extra.sf |
yes | yes | Up to three extra spreading factors the radio also listens on (side detectors), for example set extra.sf 8 9. |
flood.advert.interval |
yes | yes | Flood advert interval in hours, 0 = off, 3 to 168. |
flood.max |
yes | yes | |
flood.max.advert |
yes | yes | |
flood.max.unscoped |
yes | yes | |
freq |
yes | yes | |
guest.password |
yes | yes | |
identity.generate |
yes | Generate a new identity (write only). | |
int.thresh |
yes | yes | |
lat |
yes | yes | |
lon |
yes | yes | |
loop.detect |
yes | yes | |
multi.acks |
yes | yes | |
name |
yes | yes | |
node |
yes | set node <name> <privkey_hex>: set the name and private key together (write only). |
|
node.role |
yes | yes | companion or repeater; a change reboots the node. |
owner.info |
yes | yes | Owner text; a vertical bar stands for a newline. |
path.hash.mode |
yes | yes | |
pin |
yes | yes | |
prv.key |
yes | yes | Private key. Reading it works from the USB serial text CLI only. |
public.key |
yes | The public key. | |
pwrmgt.bootmv |
yes | ||
pwrmgt.bootreason |
yes | ||
pwrmgt.source |
yes | ||
pwrmgt.support |
yes | ||
radio |
yes | yes | |
radio.rxgain |
yes | yes | |
repeat |
yes | yes | |
role |
yes | The live role. | |
rxdelay |
yes | yes | |
transmit |
yes | yes | |
tx |
yes | yes | |
txdelay |
yes | yes | |
tz.offset |
yes | yes | |
usb |
yes | yes | |
wifi.enabled |
yes | yes | |
wifi.rssi |
yes | WiFi signal strength. | |
wifi.status |
yes | WiFi connection status. | |
tuning.* |
yes | yes | The tuning settings, for example tuning.trial.enabled. See Settings. |
This table is beebo admin's own built-in ADMIN_CLI_HELP reference
(beebo admin --help prints it in full); it's kept here so it shows up
alongside the rest of the command surface without needing --help.
RF bench measurement¶
measure groups the lab-equipment-based procedures detailed in RF Experiments — as opposed to rxlog --compare's no-equipment, in-field alternative:
measure cw --power <dBm> [--secs N]— key a manual continuous-wave carrier at one TX power level, for spot-checking with a spectrum analyzer.--secsis the carrier duration (default 30);0keeps it on until Ctrl-C, with no firmware auto-stop, so the PA stays keyed if the connection is lost.measure txpower [--carrier advert|cw] [--optimize/--no-optimize]— the automated TX power sweep described in TX Radiated Power.measure noise {internal|combined|in_band}— the noise-floor characterization procedures in System Noise Floor (50-ohm stub / antenna / bandpass filter), across everyrxgain/fem.rxgainpermutation. Values are raw SX1262 input unless--antenna-refkeeps the node's FEM RSSI offsets;combined/in_bandalso print the LNA gain against the latestinternalrun.measure rssi-by-bw— sweep LoRa bandwidth with transmit turned off by the test. A 50-ohm stub measures the receiver's internal noise; the real antenna measures the in-band environment noise. It shows how the noise floor scales with bandwidth (verifying the thermal-noise relationship in Thermal Noise).