Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CoreScope TUI

A lightweight terminal client for CoreScope, a real-time analyzer for MeshCore LoRa mesh networks. CoreScope's own web frontend is a full browser app (Leaflet map, live packet feed, charts) which is heavy to run on small hardware. This is a from-scratch terminal reimplementation of the same idea: it talks to a CoreScope instance's existing public REST + WebSocket API and renders the live map, node/observer lists, live packet feed, and RF/topology analytics — no browser, no JS/CSS engine, low memory footprint. It's a thin client only: all decoding and aggregation happens server-side on CoreScope; this just visualizes what the API already provides.

Built with resource-constrained handhelds (e.g. the ClockworkPi uConsole) in mind, but it's a normal Go binary and runs on any Linux/macOS/Windows box with a terminal.

Features

  • Live map — ASCII/Unicode world map with nodes plotted at their real position, color-coded by role (repeater/companion/room/sensor/observer)
  • Live packet animation — a travelling marker follows each packet's actual multi-hop route in real time, using CoreScope's own hop resolution (resolved_path); anything without a resolvable hop just pulses at the receiving station
  • Fly-to search — jump the map to a named location by IATA airport code
  • Node picker — cycle through the nodes currently on screen to see name, role, pubkey, and last-seen
  • Node / observer tables — sortable by any column (ascending or descending), filterable by role (nodes) or region (observers)
  • Live packet feed — scrolling real-time feed with decoded payload type, route type, signal strength
  • RF / topology analytics — histogram and summary views, loaded on demand so a busy instance's multi-MB analytics payloads aren't polled in the background

Dependencies

Requires Go 1.24+ to build. The compiled binary is a single static executable with no runtime dependencies — copy it anywhere and run it.

Go modules used (fetched automatically by go build):

Module Purpose
charmbracelet/bubbletea Terminal UI framework (Elm-style architecture)
charmbracelet/bubbles TUI components (tables, viewport, text input)
charmbracelet/lipgloss Terminal styling/layout
gorilla/websocket WebSocket client for the live packet feed

Installation

1. Install Go 1.24+

Check what you have first:

go version

The easiest way, if your distro's repos are recent enough:

sudo apt install golang-go

If that installs a version older than 1.24 (common on Debian/Ubuntu, whose repos often lag behind upstream Go releases), install it from go.dev directly instead. On a uConsole or Raspberry Pi (ARM64):

curl -LO https://go.dev/dl/go1.24.2.linux-arm64.tar.gz
mkdir -p ~/.local
tar -C ~/.local -xzf go1.24.2.linux-arm64.tar.gz
echo 'export PATH=$HOME/.local/go/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
go version

On a regular amd64 Linux box, swap linux-arm64 for linux-amd64 in the URL. Check go.dev/dl for the current release.

2. Get the source

git clone <this-repository-url> corescope-tui
cd corescope-tui

(Or copy the project directory over however you'd like — scp, a USB drive, etc. — if you haven't pushed it to a remote yet.)

3. Build

go build -o corescope-tui ./cmd/corescope-tui

The first build downloads the Go module dependencies listed above; subsequent builds are fast and fully offline.

Cross-compiling (e.g. building on a laptop to deploy onto a uConsole without needing Go installed there at all):

GOOS=linux GOARCH=arm64 go build -o corescope-tui-arm64 ./cmd/corescope-tui

Copy the resulting binary to the target machine with scp and run it directly — no Go toolchain or any other dependency needed on that machine.

Running

./corescope-tui                                      # connects to the default public instance
./corescope-tui --url https://your-instance.example   # or point at a specific CoreScope deployment

Flags

Flag Default Description
--url https://analyzer.00id.net CoreScope instance base URL
--timeout 15s REST request timeout per attempt (one automatic retry is always made on failure)
--buffer 500 Max packets kept in the live feed's ring buffer
--debug (off) Path to append connection/request diagnostics to — useful since the TUI takes over the terminal, so there's nowhere else to see errors

Keys

  • 15 — switch tabs (Live / Map / Nodes / Observers / Analytics)
  • q / Ctrl+C — quit

Map tab

  • + / - — zoom in/out
  • [ / ] — fine zoom (a much smaller step, for tuning zoom level the same way Shift+arrows fine-tune position)
  • Arrow keys — pan (moves a fraction of the current view; bigger jumps the more zoomed out you are)
  • Shift + arrows — nudge by exactly one grid cell regardless of zoom, for fine-tuning a position once you've zoomed in
  • Tab / Shift+Tab — cycle through the nodes currently on screen; the selected one shows name/role/pubkey/last-seen below the map
  • g — open "fly to": type an IATA airport code (e.g. SFO), / to pick a match, Enter to jump, Esc to cancel
  • 0 — re-fit the view to all currently loaded nodes
  • o — toggle dual-observer view: some hardware is both a mesh node (repeater/companion/room) and an observer station — CoreScope's own web UI shows both facts at once (a small star overlay on the normal role icon), but a terminal cell can't overlay two glyphs, so this toggles between showing such a node by its primary role or by the observer glyph/color instead

Nodes tab

  • f — cycle role filter (all / repeater / companion / room / sensor / observer)
  • s / S — cycle sort column (Last Seen / First Seen / Adverts / Name / Role) / toggle ascending-descending
  • / — select a row

Observers tab

  • f — cycle region filter (all + whatever IATA codes are actually present in the current data)
  • s / S — cycle sort column (Packets / Last Seen / Name / IATA) / toggle ascending-descending
  • / — select a row

Analytics tab

  • / / Tab — switch between RF and topology charts

How the live animation works

Every live packet pulses the observer station that received it. When CoreScope can resolve the packet's actual route — either because it's an ADVERT packet (which carries the sending node's own pubkey and exact position directly) or because the server's own hop-disambiguation already resolved the path's hash-prefixed hops to full pubkeys (resolved_path) — a marker travels the real route across the map instead of just pulsing in place.

The travelling marker is colored by payload type (ADVERT, TXT_MSG, REQ, GRP_TXT, ...), each given its own stable color spaced evenly around the hue wheel — so at a glance you can tell what kind of packet is moving, and simultaneous animations of different types are visually distinguishable from each other rather than all looking identical.

Map orientation

The map has no tile/image backend, but it's not just dots in blank space either:

  • Coastlines and country/state borders render as a faint background layer, using embedded public-domain Natural Earth data — no network fetch, no runtime parsing, compiled directly into the binary. Country borders and coastlines are worldwide; state/province-level borders currently cover the US and Canada (Natural Earth's smallest-scale admin-1 dataset only has full-world coverage for a handful of large countries — easy to extend to others later if useful).
  • The legend shows the current view's center and approximate width (center: 47.68,-64.04 ~7628km), for absolute orientation independent of whatever nodes happen to be on screen.

Project structure

cmd/corescope-tui/    entrypoint: flag parsing, wiring, starts the TUI program
internal/client/      typed REST + WebSocket client for CoreScope's API
internal/store/       in-memory state shared between the network layer and the UI
internal/geo/         lat/lon → terminal-grid projection (pan/zoom/fit, no map tiles)
internal/ui/          the TUI itself (bubbletea models, one file per tab + shared styles)

Scope

This covers live map, node/observer lists, live packet feed, and basic RF/topology analytics. Not implemented: channel chat decryption, VCR-style historical replay, geofilter tooling, and deeper analytics views (hash-collision, subpaths, rx-coverage) that CoreScope's web UI has.

Troubleshooting

  • Connection times out completely, no HTTP response at all — the instance itself is likely unreachable; check the URL loads in a browser first.
  • Empty/reset response from /api/* but the homepage loads fine — some deployments block default library User-Agents (curl/x, Go-http-client/1.1). This client already identifies itself with an honest custom UA (corescope-tui/0.1) rather than a spoofed browser string, specifically to avoid that.
  • decode: unexpected end of JSON input — the server returned an empty/truncated body. The client retries once automatically on this; if it persists, the instance itself may be having trouble.
  • If the default --url is down, https://live.meshcore.ca is a known-working public CoreScope deployment.

Run with --debug <path> to log connection attempts, retries, and errors to a file for troubleshooting, since the TUI otherwise owns the whole terminal.

About

Lightweight terminal client for CoreScope (MeshCore mesh network analyzer) — live map, node/observer lists, live packet feed, and RF/topology analytics, no browser required

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages