A JS8 ops console in the browser.
The native JS8Call decoder, headless in Docker, wired to public KiwiSDR receivers and GhostNet.
- Real decoding. KiwiSDR audio goes into native JS8Call. CI proves it end to end with a real recording.
- Live console. Waterfall, decoded traffic, heard stations, map and an audio monitor work on desktop and phone.
- GhostNet autopilot (opt-in). It follows your region's GhostNet JS8 nets on the nearest KiwiSDR. Each net is recorded (traffic, waterfall, audio) for later review. Live
@GSTFLASHtraffic raises an alert. - Truthful health. Every component reports timestamped evidence. "Connected" is never mistaken for "decoding".
- Polite on shared receivers. It identifies itself, backs off on reconnect and never touches shared receiver settings.
- RX today, built to grow. Current builds have no transmit path (the UI shows an
RXmode chip). Transmit is planned as a separate, explicitly enabled extension with proper radio tooling.
KiwiSDR ─ SND ─▶ bridge ─▶ decoder-agent ─▶ PulseAudio ─▶ JS8Call (native, headless)
└ W/F ─▶ bridge ─▶ browser JS8Call ─ UDP ─▶ agent ─▶ bridge ─▶ browser
git clone https://github.com/d3mocide/ghost.js8 && cd ghost.js8
cp .env.example .env # set GHOSTJS8_ALLOWED_ORIGINS
docker compose up -d --build # UI on http://127.0.0.1:8080To monitor GhostNet unattended, add three lines to .env (details):
GHOSTJS8_GHOSTNET=on
GHOSTJS8_GHOSTNET_REGION=na # na | eu | aus
GHOSTJS8_HOME_GRID=EM73 # your Maidenhead gridRuns on amd64 and 64-bit ARM (Raspberry Pi 4/5 on a 64-bit OS, Apple Silicon, ARM servers). Releases publish multi-arch images, so you can pull instead of build: set GHOSTJS8_IMAGE_PREFIX=ghcr.io/d3mocide/ghostjs8 and GHOSTJS8_TAG in .env, then run docker compose pull && docker compose up -d --no-build.
Put a reverse proxy in front for TLS and authentication (operations). Keep the host NTP-synced, because JS8 decoding depends on accurate time.
Architecture · GhostNet · Operations · Protocol · KiwiSDR notes · Decoder container · Security updates · Contributing / agents
Requires uv, Node 22, GNU make and Docker.
make setup # pinned deps
make check # lint, typecheck, unit tests (bridge + web)
make acceptance # real-recording decode test (Docker)
make e2e # Playwright against a simulated stackFor UI work without Docker, run tools/dev-stack.sh and npm --prefix web run dev. Add GHOSTNET=1 SEED_NET=1 to the dev stack for a demo GhostNet recording.
GPL-3.0-or-later. JS8Call (GPL-3.0) runs as a separate, unmodified process. The upstream test recording is fetched at test time, not redistributed. Map outlines are Natural Earth (public domain).
A d3FRAG Networks project. In the spirit of S2 Underground's GhostNet; not affiliated.

