|
|
|
\
|
Warning
This project was completely vibe-coded with Claude Code and Cursor.
A terminal UI for monitoring and configuring Meshtastic mesh networks. Connects to a Meshtastic node via HTTP and displays real-time packet traffic, node information, chat messages, and device configuration.
- Packets view - Live packet stream with detailed inspection (decoded payload, JSON, hex dump)
- Nodes view - Discovered nodes with signal quality, battery, position, hardware, favorites
- Chat view - Send and receive channel messages with emoji support and delivery status
- DM view - Direct messages with delivery status and resend support
- Config view - View and edit device configuration with batch mode
- Log view - Position, traceroute, and nodeinfo response history
- Node commands - Traceroute, position/telemetry/nodeinfo request, direct ping, DM
- ACK notifications - Visual feedback when nodes acknowledge your packets
- MeshView integration - Update node info from a MeshView server, view live MeshView traffic
- Persistent storage - SQLite database for nodes, messages, and packets
- Session support - Multiple named sessions for different radios
Grab the latest release for your platform from the Releases page.
chmod +x meshtastic-cli-darwin-arm64
./meshtastic-cli-darwin-arm64 192.168.1.100Note: macOS binaries are not codesigned. You may need to right-click and select "Open" or run xattr -d com.apple.quarantine <binary> to bypass Gatekeeper.
docker volume create meshtastic-cli
docker run --rm -it -e TERM -v meshtastic-cli:/root/.config ghcr.io/statico/meshtastic-cli 192.168.1.100
# With MeshView integration (e.g., Baymesh)
docker run --rm -it -e TERM -v meshtastic-cli:/root/.config ghcr.io/statico/meshtastic-cli 192.168.1.100 --meshview https://meshview.bayme.shRequires Bun.
bun install
bun run dev 192.168.1.100meshtastic-cli <address> [options]
Arguments:
address Device address (required) - IP address, hostname, or serial port
Options:
--session, -s Session name for database (default: default)
--clear Clear the database for the session and exit
--skip-config Skip loading device configuration on startup
--skip-nodes Skip downloading node database (faster connect)
--meshview, -m MeshView URL for packet/node links
--fahrenheit, -F Display temperatures in Fahrenheit
--port, -P HTTP port number (default: 4403 if no port in address)
--tls, -T Use HTTPS instead of HTTP
--insecure, -k Accept self-signed SSL certificates
--pcap <file> Write packets to pcap file for analysis
--help, -h Show help
Connect to a Meshtastic device (default port 4403):
meshtastic-cli 192.168.0.123Connect to meshtasticd HTTP API (port 8080 with HTTPS):
meshtastic-cli 127.0.0.1 --port 8080 --tls --insecureNote: meshtasticd servers need to have the webserver enabled. The webserver typically runs on port 8080 with HTTPS. Check your meshtasticd configuration to ensure the webserver is enabled.
Connect to a device on a custom port:
meshtastic-cli 192.168.1.100 --port 8080Connect with HTTPS and accept self-signed certificate:
meshtastic-cli example.com --tls --insecureCapture packets to pcap file for analysis:
meshtastic-cli 192.168.0.123 --pcap traffic.pcapThe pcap file can be analyzed with tools like Wireshark or tcpdump. Packets are written in pcap format with LINKTYPE_USER0 (147) containing the raw Meshtastic protobuf frames.
In Chat and DM views, messages show delivery status:
| Indicator | Meaning |
|---|---|
[...] |
Pending - waiting for acknowledgment |
[β] |
Acknowledged - recipient confirmed receipt |
[β] |
Failed - delivery failed or timed out |
[M] |
MeshView confirmed - packet seen on MeshView server |
The [M] indicator also appears in the Packets view when a MeshView URL is configured. This confirms the packet was received by the MeshView aggregation server, which is useful for verifying mesh propagation.
Direct ping sends a traceroute request with hopLimit: 0, which means only nodes in direct radio range will receive and respond to the packet. This is useful for testing immediate connectivity to neighbors.
How it works:
- The request is sent with 0 hops, so only direct recipients can receive it
- No retransmissions occur (more lightweight than regular traceroute)
- Only nodes that can directly hear your transmission will respond
Caveats:
- The response may still be relayed through intermediate nodes (firmware limitation)
- You cannot definitively confirm bidirectional direct connectivity - you only know they heard YOU directly
- Less reliable than regular traceroute (single transmission, no retries)
- No response could mean: (a) not in direct range, or (b) packet was lost to interference
For full bidirectional direct-link testing with RSSI measurements, firmware changes would be needed. See meshtastic/firmware#8905 for ongoing discussion.
For proper emoji and Unicode character display, ensure your terminal uses Unicode-compliant width calculations:
- Ghostty - Uses Unicode widths by default (
grapheme-width-method = unicode) - Kitty - Uses Unicode widths by default
- iTerm2 - Enable in Preferences β Profiles β Text β "Unicode version 9+ widths"
- Terminal.app - May have issues with some emoji
There are still issues with some emoji and fixing them is a work in progress.
| Key | Action |
|---|---|
| 1-7 | Switch to view (7 with MeshView) |
| [ / ] | Previous / Next view |
| Ctrl+L | Redraw screen |
| q | Quit |
| ? | Toggle help |
| Key | Action |
|---|---|
| j/k | Navigate packets |
| g/G | First/last packet |
| h/l | Switch inspector tab |
| Tab | Toggle pane sizes |
| +/- | Resize inspector |
| m | Open position in Maps |
| n/Enter | Jump to sender node |
| u | Update node from MeshView |
| o | Open packet in MeshView |
| Key | Action |
|---|---|
| j/k | Navigate nodes |
| / | Filter nodes |
| t | Traceroute |
| p | Request position |
| e | Request telemetry |
| d | Start DM |
| D | Direct ping (hop=0) |
| u | Update from MeshView |
| U | Update all unknown from MeshView |
| m | Open position in Maps |
| l | Lookup hardware model |
| f | Toggle favorite |
| i | Request node info |
| I | Toggle ignored |
| x | Remove node from DB |
| H | Sort by hops |
| S | Sort by SNR |
| B | Sort by battery |
| A | Sort by age (last heard) |
| F | Sort by favorites |
| Key | Action |
|---|---|
| j/k | Navigate messages |
| / | Filter messages |
| Tab | Switch channel |
| n | Go to sender node |
| d | DM the sender |
| u | Update node from MeshView |
| R | Resend failed message |
| Enter | Focus input |
| Alt+E | Emoji selector |
| Escape | Unfocus / Exit |
| Key | Action |
|---|---|
| j/k | Navigate conversations or messages |
| l/β | Enter message selection mode |
| h/β | Back to conversation list |
| n | Go to node |
| u | Update node from MeshView |
| R | Resend failed message |
| Enter | Focus input |
| Escape | Back / Unfocus |
| # | Delete conversation |
| Key | Action |
|---|---|
| j/k | Navigate responses |
| g/G | First/last response |
| Key | Action |
|---|---|
| h/j/k/l | Navigate menu |
| Enter | Select section |
| j/k | Navigate config fields |
| g/G | First/last field |
| c | Commit changes |
| C | Discard changes |
| Escape | Back to menu |
| r | Reboot device |
| Key | Action |
|---|---|
| j/k | Navigate channels |
| e | Edit channel name |
| r | Cycle channel role |
| p | Edit encryption key (PSK) |
| u | Toggle uplink |
| D | Toggle downlink |
MIT



