XTOC™ Tactical Operations Center Software Suite
What XTOC™ is
Use the disaster guide for civil response workflows and the MILSIM guide for multi-day tactical / airsoft events with XCOM, XINTEL, XCORE, ATAK, APRS, JS8Call, FLDIGI, VarAC, mesh, MANET, SATCOM, drones, QR handoff, thermal printing, and TOC workflows. Both guides now include detailed Digi Modes playbooks and practical APRS, JS8Call, FLDIGI, and VarAC use cases.
Latest overview video:
Aircraft surveillance walkthrough (video):
What you can use it for (examples):
- Turn an old phone/tablet into a dedicated field log + tactical map device.
- Run a “wall map” by casting to a TV, connecting a laptop to HDMI, or using a mini projector.
- Run a shared TOC / mission control on your LAN: one “master” XTOC hosts the live DB; other devices join via Mirror QR as read-only viewers and stay synchronized automatically (no more re-importing backups every minute).
- Operate in low-connectivity environments: move updates by QR, copy/paste, SMS, email, APRS, JS8Call, FLDIGI, or VarAC digital text, or radio relay.
- Manual voice relays: use Voice (TTS) output to spell packet text character-by-character.
- NEW: ViperGram radio-audio transport. Export robust OFDM audio bursts you can play into almost any radio (no TNC/data port required), then decode them in XTOC/XCOM from a recording or on-demand live mic listen, or let XINTEL handle continuous automatic packet ingest.
- NEW: Digi Modes radio bridges for APRS + JS8Call + FLDIGI + VarAC. Run
aprs-bridge,js8call-bridge,fldigi-bridge, orvarac-bridge, open the matching Digi Modes subpage, watch bridge health/raw traffic/debug data, move structured APRS packet traffic or decoded digital text straight into XTOC, and auto-import embeddedX1...packets without copy/paste.
- NEW: Radios workbench / SDR go-box. Run browser-based scanner, HF, and dual-band control heads in three bays, map each bay to a USB SDR source, use live front-panel controls plus direct-entry keypads, and drive a local headless receiver from the Radios page. Current helper support is RTL-SDR receive via
rtl_fm. - NEW: Run a TOC video-on-demand watch floor. Scan a local LAN for RTSP cameras, merge ATAK/CoT video links, and open live ISR feeds inside XTOC with metadata, numeric alerts, fullscreen watch, and screencaps.
- Stand up a fast field LAN: connect devices over Wi-Fi HaLow / Open MANET / any trusted IP network and let packet updates flow live between the XTOC master and XCOM field clients (no chunking needed on LAN).
- Connect to a mesh network and let updates flow in automatically: packets are decoded and applied straight to the map + log when received.
- Maintain a shared picture without a server: share SITREPs / TASKs / CONTACTs / CHECKIN/LOC / EVENTs plus ZONE area markings, PHASE LINE overlays, and EVENT map labels.
- Buy it here: XTOC™ Tactical Operations Center Software Suite – MKME Store
Real-world scenario people actually integrate a TOC:
- Disaster recovery / emergency response: track teams, requests, hazards, and status updates when cell service is degraded.
- CERT / SAR / volunteer ops: run an incident log, map check-ins, and share updates between radios, runners, and vehicles.
- Ham radio nets: use CLEAR packets (openly decodable) to move structured SITREPs/LOC/RESOURCE reports over voice relays or digital text.
- Digital mode operators: use Digi Modes subpages for APRS, JS8Call, FLDIGI, or VarAC to move structured packet traffic into the TOC, auto-import embedded XTOC packets, inspect live bridge/debug status, and alert on matching traffic without manual copy/paste. VarAC is especially strong for long-range HF backhaul.
- Milsim / training / exercises: create a lightweight “training TOC” that can be projected on a wall, with zones and tasking for learning reps.
- Community preparedness: keep a local roster, comms plan (P.A.C.E.), and printable checklists; share a backup file to hand off the TOC.
training, and off-grid operations. It runs as an installable Progressive Web App (PWA) and exchanges updates using
compact, chunkable text packets over QR codes, Meshtastic/MeshCore messaging, Reticulum (MeshChat/RNode), SMS/email, or radio relay—so your team can
maintain a shared operational picture without a server.
APRS, JS8Call, FLDIGI, and VarAC, with APRS bridge send/receive, per-program visibility, raw traffic/debug panels, automatic X1... packet import, and trigger support for matching radio traffic.SMS, mesh text (Meshtastic/MeshCore), Reticulum (MeshChat/RNode), email, QR, clipboard, even radio relays—without relying on a server.
APRS, JS8Call, FLDIGI, and VarAC now share one module with per-program subpages, so bridge-backed packet traffic and decoded digital text are no longer just loose radio logs; they become TOC data with import, visibility, alerts, and bridge-debug insight.Install it as a PWA and it keeps working with no network (no accounts, no backend, no live tracking server).

That makes it power-efficient and ideal for improvised TOCs. BUY IT HERE: XTOC™ Tactical Operations Center Software Suite – MKME Store
Why it’s awesome
- Works with whatever you have.
If you can move text, you can move XTOC™ packets (radio relays, email, Meshtastic/MeshCore, Reticulum (RNS), clipboard, QR). - Voice (TTS) output.
Have XTOC™ spell packets out character-by-character for manual voice relays. - NEW: ViperGram audio bursts.
Render packet text as a robust OFDM WAV burst for radio transmission, import recordings back into packet text, use on-demand live mic listen in XTOC/XCOM, or let XINTEL decode the burst continuously and pipe it right into XTOC like any other packet source. - NEW: Digi Modes bridges for APRS + JS8Call + FLDIGI + VarAC.
Runaprs-bridge,js8call-bridge,fldigi-bridge, orvarac-bridge, monitor all traffic in the matching Digi Modes subpage, inspect live debug/health data, auto-import embeddedX1...packets, and let Triggers alert on live digital radio traffic. - NEW: Radios workbench / SDR go-box.
Run compact browser-based scanner, HF, and dual-band control heads in three bays, use direct-entry keypads and live front-panel controls, and drive a headless local receiver without opening a separate SDR desktop app. Current helper support is RTL-SDR receive viartl_fm. - Mesh + auto-ingest (new).
When packets are received via mesh, XTOC™ decodes and applies them automatically. Timeline + Tactical Map update with the full field-level details from the AO (area of operations)—zero clicks. - Mesh channels + DMs (Meshtastic / MeshCore) (new).
From the Mesh page, connect over Web Bluetooth, import Meshtastic channel labels (Meshtastic only), quick-select a channel, and click a node heard to send a direct message (DM). - MeshChat (Reticulum / RNode) (new).
Move XTOC packets over Reticulum (RNS) including an RNode over Bluetooth/serial using the bundledreticulum-bridge. Share a QR to provision field devices and send packet lines via broadcast or direct (DM). - MANET / HaLow LAN link (new).
When you have an IP network (Wi-Fi HaLow / Open MANET / any trusted LAN), run a tiny bridge on the XTOC laptop, connect XCOM clients via QR, see network topology, and send/receive packets live over LAN without chunking. (In the ZIP:halow-bridge/— seehalow-bridge/README.md.) - Anyone can run a TOC.
No accounts, no SaaS, no central database. Each device keeps its own local log and shares updates by exchanging packets. - Offline-first.
Installable as a PWA. Once loaded, XTOC™ keeps working without signal. - Built for tight character limits.
Packets can be sized to your channel and automatically chunked into multipart messages (SMS,
mesh text, JS8/APRS style constraints) and reassembled on import. - Structured info beats chat spam.
Instead of free-form messages, XTOC™ uses templates (SITREP, TASK, CONTACT, RESOURCE, ASSET, CHECKIN/LOC, ZONE, MISSION, EVENT, PHASE LINE) so the TOC can filter,
map, and archive reliably. - Zones (area markings).
Mark areas on the map (circle or drawn polygon), label them (Danger/Safe/etc.), and share them via Comms packets so everyone has the same picture. - SATCOM (satellite tracking).
Load TLE sets (paste/file/Celestrak) and visualize satellite positions + ground tracks right on the Tactical Map. Includes ham radio satellite lists and filtering so you only display what you need. - Ships (AIS) (optional).
Decode an AIS feed with the bundledships-helperand plot nearby vessels as a live Tactical Map overlay. - Aircraft (ADS-B) (optional).
Decode local 1090 MHz ADS-B with an RTL-SDR (or HackRF with a compatible dump1090/readsb build) using the bundledadsb-helperand plot aircraft as a live Tactical Map overlay. Includes an offline aircraft registry database (US FAA + Transport Canada) with 344,924 aircraft records (tail/registration, make/model, operator/owner) and offline lookup by tail number or ICAO hex – no internet required. - NEW: Aircraft watchlist (flagging).
Flag specific aircraft from the Tactical Map popup or Aircraft lookup. Flagged aircraft are emphasized everywhere (flag in lists + larger red pulsing icon on the map) so you can track the planes you care about even when offline. Flags persist locally and are included in backup export/import. - ATAK integration (optional).
Exchange KML/KMZ overlays and run an optional live CoT gateway using the bundledatak-helper(ATAK ↔ XTOC™). - NEW: Video ISR / TOC video on demand.
Watch RTSP camera streams inside XTOC using the bundledvideo-helper, scan a LAN for feeds, merge ATAK/CoT video cues, get numeric “new feed” alerts, and keep metadata + screencaps with the live picture. - NEW: Secure Session (Trust Link) (optional).
Link field operators to the TOC with a one-time challenge/response. After linking, every packet is auto-signed so the TOC can verify it and reject replays/forgeries – regardless of transport. - Secure when you’re allowed to be.
CLEAR mode is designed to be openly decodable and “amateur-radio compatible by default.”
Secure Session (optional) adds authentication/anti-replay (signed packets). SECURE mode adds encryption for non-amateur-radio transports.
NEW: Video ISR / TOC video on demand
Video ISR gives the TOC a real watch floor inside XTOC. Run the bundled video-helper, scan the local LAN for RTSP cameras, merge ATAK/CoT video cues from the existing ATAK ingest, and watch live feeds on demand in one tactical board.
- Numeric video alerts: when a new feed appears, the Video ISR module shows a numeric badge so operators know something is waiting to be watched.
- Single-board ISR workflow: feed roster, live viewer, ATAK-linked metadata, geolocation, notes, probe status, and fullscreen watch all stay together.
- Screencaps + handoff: snag JPEG stills, copy the feed URL/metadata, and move directly into SITREPs, tasking, or chat handoff.
- Simple operator path: release helper bundles include a Windows launcher/executable for
video-helper; operators do not need Python to use the feature.
How it works: the packet
XTOC™ is not a messaging network. It’s a packet creation + import/export + local log system.
Every report you create becomes a text packet you can move through any channel. On the receiving side, importing it (or receiving it directly via mesh) decodes it and updates
the local log and (when applicable) the tactical map automatically.
XTOC™ Off Grid Secure Communication TOC Platform
Packet sizing + chunking (the superpower)
Real-world comms have hard limits: SMS caps, mesh message length, gateway line breaks, and radio workflows.
XTOC™ lets you pick a max characters-per-line and automatically splits a packet into numbered parts.
Receivers import the parts in any order; XTOC reassembles and deduplicates.
X1.<T>.<M>.<ID>.<P>/<N>.<PAYLOAD>
T = template id (e.g. SITREP, TASK, CONTACT...)
M = mode: C = CLEAR, S = SECURE (non-ham)
ID = message id (used for dedupe + multipart reassembly)
P/N = part number and total parts for chunking
PAYLOAD = compact encoded data
The details are documented in the project docs (packets/transports, crypto/keys, templates/codebooks).
NEW: ViperGram radio-audio transport
ViperGram is the X* toolchain audio transport for moving XTOC packet text over any audio path, including handheld/mobile radios.
Generate the burst in XTOC/XCOM, play it into a radio, record it off-air, then decode it back into the original packet text. XTOC/XCOM can also do on-demand live listening from the device microphone.
If you run XINTEL on the receive side, it can decode the same burst continuously and inject the recovered packet text directly into XTOC.
This is a major capability because it gives you a radio-audio packet path with no TNC, no data port, and no special cabling requirement.
It targets the same operational niche as Rattlegram-style audio transfer, but it is not wire-compatible with Rattlegram; the burst format is purpose-built for the X* packet workflow.
- Audio format: mono 16-bit PCM WAV at 8000 Hz.
- Lead/tail: 180 ms silence at the start and end.
- Inter-burst gap: 240 ms.
- Edge shaping: 10 ms cosine ramp on each burst; normalized to about 0.92 full scale.
- OFDM symbol: 1280 useful samples (160 ms) + 160 sample guard/cyclic prefix (20 ms) = 180 ms on-air.
- Symbols per burst: 7 total = noise, sync, preamble, then 4 payload symbols.
- Burst duration: 1260 ms.
- Carriers: 256 active, bins 112..367, spacing 6.25 Hz, occupied audio about 700 Hz..2293.75 Hz.
- Payload modulation: differential QPSK.
- Bit processing: 32-column bit interleave, payload whitening with a xorshift32 PRBS, CRC-32 validation, multi-burst reassembly.
- Import path: XTOC/XCOM can decode audio files or use on-demand live mic listen; XINTEL can decode the same bursts continuously from radio audio and forward the recovered multiline packet text into XTOC so chunked packets reassemble correctly.
byte 0 0x56 magic 'V'
byte 1 0x47 magic 'G'
byte 2 0x01 format version
byte 3 protection code 1=Strong, 2=Medium, 3=Normal
byte 4 burst index 1-based
byte 5 burst total total bursts in message
byte 6 payload length clear payload bytes in this burst
byte 7 burst repeats repeats used by this protection profile
byte 8 CRC32 byte 0 payload CRC, least-significant byte first
byte 9 CRC32 byte 1
byte 10 CRC32 byte 2
byte 11 CRC32 byte 3
byte 12+ whitened payload bytes
- Strong: 85 bytes per burst, duplicated payload bitstream, 2 repeats.
- Medium: 128 bytes per burst, 2 repeats.
- Normal: 170 bytes per burst, 1 transmit.
NEW: Digi Modes radio bridges (APRS + JS8Call + FLDIGI + VarAC)
XTOC now includes a Digi Modes module with separate APRS, JS8Call, FLDIGI, and VarAC subpages, so the TOC can connect the right helper for the radio program already in use. APRS gives the TOC a bridge-backed packet path with provisioning QR, send/receive, and auto-import over APRS / AX.25. JS8Call gives the TOC a weak-signal long-haul text path, FLDIGI supports keyboard-style soundcard nets and local or regional relay traffic, and VarAC reads inbound chat, broadcasts, and VMail from VarAC.db so long-range HF traffic enters the TOC directly. If a decoded message contains an embedded X1... packet, XTOC imports it automatically just like mesh ingress.
- Huge differentiator: structured off-grid data can ride over
APRS,JS8Call,FLDIGI, orVarACand land in the TOC as real packet data instead of loose chat text. - Per-program subpages: operators can open
Digi Modes -> APRS,Digi Modes -> JS8Call,Digi Modes -> FLDIGI, orDigi Modes -> VarACand keep each bridge separate and easy to supervise. - How it works: each subpage talks to a small local bridge/helper, shows bridge health plus raw traffic/debug data, and auto-imports complete
X1...wrappers into the normal XTOC packet store. - APRS workflow: create a provisioning QR for field devices, connect through
aprs-bridge, and move clearXTOCpacket lines over APRS with direct send and auto-import. - VarAC is the HF game changer:
varac-bridgereads inbound chat, broadcasts, and VMail directly fromVarAC.db, opening a practical long-range HF path that can bring distant or even international traffic straight into the TOC. - Live inbound display: operators can watch all bridge traffic in one place while the TOC stays focused on the map and timelines.
- Automatic packet recovery: multipart XTOC packets received over Digi Modes are buffered, reassembled, deduped, and imported into the timeline + map.
- Alertable radio traffic: Time/Triggers can alert on recent
JS8Call,FLDIGI, orVarACtraffic by text, callsign, station tag, or packet snippet, while APRS traffic stays visible in the APRS subpage log. - Simple setup: launch
aprs-bridgefor theAPRSsubpage, enable theJS8CallAPI server and launchjs8call-bridgeforJS8Call, launchfldigi-bridgeforFLDIGI, or launchvarac-bridgeon the same host asVarACfor theVarACsubpage.
NEW: Radios workbench / SDR go-box
XTOC now includes a Radios page that behaves like a compact three-bay SDR go-box inside the browser. Operators can place scanner, HF, and dual-band 2m / 70cm control heads in any bay, keep separate state per bay, and swap panel styles without losing the stored setup for the others. The active bay drives a headless local receiver helper instead of a separate desktop SDR app.
- Three independent bays: top, middle, and bottom positions can each be scanner, HF, or dual-band, and each bay keeps its own stored tuning and front-panel state.
- Working control heads: scan/search, VFO/memory workflows, AGC/filter or tone/offset controls, and direct-entry numeric keypads are wired into the browser UI.
- Simple operator path: plug in the RTL-SDR, assign WinUSB with Zadig if needed, run
radio-helper/windows/Start-XTOC-Radio.bat, openRadios, choose the live bay, and clickListenfor browser audio. - Receiver setup on the page: each bay exposes Front panel, USB source, Coverage, and Backend selectors, while RTL-SDR sources add sample rate, audio rate, gain, ppm, and direct sampling controls.
- Status + audio visibility: helper, radio, audio, and error lines stay visible at the top, with live VU indication and browser output selection where supported.
- Current hardware note: the UI already models future SDR source assignments, but the present headless helper implementation is RTL-SDR receive via
rtl_fmonly.
Quick start
index.html (for example: reticulum-bridge/, halow-bridge/, aprs-bridge/, js8call-bridge/, fldigi-bridge/, varac-bridge/, atak-helper/). Open each folder’s README.md for run instructions.video-helper/ with a launcher-first Windows helper, so the TOC can bring RTSP/ATAK video feeds online without asking operators to set up Python.aprs-bridge/ for APRS, js8call-bridge/ for JS8Call, fldigi-bridge/ for FLDIGI, and varac-bridge/ for VarAC, giving the TOC bridge-backed APRS packet movement plus fully supported digital-mode ingest with automatic packet import, live traffic logs, and program-specific triggers/debug tools.radio-helper/ with a launcher-first Windows headless receiver helper. Start radio-helper/windows/Start-XTOC-Radio.bat, open Radios, choose the live bay, and click Listen. Current headless receive support is RTL-SDR.1) Install for offline use (recommended)
- iPhone/iPad: Safari → Share → Add to Home Screen
- Android: Chrome menu → Install app
- Desktop: Chrome/Edge install icon → Install
2) Set up your team
- Open Team and add members (Unit ID, label/callsign, role, optional color). Optional: create Squads and assign members.
- Use Unit IDs for addressing and deconfliction across the net.
3) Create and move packets
- Open Comms.
- Create SITREP / TASK / CONTACT / RESOURCE / ASSET / ZONE / PHASE LINE / MISSION / EVENT / CHECKIN packets (Source Unit(s) supports multi-select; CHECKIN supports multi-unit; optional Squad quick-pick fills unit lists).
- Export via Copy or QR, then send using your chosen transport.
- Receiver uses Import (paste text or scan QR).
- Optional auto-ingest: when wrapper lines are received over Mesh (Meshtastic/MeshCore), MeshChat (Reticulum), or Digi Modes (
APRS/JS8Call/FLDIGI/VarAC), XTOC™ can auto-decode and update the log + map (no manual steps). - MeshChat (Reticulum/RNode) (new): run
reticulum-bridgeon the TOC laptop (connected to the RNode), connect XTOC MeshChat, then share a QR to field devices (XCOM MeshChat → Scan Bridge QR). - Digi Modes (new): for
APRS, runaprs-bridgeand open Digi Modes -> APRS to connect, share the provisioning QR, and move packet lines over APRS; forJS8Call, enable the API server and runjs8call-bridge; forFLDIGI, runfldigi-bridge; forVarAC, runvarac-bridgeon the same host as the VarAC radio app or pass--varac-dbif the database is elsewhere. Then open the matching Digi Modes subpage to monitor inbound traffic, inspect bridge/debug status, and auto-import any embeddedX1...packets. - Radios (new): plug in the RTL-SDR, use Zadig / WinUSB if the driver is wrong, run
radio-helper/windows/Start-XTOC-Radio.bat, open Radios, click Drive Headless RX on the bay you want, then click Listen for browser audio. Use the RTL-SDR backend controls above the radio face to set sample rate, audio rate, gain, ppm, and direct sampling.
4) View the operational picture
- Timeline pages show your local log by template (SITREPs, TASKs, etc.).
- Tactical Map shows member locations, packet markers when location is present, shared Zones as shaded areas, and Phase Lines as line overlays.
- Video ISR gives the TOC live video on demand: scan RTSP feeds, merge ATAK video cues, watch the stream, inspect metadata, and capture screencaps from one board.
Backups / moving to another device
Use the top-bar Export / Import to move your saved dataset (members, squads, packets, keys, settings) as a JSON
file—without the offline tile cache.
Modes: CLEAR vs SECURE
CLEAR (default)
- Designed to be compact and openly decodable.
- Good for ham-radio-adjacent workflows, relays, and public channels.
- Confidentiality is not provided.
Secure Session (optional)
- One-time challenge/response link (operator → TOC) that creates a short-lived session.
- After linking, packets are signed so the TOC can verify authenticity and reject replays/forgeries.
- Works with CLEAR or SECURE and over any transport (mesh, SMS, email, QR, relay).
SECURE (optional)
- Encrypted payload for non-amateur-radio transports.
- Uses a shared team key (KID/key id) and fails closed on tampering.
- Keys are shared via QR “key ceremony” and can be rotated.
How encryption works (SECURE mode)
This section explains what XTOC™ does in SECURE mode so operators understand the properties and limitations.
- What is encrypted: only the packet payload (the structured report bytes). The header stays readable so packets can be routed/relayed and multipart chunks can be reassembled.
- Algorithm: XTOC™ uses XChaCha20-Poly1305 (AEAD). AEAD provides both confidentiality and integrity (tamper detection). In constrained channels, XTOC™ may use a compact ChaCha20-Poly1305 variant to save characters (still AEAD).
- Team key: a shared 32‑byte symmetric key. Everyone who should decrypt must possess the same key. Keys are versioned by KID (key id) so teams can rotate keys over time.
- Nonce: each SECURE packet uses a fresh random nonce. The nonce is not secret and is stored with the ciphertext.
- Header binding (AAD): XTOC™ binds important header fields as associated data so changes to template id, message id, part numbers, or KID will cause decryption to fail.
- Encoding: the encrypted bytes are encoded as base64url (ASCII‑safe) so they can travel via SMS/email/mesh text without “+ / =” characters.
SECURE packet format
X1.<T>.S.<ID>.<P>/<N>.<KID>.<PAYLOAD>
T = template id (SITREP, CHECKIN/LOC, etc.)
ID = message id (used for dedupe + multipart reassembly)
P/N = part number / total parts
KID = key id (selects which team key to use)
PAYLOAD = base64url( versionByte || nonce || ciphertext+tag )
Mapping & offline basemaps
XTOC™ includes a Tactical Map for quick situational awareness. Member locations update via store-and-forward packets (no live
tracking server). When location is included in a report, it can appear as a marker.
With mesh receive enabled, packets are decoded and applied automatically so the map + log update themselves as messages arrive.
Mesh + OpenMANET node mapping
- Plot Meshtastic/MeshCore GPS packets and OpenMANET node positions as map markers.
- Assign a heard node to a roster member so the member’s last-known location can update from that node.
MeshChat (Reticulum / RNode)
- Run Reticulum (RNS) on the TOC laptop (or a bridge host) and connect an RNode over serial/Bluetooth.
- Start the bundled
reticulum-bridge, then connect XTOC/XCOM MeshChat over a trusted LAN (QR provisioning supported). - Where to find it: after unzipping, look for
reticulum-bridge/next toindex.html(seereticulum-bridge/README.md). - Send XTOC packet lines over Reticulum using broadcast or direct (DM) and optionally auto-ingest them into the log + map.
SATCOM (satellite tracking) — native in the app
- Load TLEs by paste, file import, or direct download from Celestrak.
- Includes a HAM-focused “Amateur Radio” list and other subsets (stations, weather, nav, etc.).
- Filter before you render: download large sets, but only select a small subset to show on the map so performance stays smooth.
- Built-in guardrail: Tactical Map caps the number of satellites rendered at once to prevent overload.
ATAK integration
- File exchange: import/export KML/KMZ overlays (“data package” style workflows).
- Live CoT gateway (optional): run the bundled
atak-helperon a TOC laptop to bridge ATAK ↔ XTOC™ CoT.
XTOC™ can ingest CoT as CHECKINs and can broadcast Team/Missions/Zones back out as CoT.
Offline basemap (raster caching)
- Switch the basemap to Offline Raster (cached).
- Download tiles for your AOI while online.
- Those cached tiles remain available offline for that area/zoom range.
Note: public tile servers have usage policies. For serious use, point XTOC™ to your own tile server.
Design principles
-
- No backend: no central service required for storage, sync, or routing.
- Transport-agnostic: packets must survive copy/paste and character limits.
- Short by design: compact schemas, packet sizing, and chunking for constrained channels.
- QR-first: fast, reliable transfer between phones/PCs in the field.
- Local-first: your device owns its own data; it continues to work offline.
CLEAR packet format (public, ham-friendly)
CLEAR packets are designed to be openly decodable by anyone. There are no keys and no hidden fields.
The payload is compact, but it is not “secret”: it’s just structured data encoded into safe ASCII characters.
S) on amateur radio. CLEAR (mode C) is the ham-friendly mode.1) The outer wrapper (human-visible header)
Every XTOC packet is a single line of text with dot separators. This header makes it easy to route, relay, and reassemble multipart messages.
X1.<T>.<M>.<ID>.<P>/<N>.<PAYLOAD>
X1 = literal protocol marker (version 1)
T = template id (decimal). Examples: 1=SITREP, 4=CHECKIN/LOC
M = mode: C=CLEAR, S=SECURE (non-ham)
ID = message id (Crockford-like Base32, used for dedupe/reassembly)
P/N = part number / total parts (1-indexed). Example: 2/3
PAYLOAD = encoded payload (for CLEAR this is base64url text)
Multipart packets: all parts share the same T, M, and ID. Only P/N changes, and the payload is split across parts.
To reassemble, concatenate payload pieces in part order (1..N).
2) The CLEAR payload encoding (ASCII-safe)
The CLEAR payload is binary structured data that is encoded using base64url so it can be carried in SMS/email/mesh text
without punctuation problems:
- Characters used:
A–Z a–z 0–9 - _(no+,/, or trailing=). - Decoding step: convert base64url to bytes, then interpret bytes per the template schema below.
- This is not encryption. Anyone can decode it with this page/spec.
3) Common fields and conventions (applies to all CLEAR templates)
- Endianness: multi-byte integers are big-endian (network byte order).
- Time: timestamps are stored as
unixMinutes= minutes since Unix epoch (UTC). Convert witht = unixMinutes * 60,000(ms). - Coordinates:
latE5andlonE5are signed int32 values of degrees × 100,000.
Example:lat = latE5 / 100000. - Flags: many templates include a flags byte. Bits indicate optional sections like location or note text.
- Text: note/label text is UTF‑8 with a 1-byte length prefix (
u8).
4) Public codebooks (small enums)
- Priority (
pri):0=P1,1=P2,2=P3,3=UNK - Status:
0=OK,1=HELP,2=RTB,3=UNK - Event status (EVENT):
0=PLANNED,1=ACTIVE,2=COMPLETE,3=CANCELED,4=UNKNOWN - Phase line status (PHASE LINE):
0=PLANNED,1=ACTIVE,2=CROSSED,3=CLOSED - Phase line kind (PHASE LINE):
0=PHASE_LINE,1=LD,2=LC,3=LOA - Line style (PHASE LINE):
0=SOLID,1=DASHED,2=DOUBLE - Bearing: in CONTACT,
diris in 10-degree steps:bearingDeg = dir * 10
5) Template IDs (what T means)
T=1— SITREPT=2— CONTACTT=3— TASK / REQUESTT=4— CHECKIN / LOCT=5— RESOURCE / REQUESTT=6— ASSETT=7— ZONE (area marking)T=8— MISSIONT=9— EVENTT=10— PHASE LINET=11— SENTINELT=12— ROUTET=13— MESSAGET=14— AUTH_REQ (Secure Session)T=15— AUTH_CHAL (Secure Session)T=16— CONTROLT=50..99— CUSTOM (user-defined templates)
6) Per-template binary schemas (CLEAR)
The schemas below describe the decoded byte layout after base64url decoding the payload.
T=4 — CHECKIN/LOC
// layout v1 (single unit, 16 bytes total)
[0] u8 version = 1
[1..2] u16 unitId
[3..6] i32 latE5
[7..10] i32 lonE5
[11..14] u32 unixMinutes
[15] u8 status (0=OK,1=HELP,2=RTB,3=UNK)
// layout v2 (multi-unit / squad check-in)
[0] u8 version = 2
[1] u8 unitCount (1..32)
[2..] repeated unitCount: u16 unitId
[..] i32 latE5
[..] i32 lonE5
[..] u32 unixMinutes
[..] u8 status (0=OK,1=HELP,2=RTB,3=UNK)
New: CHECKIN/LOC can include multiple Unit IDs for squad/group check-ins (Comms -> Units multi-select). Older builds that only support v1 will reject v2.
T=1 — SITREP
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3..4] u16 dst
[5] u8 pri (0..3)
[6] u8 status (0..3)
[7..10] u32 unixMinutes
[11] u8 flags: bit0 hasLoc, bit1 hasNote, bit2 hasSrcIds
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
T=2 — CONTACT
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3] u8 pri (0..3)
[4..7] u32 unixMinutes
[8] u8 typeCode
[9..10] u16 count
[11] u8 dir (0..35) // bearingDeg = dir*10
[12] u8 flags: bit0 hasLoc, bit1 hasNote, bit2 hasSrcIds
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
T=3 — TASK / REQUEST
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3..4] u16 dst
[5] u8 pri (0..3)
[6..9] u32 unixMinutes
[10] u8 actionCode
[11..12] u16 dueMins
[13] u8 flags: bit0 hasLoc, bit1 hasNote, bit2 hasSrcIds
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
T=5 — RESOURCE / REQUEST
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3] u8 pri (0..3)
[4..7] u32 unixMinutes
[8] u8 itemCode
[9..10] u16 qty
[11] u8 flags: bit0 hasLoc, bit1 hasNote, bit2 hasSrcIds
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
T=6 — ASSET
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3] u8 condition (0=FUNCTIONAL,1=NONFUNCTIONAL,2=UNKNOWN,3=UNK)
[4..7] u32 unixMinutes
[8] u8 typeCode
[9] u8 flags: bit0 hasLoc, bit1 hasLabel, bit2 hasNote, bit3 hasSrcIds
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8)
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
T=7 — ZONE (area marking)
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3] u8 threat (0=SAFE,1=DANGER,2=UNKNOWN)
[4] u8 meaningCode (0..255) // team-defined meaning codebook
[5..8] u32 unixMinutes
[9] u8 flags: bit0 hasLabel, bit1 hasNote, bit2 shapeIsCircle (else polygon), bit3 hasSrcIds
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 48)
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8, max 120)
if shapeIsCircle:
[..] i32 centerLatE5
[..] i32 centerLonE5
[..] u16 radiusM
else (polygon):
[..] u8 nPoints (3..32)
repeat nPoints:
[..] i32 latE5
[..] i32 lonE5
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
Notes:
- Polygon is implicitly closed (last point connects back to first).
- Coordinates use degrees × 100,000 (latE5/lonE5).
T=8 — MISSION
// layout v1
[0] u8 version = 1
[1..4] u32 updatedUnixMinutes
[5..8] u32 createdUnixMinutes
[9] u8 statusCode (0=PLANNED,1=ASSIGNED,2=IN_PROGRESS,3=ON_HOLD,4=COMPLETE,5=ABORTED)
[10] u8 pri (0..3)
[11] u8 flags: bit0 hasAssigned, bit1 hasLoc, bit2 hasLocLabel, bit3 hasDue, bit4 hasNotes, bit5 hasAssignees
then:
[..] u8 idLen
[..] id bytes (UTF-8, max 32)
[..] u8 titleLen
[..] title bytes (UTF-8, max 96)
if hasAssigned:
[..] u16 unitId
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasLocLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 48)
if hasDue:
[..] u32 dueUnixMinutes
if hasNotes:
[..] u16 notesLen
[..] notes bytes (UTF-8, max 600)
if hasAssignees:
[..] u8 n
[..] repeated n: u16 unitId // extra assignees beyond assignedTo
T=9 — EVENT
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3..4] u16 dst
[5] u8 pri (0..3)
[6] u8 status (0=PLANNED,1=ACTIVE,2=COMPLETE,3=CANCELED,4=UNKNOWN)
[7..10] u32 unixMinutes (reportedAt)
[11] u8 typeCode (0..255)
[12] u8 flags: bit0 hasLoc, bit1 hasLabel, bit2 hasLocLabel, bit3 hasNote, bit4 hasStart, bit5 hasEnd, bit6 hasSrcIds
if hasStart:
[..] u32 startUnixMinutes
if hasEnd:
[..] u32 endUnixMinutes
if hasLoc:
[..] i32 latE5
[..] i32 lonE5
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 48)
if hasLocLabel:
[..] u8 locLabelLen
[..] locLabel bytes (UTF-8, max 48)
if hasNote:
[..] u8 noteLen
[..] note bytes (UTF-8, max 160)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
T=10 — PHASE LINE
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3] u8 status (0=PLANNED,1=ACTIVE,2=CROSSED,3=CLOSED)
[4] u8 kind (0=PHASE_LINE,1=LD,2=LC,3=LOA)
[5] u8 style (0=SOLID,1=DASHED,2=DOUBLE)
[6] u8 color (0..255)
[7] u8 flags: bit0 hasLabel, bit1 hasInstruction, bit2 hasStart, bit3 hasEnd, bit4 hasSrcIds, bit5 autoDetectCross
[8..11] u32 updatedUnixMinutes
[12..15] u32 createdUnixMinutes
then:
[..] u8 idLen
[..] id bytes (UTF-8, max 32)
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 48)
if hasInstruction:
[..] u8 instructionLen
[..] instruction bytes (UTF-8, max 160)
if hasStart:
[..] u32 startUnixMinutes
if hasEnd:
[..] u32 endUnixMinutes
[..] u8 nPoints (2..32)
repeat nPoints:
[..] i32 latE5
[..] i32 lonE5
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
PHASE LINE packets are line overlays (phase lines / LD / LC / LOA). The id is a stable string used for updates and dedupe.
T=11 — SENTINEL
// layout v1
[0] u8 version = 1
[1] u8 sensorCount (0..32)
[2..5] u32 unixMinutes
[6..9] i32 latE5
[10..13] i32 lonE5
[14..17] u32 nodeId
[18] u8 flags: bit0 alert, bit1 hasIo, bit2 hasLabel
if hasIo:
[..] u8 inMask
[..] u8 outMask
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 32)
repeat sensorCount:
[..] u8 type (0..255)
[..] i16 value // interpretation depends on type
SENTINEL packets are compact sensor-stack reports: node ID, location, time, optional IO bitmasks, an optional label, and up to 32 sensor readings.
T=12 — ROUTE
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3] u8 status (0=PLANNED,1=ACTIVE,2=COMPLETE,3=CANCELED)
[4] u8 typeCode (0..255)
[5] u8 flags: bit0 hasLabel, bit1 hasInstruction, bit2 hasStart, bit3 hasEta, bit4 hasEnd, bit5 hasSpeed, bit6 hasSrcIds
[6..9] u32 updatedUnixMinutes
[10..13] u32 createdUnixMinutes
then:
[..] u8 idLen
[..] id bytes (UTF-8, max 32)
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 48)
if hasInstruction:
[..] u16 instructionLen
[..] instruction bytes (UTF-8, max 400)
if hasStart:
[..] u32 startUnixMinutes
if hasEta:
[..] u32 etaUnixMinutes
if hasEnd:
[..] u32 endUnixMinutes
if hasSpeed:
[..] u16 speed10 // speedKph = speed10 / 10
[..] u8 nPoints (2..32)
repeat nPoints:
[..] i32 latE5
[..] i32 lonE5
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
ROUTE packets describe a polyline on the map (2–32 points) with optional label, instructions, schedule, and speed.
T=13 — MESSAGE
// layout v1
[0] u8 version = 1
[1..2] u16 src
[3..4] u16 dst (0 = ALL)
[5] u8 precChar (ASCII: Z/O/P/R)
[6] u8 msgType (0..255)
[7..10] u32 unixMinutes
[11] u8 flags: bit0 hasSubject, bit1 hasSrcIds
if hasSubject:
[..] u8 subjectLen
[..] subject bytes (UTF-8, max 80)
[..] u16 textLen
[..] text bytes (UTF-8, max 1400)
if hasSrcIds:
[..] u8 n
[..] repeated n: u16 unitId // extra unitIds beyond src
MESSAGE packets are typed or free-text messages (BULLETIN/BRIEF/EAM/etc) with precedence and an optional subject.
T=14 — AUTH_REQ (Secure Session)
// payload bytes decode to UTF-8 JSON (v1)
{
"v": 1,
"opId": "OP123",
"nonceB64Url": "<base64url(nonceBytes)>",
"ttlSec": 300,
"scopeRequest": "OPERATOR"
}
AUTH_REQ starts a Secure Session handshake. It must be sent as CLEAR (mode C).
T=15 — AUTH_CHAL (Secure Session)
// payload bytes decode to UTF-8 JSON (v1)
{
"v": 1,
"opId": "OP123",
"nonceB64Url": "<base64url(nonceBytes)>",
"ttlSec": 300,
"scopeGranted": "OPERATOR",
"proofB64Url": "<base64url(8-byte proof)>"
}
AUTH_CHAL is the TOC response to AUTH_REQ. When accepted, XTOC and XCOM derive a session key for Secure Session signed envelopes.
T=16 — CONTROL
// layout v1
[0] u8 version = 1
[1..4] u32 nodeId
[5..8] u32 unixMinutes
[9] u8 flags: bit0 ackRequested, bit1 hasOut, bit2 hasLabel, bit3 hasControls
if hasOut:
[..] u8 outOp (0=ABS,1=SET,2=CLEAR,3=TOGGLE)
[..] u8 outMask (0..255)
if hasLabel:
[..] u8 labelLen
[..] label bytes (UTF-8, max 32)
if hasControls:
[..] u8 controlCount (0..32)
repeat controlCount:
[..] u8 type (0..255)
[..] i16 value // interpretation depends on type
CONTROL packets are command messages intended to control Sentinel node outputs (outMask) and optional typed control actions.
Recommendation: send CONTROL commands as SECURE in real deployments.
T=50..99 — CUSTOM (user-defined templates)
// layout v1 (schema-driven)
[0] u8 schemaVersion
[1..] u8 optMask[...] // length = ceil(optionalFieldCount / 8)
then fields in schema order:
for each field:
if field is optional and its optMask bit is 0: field omitted
else encode by type:
u8 -> u8
u16 -> u16
u32 -> u32
i32 -> i32
unixMinutes -> u32 unixMinutes
locE5 -> i32 latE5 + i32 lonE5
text -> u8 len + UTF-8 bytes
u16list -> u8 count + repeated u16
Notes:
- optMask bits correspond to optional fields only (in template order), not all fields.
- Decoding requires the matching custom template definition (shared as an XTOC-TPL token).
Custom templates let you define your own compact schema and share it as XTOC-TPL.<base64(json)>. Use any template ID in 50..99.
7) How to decode a CLEAR packet (plain-English steps)
- Collect parts: if you received multiple lines with the same
ID, ensure you have all parts1/NthroughN/N. - Reassemble: sort by part number, then concatenate the
PAYLOADtext from each part (no separators). - Base64url decode: convert the payload text into raw bytes (base64url → bytes).
- Interpret bytes: use the schema for that template (
T) to read fields from the byte array. - Convert units: apply the time and coordinate conversions described above.
S) on amateur radio.



























