CLI tool
DSheirer/sdrtrunk avatar
DSheirer/sdrtrunk

sdrtrunk, a trunked radio decoder whose current build is a rolling tag

A cross-platform java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using Software Defined Radios (SDR). Website:

2,196 stars364 forksJavaGPL-3.0

At a glance

What is it?
sdrtrunk decodes, records and streams trunked mobile radio through a software defined radio, and it is the most complete tool in that space. Two things in this repository are worth reading before you install it: the last final release is version 0.6.1 from December 2024, so the current code ships on a nightly tag that moves on every commit, and the top of the README is a workaround for macOS 26 breaking the USB path entirely.
Who is it for?
Install sdrtrunk from the nightly tag if you need a trunked radio decoder, because the last final release predates current macOS and the newest hardware by more than a year, and copy your playlist files before you do since the author warns that the rolling tag can change under you.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What it decodes, and the four verbs in the description

sdrtrunk is described in four verbs, and each one is a different use of the same machinery.

Decoding is the core. The application takes radio samples from a software defined radio and works out what protocol is on the air, so that a digital voice transmission becomes audio. Monitoring is the same thing run continuously, watching a set of frequencies and following the control channel of a trunked system. Recording is decoding with a file written out, and streaming is decoding forwarded somewhere else.

The subject is trunked mobile and related radio protocols, and that phrase carries the important technical content. A trunked system is how public safety and commercial fleets share a single frequency pair: one control channel tells every radio on the system which voice channel to move to next, and the voice traffic follows. A decoder that follows the control channel and tunes the voice channels itself is following a conversation across a hopping frequency plan, which is why the application needs a control channel decoder and a voice channel decoder and a way to keep them in step.

That is a genuinely hard signal-processing problem, and it is why an application like this is worth an article. You are not filtering frequencies. You are implementing the signalling of several digital radio standards in reverse, which is reverse engineering applied to radio airwaves, and the standards are documented unevenly and implemented by different manufacturers with different choices.

The platform story is broad, described as cross-platform and covering Windows, Linux and Mac, and the hardware requirement is a software defined radio rather than a conventional receiver. A conventional receiver cannot do this, because decoding needs the raw samples, not the demodulated audio.

Where the documentation lives is the other thing to notice. The repository README is short and its links go to a wiki with a home page, a getting started page, a user's manual and a support page. For an application with this much surface, a wiki maintained alongside the code is a reasonable choice, and it also means the README you read on the forge is not the documentation.

Twenty-one months past the last final release, on a tag that never stops moving

The release history is three entries and the shape of them is the maintenance story.

The newest final release is version 0.6.1, published on 2024-12-03, after a beta in November. The last push to the repository was on 2026-09-26. So there are roughly twenty-one months of development past the newest packaged release, in a project whose only other release channel is a tag named nightly whose own date is 2023-11-06.

That nightly date needs explaining, and the README explains it. The nightly release is updated each time code changes are committed, so it is not really nightly as much as it is current. In other words, the tag is a moving pointer to the latest build rather than a dated artefact, and the date attached to it is when the tag was created. Anyone reading the release list and concluding that the nightly build is three years stale would be wrong, and anyone relying on the tag's date for any kind of reproducibility would also be wrong.

The three-channel scheme is well documented and worth quoting in substance. Alpha versions are under development feature previews and likely to contain bugs and unexpected behaviour. Beta versions are being tested for bugs and functionality before a final release. Final versions have been tested and are the current release version. That is a clearer staging policy than most projects state.

The consequence is a project with an unusually long gap between its tested release and its current code, which is a signal worth weighing. It may mean the release process has stalled while the work continues, which is the commonest explanation and the least alarming. It may mean the author is maintaining it primarily against new hardware and new operating system versions, which the macOS section below supports, and releasing only when something forces a decision. Or it may mean the project is in a slow decline where commits continue but releases have stopped, which the last push date argues against.

A reader should not have to guess. The changelog at the top level would answer it, and the repository has one, though it carries no file extension, which is the older naming convention rather than an oversight.

The macOS USB break, and a symlink into a hard-coded path

The first thing in the README is a warning, and it is placed above the project title rather than in a troubleshooting section, which tells you how current the problem is.

Changes to USB support in a recent macOS release cause sdrtrunk to fail to launch. The application does not start. The fix, in the author's own steps, is to install libusb from the development version rather than the packaged one, create a directory structure that the older native binding expects, and then place a symbolic link where that binding looks for the library.

The first step:

bash
brew install libusb --HEAD

The development version rather than the stable one, because the stable build does not have whatever the new macOS needs. Then some directories, which is the older Unix convention for a locally-installed library tree and exists here because the native binding looks there:

bash
cd /opt
sudo mkdir local
cd local
sudo mkdir lib

And then the symlink itself, from wherever Homebrew actually put the library to the path the binding expects:

bash
sudo ln -s /opt/homebrew/Cellar/libusb/HEAD-9ceaa52/lib/libusb-1.0.0.dylib /opt/local/lib/libusb-1.0.0.dylib

Three things about that line are worth pausing on. It requires a Homebrew installation from the development branch, which means a library version that can change under you when Homebrew updates. It requires root. And the source path contains a hash that is specific to one particular build of that library, so the command as written works once and then breaks for everyone else, which is why the surrounding prose has to tell you to find your own path. The trailing sentence concedes that issues may remain with the application accessing USB tuners on that platform.

Then there is the release recommendation that follows from all of this: use the nightly build, because it includes an updated native library with ARM support for the affected macOS version. So the fix for the current operating system ships only in the untagged rolling build, and the final release from December 2024 will not work on it. That is the practical shape of this project's maintenance, and it is the single most useful fact on the page.

Back up your playlists before you run a nightly, and the author says so twice

The nightly section contains the most sensible warning in the README, and it is worth repeating because it tells you what kind of software this is.

The nightly release contains current builds for all supported operating systems, and the README says it may contain bugs and may not run correctly. Its purpose is to let you preview the most recent changes and fixes before the next release. And then, in bold: always back up your playlists before you use the nightly builds.

A warning in bold, about data loss, in a project whose published releases are fine, tells you the author has seen the nightly build destroy a user's configuration. What a playlist is in this application is not documented in the excerpt, but from the application's purpose it is a saved list of frequencies, systems and decode settings, which in practice is the entire setup work of a user who monitors a dozen systems. Losing it means re-tuning everything by hand.

Why would a nightly build destroy it? The most likely mechanism is a schema change: a settings format is revised, the new build writes the new format, the old build cannot read it back, and there is no migration path. That is the ordinary failure mode for an application with twenty months of unversioned development, and it is exactly the reason the author says to back up rather than merely to expect bugs.

The second half of the warning is about what nightly means. Because the tag moves on every commit, the build you run today is not the build you ran last week, and it is not the build you will get tomorrow. So the tag is not a version. It is a pointer, and the only way to have a fixed version of the current code is to save the build you are happy with, which is a slightly odd thing to tell a user of a nightly channel and an entirely reasonable one.

For an evaluator this is the practical risk to plan around. If you are going to use this application, decide early whether you are a user of the final release, which is stable and older, or a user of the rolling build, which is current and moves, and keep backups in either case.

Gradle, a copyright template, and an IDE project checked into the repository

The build configuration is conventional and one entry in it is worth more attention than the others.

There is a Gradle build with a wrapper, a settings file, a properties file, and a single source directory. Two GitHub Actions workflows exist, one for the Gradle build and one for the nightly releases, which matches the release model exactly: continuous integration produces the rolling build, so the nightly is not a separate process that has to be remembered.

The entry that matters is a copyright template file at the top level. That is a template for a source-file licence header, and its presence means the project enforces licence headers on its source, which is a practice you see in corporate and government-adjacent code and in long-lived GPL projects where the provenance of each file matters. For a project that has imported protocol implementations from several sources over years, tracking which code carries whose copyright is a real maintenance task rather than a formality.

The changelog carries no file extension, which is the older naming convention and the same habit appears in other long-lived GPL projects. It is not an error, and a script looking for CHANGELOG.md will not find it.

The other notable entry is a checked-in IDE project file alongside a checked-in IDE configuration directory, which is a practice that goes out of fashion and then comes back. The same file usually contains absolute paths, and a file with absolute paths in version control produces merge conflicts for every developer whose username is not the author's. Committing it is a trade: everyone gets the same project settings, and everyone fights over the diff.

The overall picture is a project with real infrastructure and small rough edges, which is a healthy combination. The build is automated, the release is automated, the licensing is tracked, and the documentation lives in a wiki rather than in a repository file that will go stale.

Minimum requirements, and 32-bit support struck through

The requirements are three lines and one of them contains a deletion.

Operating system: 64-bit Windows, 64-bit Linux, or a 64-bit Mac on version 12 or later. And in the README, the words 32-bit appear struck through in both the Windows and the Linux entries, which is a visible erasure rather than a silent change. Support for 32-bit Windows and 32-bit Linux has been dropped.

That is a meaningful change for this particular application, because software defined radio users are a population with a lot of older machines. A machine that was adequate for a narrowband receiver in 2015 may still be running, and for some of those users the last final release is the only build that will work at all. The strikethrough tells you that a new user on 32-bit should not bother.

The processor requirement is four cores, which is a modest ask for a Java application doing real-time signal processing. The memory requirement is 8 GB or more preferred, with a note that 4 GB may be sufficient depending on usage. The qualifier matters: an application decoding several simultaneous voice channels is doing real work continuously, and the memory cost scales with the number of active decoders rather than with the size of your library.

The Mac requirement of version 12 or higher is interesting next to the warning about a later version breaking USB. It means the project supports a wide range of macOS versions and has to work around a regression in the newest one, which is a very different problem from supporting only current systems. The Homebrew development-branch libusb install and the hand-placed symlink are the cost of that breadth.

So the requirements are not demanding in absolute terms, and the real constraint is the native library path. A machine that meets every stated requirement can still fail to launch on a current macOS without the four manual steps, and that is the practical limit on who this application serves today.

sdrtrunk against a bare signal program, and the legal line the tool does not draw for you

Two comparisons, and the second is the one that matters more than the first.

Against a bare software defined radio program, the difference is what sdrtrunk has already done for you. A raw receiver application gives you samples and maybe a demodulator. Everything above that, knowing which digital voice standard is on the air, following a trunked system's control channel, tuning to the assigned voice channel, decoding the audio codec, and presenting a conversation, is the work this project has done. For someone whose interest is trunked radio, that work is the entire value and it is not available anywhere else at this quality. For someone whose interest is signal processing as a subject, it is a large codebase to read rather than a tool.

Against a conventional scanner, the comparison is about the trunking. A scanner that scans frequencies will find a voice transmission and then lose it when the system moves to the next channel. sdrtrunk follows the signalling, so it stays on the conversation. That is the capability that distinguishes it, and it is also the capability that makes the recording and streaming features worth thinking about.

Which brings the second comparison, which is not with another tool but with the law and with the terms of the frequencies involved. Receiving a broadcast radio transmission is lawful in many jurisdictions, and monitoring public safety radio is a widespread practice in several countries with published guidance about it. Intercepting private or cellular traffic is a different matter in every jurisdiction, and so is recording and redistributing traffic that is not addressed to you.

The application does not draw that line for you, and the README excerpt does not discuss it at all. A user who tunes a trunked public safety system and listens is in one position. A user who records a conversation and streams it to the internet is in another. A user who points it at a cellular network is in a third, and the capability is identical in all three cases because the tool does not know which one you are.

That is not a criticism of the software, which is a general-purpose tool, and it is a real consideration for anyone evaluating it. The recording and streaming features are the ones to think hardest about, the streaming destination in particular, because a live stream of a public safety conversation is a different object from a recording you keep on your own disk. This is not legal advice, and the frequency-specific position varies by jurisdiction, so the check to make is with your own regulator rather than with a README.

Editorial conclusion

Install sdrtrunk from the nightly tag if you need a trunked radio decoder, because the last final release predates current macOS and the newest hardware by more than a year, and copy your playlist files before you do since the author warns that the rolling tag can change under you. Do not treat a nightly build as something to deploy, and read the legal position for your own jurisdiction and frequency before recording anything, because the tool's recording and streaming features are where lawful monitoring of a broadcast feed becomes something else entirely. Verify first by confirming your radio hardware enumerates on your platform, which the Tahoe section suggests is not guaranteed, then reading the wiki's getting started page and the user manual rather than the repository README, which is where the substantive documentation lives.

Frequently asked questions

What is sdrtrunk?

It is a cross-platform Java application for decoding, monitoring, recording and streaming trunked mobile and related radio protocols using software defined radios, licensed under the GPL version 3. It follows a trunked system's control channel to stay on a conversation as it moves between voice channels, and its substantive documentation lives in a repository wiki with getting started, user manual and support pages.

When was the last sdrtrunk release, and what is the nightly tag?

The newest final release is version 0.6.1 from 2024-12-03, after a beta in November, while the last push to the repository was on 2026-09-26. The nightly tag is updated on every commit rather than on a schedule, so the author describes it as current rather than nightly, and its own date of 2023-11-06 is when the tag was created.

What is the macOS USB problem in sdrtrunk?

Changes to USB support in macOS 26.x stop the application launching. The README instructs installing libusb from the Homebrew development branch, creating directories under /opt, and symlinking the installed library to the path the usb4java native binding expects, then using a nightly build that includes an updated native library for ARM processors. The author notes problems accessing USB tuners may remain.

Why does sdrtrunk tell you to back up your playlists before using a nightly build?

Because the nightly is updated on every commit, so the build changes between runs and can carry a settings format that an earlier build cannot read, and the author issues the backup instruction in bold. The same section says the tag is current rather than nightly, so it cannot be used as a fixed version.

What are the minimum system requirements for sdrtrunk?

64-bit Windows, 64-bit Linux, or a 64-bit Mac on version 12 or later, with 32-bit support struck through for Windows and Linux. A four-core processor, and 8 GB of RAM preferred, with a note that 4 GB may be sufficient depending on usage.

How is sdrtrunk built and released?

With Gradle and a wrapper over a single source directory, with two GitHub Actions workflows, one for the Gradle build and one for nightly releases. The top level also holds a copyright template for source licence headers, a checked-in IDE project file, a changelog without a file extension, and a LICENSE file.

Official sources

  1. DSheirer/sdrtrunk on GitHub
  2. Issues
  3. License: GPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dsheirer-sdrtrunk.svg)](https://hysenlabs.com/projects/dsheirer-sdrtrunk)