A modern WSJT-CB companion — live map, logbook, and propagation dashboard for 11 m CB FT8 operators.
Purpose-built for WSJT-CB. Streams decodes and QSOs live over UDP, tails the ADIF log for automatic imports, and enriches everything with grid lookups, propagation snapshots, and an interactive world map.
Logged QSOs, live PSK Reporter spots, propagation strip, and the layered filter/equipment panel.
Running-QSO overlay — animated line and callsign marker to the DX you're currently working, driven straight from WSJT-CB's Status packet.
Equipment heatmap — pin a radio or antenna and every worked station blooms into a soft signal cloud coloured by RST, so you can see at a glance where each rig actually gets out.
Live
- Real-time decode stream from WSJT-CB on UDP 2237
- Status pane with band, mode, DX target, TX/RX offsets
- Solar / propagation strip (SFI, K, A, sunspots) with band-quality hints
- Auto-detects your callsign & grid from WSJT-CB Status — no manual setup
Map
- Live decodes as fading dots with SNR / distance / mode tooltips
- Logged QSOs coloured by equipment, with an on-demand signal heatmap per radio/antenna and a dB legend
- Running-QSO overlay:
Calling → Workingstate driven by WSJT-CB Status + directed decodes, plus a Calling-CQ halo on your QTH while transmitting a CQ - NEW-CQ badge — a call you've never worked calling CQ is labelled inline with its callsign so you can spot fresh grids at a glance
- Callsign lookup (🔍 in the toolbar or Logbook header) — type any callsign for its last-known grid, country, QSO history and distance
- Auto-zoom to fit all logged QSOs on open; camera + filters persist across tab switches
- PSK Reporter spot dots + animated great-circle traffic (Mercator-correct)
- Greyline overlay, time-replay scrubber, retro / OSM tile styles
Review
- Every auto-imported QSO lands in a review queue
- Add radio / antenna / notes / rating; edit or auto-fill the grid locator
- Missing grid resolves via PSK Reporter and back-fills the row automatically
Logbook
- Searchable, filterable table (review state, rating, equipment)
- Delete QSOs with confirmation
- ADIF drag-drop import and export
Stats
- KPIs (QSOs, unique calls / grids / countries)
- QSO/day chart, distance polar chart
- Per-equipment performance table (QSOs, grids, countries, avg / best DX, avg RST)
Voice
- Optional spoken alerts for events you care about — new callsigns / grids / countries calling CQ, someone answering your call, QSO logged, personal-best DX, milestones, propagation swings, WSJT-CB connection health
- Uses the bundled Alan voice (British male, Piper VITS) via a compact sherpa-onnx runtime; fully offline, no cloud calls
- Callsigns are read digit-by-digit and letter-by-letter; grid announcements include the country (learned automatically from your ADIF imports)
- Per-event toggles, live volume slider with drag-to-preview, rate limit, and UTC quiet-hours all live in Settings → Voice announcements
- Grab
CBScope.dmgfrom the releases page and dragCBScope.appinto/Applications. Releases are signed with an Apple Developer ID and notarized, so Gatekeeper will let it open without ceremony. - In WSJT-CB → File → Settings → Reporting, enable UDP Server pointed at
127.0.0.1:2237. - In CBScope → Settings, check the WSJT-CB ADIF log path (a sane OS default is pre-filled) — new QSOs will land in the Review tab as WSJT-CB writes them.
- Enter your callsign + grid (or wait for the first WSJT-CB Status packet to fill them in).
That's it — click over to Live or Map and start decoding.
flutter pub get
flutter run -d macos # or -d windows / -d linux
flutter build macos --release # unsigned .app under build/macos/...
# Signed + notarized DMG (requires Developer ID cert + notarytool profile):
./scripts/release_macos.shRequires Flutter 3.22+. On macOS, Xcode 14+ for release builds. The release scripts' prerequisites are documented at the top of each file.
Flutter cannot cross-compile desktop Linux, so the Linux tarball has to be
produced on a Linux x86_64 host — scripts/release_macos.sh has no way to
invoke it. On Debian/Ubuntu, install the toolchain first:
sudo apt install clang cmake ninja-build pkg-config libgtk-3-dev \
liblzma-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \
curl tar bzip2
flutter config --enable-linux-desktop
./scripts/release_linux.sh # build/CBScope-linux-x86_64.tar.gzThe two gstreamer -dev packages are required by the audioplayers_linux
plugin. Miss them and CMake fails during configure with "The following
required packages were not found: gstreamer-1.0"; the runtime gstreamer
libraries listed in the shipped README.txt do not cover the build.
If a configure run fails partway, delete build/linux before retrying.
A failed run leaves CMAKE_INSTALL_PREFIX=/usr/local in CMakeCache.txt,
and because the variable is then already set, the Flutter template's
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) override no longer fires —
the next build gets as far as install and dies on "cannot copy file […] to
/usr/local/qso_book: Permission denied", which looks like a permissions
problem but is a stale cache.
Everything is stored locally in an SQLite database under the OS app-support directory. No account, no telemetry, no upload. Callsign→grid lookups hit PSK Reporter directly; propagation numbers come from hamqsl.com. Both are toggleable in Settings.
Flutter · Riverpod · Drift (SQLite) · flutter_map · WSJT-CB UDP protocol (schemas 2 & 3).
MIT
