codeplugger Español GitHub ↗

Open source · Chicago Offline

Programming a radio should be a build, not a CPS session.

codeplugger combines shared RF facts with your version-controlled profile to build a validated, radio-neutral codeplug. Export it, or write it directly to a supported radio.

codeplugger logo: a handheld radio with a code glyph on its screen and plug prongs at its base

How it works

Facts and preferences stay separate. RF data describes what exists; a profile describes what you want in a particular radio. Everything in between is deterministic and reviewable.

SSRF data

Public channel plans, repeaters, and talkgroups from SSRF-Lite, merged with shared or private overlays by stable record ID.

Profile

Your policy in YAML: which assignments, in what order, in which zones, with scan lists, RX groups, contacts, and radio settings. Profiles can inherit from one another.

Resolve & validate

codeplugger joins the inputs and checks every channel against the target radio's capabilities: bands, modes, name lengths, zone and list limits, firmware-dependent capacity.

Export or program

Export CHIRP CSV or qdmr YAML; apply a profile to a decoded P4 baseline for TOML; or use a gated backend to write a supported radio.

Prebuilt community codeplugs

CI builds these from public community profiles and RF data as the sources change, then publishes import files, printable references, and SHA-256 checksums. No codeplugger install is needed.

Supported radios

The table combines radio capabilities with checked-in export and hardware-verification details. Its generator checks that every radios/*/capabilities.json entry has a matching row.

Radio Modes CHIRP CSV export qdmr import YAML p64tool import TOML OEM CPS import vendor files Headless write direct to radio
Baofeng DM-32 DM-32UV 2 codeplugs DMR · FM · AM RX Not supported Supported Not supported Not supported dmrconfhw
Baofeng DM-1701 DM-1701 / RT84 DMR · FM Not supported Supported Not supported Not supported dmrconfhw
Retevis MateTalk P4 UHF DMR DMR · FM Not supported Not supported Supported Not supported p64toolhw
Baofeng UV-5R Mini UV-17Pro family 2 codeplugs FM · AM RX Supported Not supported Not supported Not supported chirp-writer
Baofeng BF-C50 70 cm, no display FM Supported Not supported Not supported Not supported no CHIRP driver
Baofeng BF-888S UHF, no display 2 codeplugs FM Supported Not supported Not supported Not supported chirp-writer
Baofeng BF-1909 UHF, no display Codeplug FM hw Not supported Not supported Not supported chirp-writerhw
Baofeng W31E UHF, no display FM Supported Not supported Not supported Not supported chirp-writer
Ailunce HA2 Dual-band analog FM · AM RX Supported Not supported Not supported Not supported chirp-writer
Retevis C64 Dual-band analog FM hw Not supported Not supported Not supported chirp-writer
Retevis RT3S (OpenGD77) MD-UV380 family, OpenGD77 DMR · FM Not supported Supported Not supported Not supported dmrconfhw
Baofeng DM-1701 (OpenGD77) MD-UV380 family, OpenGD77 DMR · FM Not supported Supported Not supported Not supported dmrconf
Vero VR-N76 Dual-band, Bluetooth FM · AM RX Not supported Not supported Not supported Not supported benlink
BTECH UV-Pro Dual-band, Bluetooth 2 codeplugs FM · AM RX Not supported Not supported Not supported Not supported benlink
Yaesu FT-270R 2 m submersible FM as VX-170 Not supported Not supported Not supported chirp-writer
Yaesu FT-270R (MARS/CAP) TX-modded variant FM as VX-170 Not supported Not supported Not supported chirp-writer
Yaesu FT-277R 70 cm submersible FM as VX-177hw Not supported Not supported Not supported chirp-writer
Yaesu FT-277R (MARS/CAP) TX-modded variant FM as VX-177 Not supported Not supported Not supported chirp-writer
Yaesu FT-2800M 2 m mobile FM hw Not supported Not supported Not supported chirp-writerhw
Yaesu FT-2800M (extended TX) TX-modded variant FM Supported Not supported Not supported Not supported chirp-writer
Yaesu VX-6R Tri-band submersible FM · AM RX as VX-6 Not supported Not supported Not supported chirp-writer
Yaesu VX-6R (MARS/CAP) TX-modded variant FM · AM RX as VX-6 Not supported Not supported Not supported chirp-writer
TYT TH-9800 Quad-band mobile FM · AM RX experimental driver Not supported Not supported Not supported chirp-writer
TYT TH-9800 (extended TX) TX-modded variant FM · AM RX experimental driver Not supported Not supported Not supported chirp-writer
Quansheng UV-K5 (F4HWN) Quansheng UV-K5 (F4HWN) FM · AM RX Supported Not supported Not supported Not supported chirp-writer

hw verified against a physical radio · supported today · not applicable or not implemented

CHIRP CSV

Analog FM and receive-only AM channels in profile order, checked against radio limits. Import and upload in CHIRP where a driver exists, or use chirp-writer on supported radios.

qdmr YAML

Extensible qdmr codeplug with zones, scan lists, RX group lists, contacts, and multiple DMR IDs. Radio-native settings pass through extensions.qdmr.

p64tool TOML

Applied to a p64tool decode baseline so untouched settings survive, then re-encoded for the P4.

benlink plan

A declarative channel plan for Benshi-protocol handhelds, which have no desktop CPS and no CHIRP driver — the only path in is over Bluetooth. Zones map onto the radio's regions, and regions the plan omits are never written.

Headless write

Writes require explicit confirmation and backend-specific safety checks. Backup and read-back support vary; operations can be logged. Backends: dmrconf, p64tool, chirp-writer, and Bluetooth benlink.

Planned: expand radio and export-format coverage without changing core profile resolution.

Features

Built for people who keep more than one radio consistent, and want to know exactly what went into each one.

Deterministic builds

The same inputs always produce the same codeplug, down to a stable SHA-256. Generated files are disposable artifacts, never a data source.

Capability validation

Bands, TX-vs-RX-only ranges, modes, bandwidth, name lengths, zone and list limits, and firmware-dependent contact capacity, graded hint / warning / critical with every critical reported in one run.

Gated radio writes

Explicit confirmation, backend-specific identity checks, and write logs; pre-write and read-back verification where available.

Zones, scan lists, RX groups, contacts

Talkgroups are SSRF facts; membership and per-assignment TX contact, RX group, and scan list are profile policy, all enforced against radio limits.

Profile inheritance

Share a base profile and derive variants with extends, zones_only, and omit_zones. A base that names no radio is reusable on any radio with the capacity for it. Review the merged result with --print-merged-profile.

Multi-identity DMR IDs

A radio instance can carry several DMR IDs; profiles bind one per zone or per assignment and exporters emit only the identities actually used.

Fleet registry & dry run

An instance registry maps physical radios to profiles. codeplugger-fleet resolves and validates every radio and reports readiness before anything is written.

Derived channel facts

Bandwidth from the ITU emission designator, AM mode for airband receive-only assignments, display-name overrides from overlays.

Reference artifacts

HTML and Markdown channel references plus operation logs per radio instance, so what is in the radio is always documented.

Namespaced extensions

Exporter-native settings live under extensions.<backend> at profile or assignment level, keeping the core schema radio-neutral.

How the data flows

Public RF data and overlays feed a profile-based build; export a file or program a supported radio.

flowchart LR
  rf["📡 rf-survey"] -- "reception reports" --> ssrf["🗃 ssrf-lite"]
  ov["overlays · shared + private"] --> ssrf
  ssrf -- "validated RF data" --> cp["⚙ codeplugger"]
  prof["👤 profiles"] --> cp
  cp -- "export: CHIRP CSV · qdmr YAML · P4 TOML · benlink plan" --> files(["radio files"])
  files --> radios(["📻 radios"])
  cp -- "write: dmrconf · p64tool · chirp-writer · benlink" --> radios
  click rf "https://chicago-offline.github.io/rf-survey/" _blank
  click ssrf "https://chicago-offline.github.io/ssrf-lite/" _blank
  click cp "https://chicago-offline.github.io/codeplugger/" _blank
  click prof "https://chicago-offline.github.io/chioff-codeplugger-profiles-shared/" _blank
        

Quick start

Clone codeplugger and use uv. The install brings its own RF data, so a use case needs nothing else; profiles of your own want ssrf-lite and a profile repository checked out alongside.

Program a new radio

# what is supported, and what can go on it
uv run codeplugger radios
uv run codeplugger use-cases

# compile, without touching hardware
uv run codeplugger build \
  --radio baofeng_bf888s --use-case gmrs

# or a community group's channels, by name
uv run codeplugger build \
  --radio baofeng_bf888s --profile chioff

# then write it, gated by the backend
uv run codeplugger program \
  --radio baofeng_bf888s --use-case gmrs \
  --port /dev/cu.usbserial-10 --confirm

Validate a profile

uv run codeplugger-profile path/to/profile.yml \
  --ssrf-root ../ssrf-lite/ssrf \
  --ssrf-root ../chioff-ssrf-shared/ssrf

Export for a radio

# analog radios: import in CHIRP
uv run codeplugger-profile profile.yml \
  --ssrf-root ../ssrf-lite/ssrf \
  --output-format chirp-csv > output.csv

# DM-32: qdmr YAML, then dmrconf write
uv run codeplugger-profile profile.yml \
  --ssrf-root ../ssrf-lite/ssrf \
  --output-format qdmr-yaml > codeplug.yaml

Check the whole fleet

uv run codeplugger-fleet \
  --instance-registry ../my-profiles/instances.yml \
  --profiles-root ../my-profiles/profiles \
  --ssrf-root ../ssrf-lite/ssrf

A minimal profile

version: "0.1"
id: "dm32_reference"
name: "DM-32 reference"
radio: "baofeng_dm32"
radio_instance: "dm32_green_01"
zones:
  - id: "community"
    name: "Community"
    assignments:
      - "asg_chio_all"
      - "asg_chio_road"
      - "asg_chio_repeater"