Skip to content

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 bare advert sends a direct one.
  • clock — show Device/Source from the connection's own auto-sync (see Auto Time Sync) with no extra round trip; clock TIME sets the device clock to an explicit epoch instead; --boot forces 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-priority controls 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 with import FILE, or save it with export [FILE]/save. Without FILE, export (and its save shorthand) writes to BEEBO_ROOT/nodes/<node>/identity.json, the node's own directory in the config fs layout ($BEEBO_ROOT is ~/.beebo by default). generate [FILE] creates a brand new Ed25519 keypair purely locally (no device connection) and saves it the same way — pair it with a separate import FILE to 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. filter narrows by node type (all, an int mask, or a comma list of cli/rep/room/sens); --timeout sets how long to wait for stragglers, --full requests 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 N sends 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> --converge runs 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, pull manage the node's group-channel slots. A #name channel derives its public secret; any other name needs --secret HEX or --random. Every set records the channel in <root>/mesh/channels.json (mode 0600, keyed by name), which push writes to a node and pull fills 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, --duration or --count, --max-hops), so a quiet mesh still gives a tuned node the RX rate tuning.trial.min_pkt_rate requires.
  • messages download / messages send — download drains the full pending message backlog (CMD_SYNC_NEXT_MESSAGE looped 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 its tuning.trial.min_pkt_rate without 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 as monitor.enabled on|off). monitor clear empties the ring.
  • monitor capture [leaf] [on|off]: read or set which record kinds are captured: enabled, rx, tx, radio, env, batt, tuning, event and path.
  • 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. --full refetches everything, --clear empties the ring afterwards, and --to NAME appends everything to one file NAME.bin with its own resume cursor (read it back with --from NAME on decode and analyze tuning trial or effect). monitor list shows per-file and per-kind counts of what has been pulled.
  • monitor decode: view and filter that dataset as a console table, or --save it 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 feeds beebo analyze.
  • monitor tuning trial and monitor 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. stop turns it off and aborts a running trial.
  • enable|disable SWITCH...|all changes 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 (main or exhaustive, see the setting trial), gain (min_gain_pct), confidence (confidence_pct), min_pkt_rate, block_count and block_size_s (0 = planned from the node's traffic, see Automatic schedule), and combined (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: stop it first. monitor tuning adaptive shows 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, ...); debug replays the ring's current backlog first, watch shows 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 N most heard, or -n HEX to 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. --span sets 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); --grid adds a dim dotted grid and minor ticks where there is room.
  • monitor plot tuning indicators [INDICATOR]... — live charts of the tuning indicators, the charts of analyze tuning indicators (Score, Routed, Delivered, Received, Neighbors, Busy, RSSI, SNR), drawn and updated like monitor plot rssi: a dot at each measured point, the last --span seconds (default 60), --grid for 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 example Received: 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, like plot 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 the route_stats event 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. --replay fills 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 --window seconds (default 15; rates are per minute over it), with the definitions of analyze, 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 in analyze (monitor plot tuning indicators received delivered; case and spaces ignored, a unique part of the name is enough, all for 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 NAME pins one, names after trial pick the charts: Score or indicators of analyze tuning indicators (monitor plot trial received delivered; case and spaces ignored, a unique part of the name is enough, all for every chart). Ctrl-D or Ctrl-C quits. --score NAME=WEIGHT,... re-scores the trial with other score weights, as in analyze 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 --profile flag is set, sorted/limited/filtered with --sort, --reverse, --limit; --raw prints the firmware's raw per-event timeline instead of the aggregated table. profile clear resets 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 way monitor pull does — 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_role only (no legacy simple_repeater/-r equivalent).
  • 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), and transport [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. --secs is the carrier duration (default 30); 0 keeps 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 every rxgain/fem.rxgain permutation. Values are raw SX1262 input unless --antenna-ref keeps the node's FEM RSSI offsets; combined/in_band also print the LNA gain against the latest internal run.
  • 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).