Installing GopherTrunk on macOS
Five minutes from a fresh download to a working gophertrunk sdr list.
GopherTrunk on macOS is a single static binary that talks to RTL-SDR
dongles through IOKit — no kext, no librtlsdr, no Homebrew formula
to chase.
1. Download the tarball
Go to the GopherTrunk releases page and grab the asset matching your CPU:
gophertrunk-<version>-darwin-arm64.tar.gz # Apple Silicon (M1 / M2 / M3 / M4)
gophertrunk-<version>-darwin-amd64.tar.gz # Intel Macs
If you’d rather curl it, see the one-liner under the downloads page macOS quick-start.
Verify the download against
SHA256SUMSbefore installing — see the verify section on the downloads page for the exactshasum -a 256 -cinvocation.
2. Install the binary
Extract and place gophertrunk somewhere on PATH. The conventional
spot for a single-binary command-line tool on macOS is
/usr/local/bin (Intel) or /opt/homebrew/bin (Apple Silicon, if you
use Homebrew); either works:
tar xzf gophertrunk-<version>-darwin-arm64.tar.gz
cd gophertrunk-<version>-darwin-arm64
sudo install -m 0755 gophertrunk /usr/local/bin/gophertrunk
The tarball also bundles config.example.yaml, README.md, and
LICENSE. We’ll come back to the config in step 5.
3. Clear the Gatekeeper quarantine (one-time, every download)
Builds are unsigned — the first time you run an un-signed, quarantined binary, macOS will refuse with “cannot be opened because the developer cannot be verified.” Two ways to clear it:
Easy: right-click gophertrunk in Finder → Open → confirm in
the dialog. macOS remembers your approval for that binary.
CLI: strip the quarantine xattr directly:
sudo xattr -dr com.apple.quarantine /usr/local/bin/gophertrunk
Re-do this every time you upgrade — a fresh download re-attaches the
com.apple.quarantine xattr.
No driver swap needed. Unlike Windows (Zadig → WinUSB) and Linux (DVB blacklist + udev rule), macOS lets user-space claim USB devices via IOKit without rebinding the kernel driver. Plug in the dongle and go.
4. Verify everything works
Open Terminal and run:
gophertrunk version
gophertrunk sdr list
sdr list should print one line per attached dongle with its driver,
index, serial, product string, and (when populated) tuner + gain
ladder. The plain command only reads USB descriptors, so the TUNER
and gains columns stay blank — pass --probe to open each device
just long enough to enumerate them:
gophertrunk sdr list --probe
If you see no SDR devices found and the dongle is plugged in:
- Check
system_profiler SPUSBDataType | grep -A 4 RTL2838shows the dongle (typically0x0bda:0x2838). - If you have SDR++, GQRX, or another RTL-SDR app open, close it — IOKit hands the device to whoever claims it first.
- Some USB-C hubs power-cycle low-power devices aggressively; plug the dongle directly into the Mac or into a powered hub.
See hardware.md for the full
matrix of supported tuners and dongles.
5. Configure and start the daemon
The tarball includes config.example.yaml. Drop a copy at
~/Library/Application Support/GopherTrunk/config.yaml and edit
it — the daemon walks $GOPHERTRUNK_CONFIG →
~/Library/Application Support/GopherTrunk/config.yaml →
~/Documents/GopherTrunk/config.yaml → ./config.yaml and loads
the first one it finds, so no -config flag is needed:
mkdir -p ~/Library/Application\ Support/GopherTrunk
cp config.example.yaml ~/Library/Application\ Support/GopherTrunk/config.yaml
${EDITOR:-nano} ~/Library/Application\ Support/GopherTrunk/config.yaml
gophertrunk run
On startup the daemon prints config: loaded <path> so you can
confirm it picked the right file. Override discovery any time with
-config <path> or by exporting GOPHERTRUNK_CONFIG.
If you keep more than one config in that directory (e.g.
config.yaml + prod.yaml), gophertrunk run prints a numbered
menu and asks which to load. Non-interactive launches (launchd,
cron) auto-pick the first match with a stderr warning; pin a
specific file via -config or GOPHERTRUNK_CONFIG for those.
Logs stream to the terminal. Press Ctrl+C to stop cleanly.
Run as a launchd service
For a long-running setup, register GopherTrunk as a per-user
LaunchAgent so it starts at login and respawns on crash. Drop the
following at ~/Library/LaunchAgents/org.gophertrunk.daemon.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.gophertrunk.daemon</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/gophertrunk</string>
<string>run</string>
<string>-config</string>
<string>/Users/YOUR_USER/.config/gophertrunk/config.yaml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/YOUR_USER/Library/Logs/gophertrunk.log</string>
<key>StandardErrorPath</key>
<string>/Users/YOUR_USER/Library/Logs/gophertrunk.err.log</string>
</dict>
</plist>
Then load it:
launchctl load ~/Library/LaunchAgents/org.gophertrunk.daemon.plist
launchctl start org.gophertrunk.daemon
tail -f ~/Library/Logs/gophertrunk.log
For a system-wide daemon (starts at boot, not login), put the plist
under /Library/LaunchDaemons/ and sudo launchctl bootstrap
system/<path> instead. Note that LaunchDaemons run as root by
default — set UserName in the plist to drop privileges.
Uninstall
launchctl unload ~/Library/LaunchAgents/org.gophertrunk.daemon.plist 2>/dev/null || true
rm -f ~/Library/LaunchAgents/org.gophertrunk.daemon.plist
sudo rm -f /usr/local/bin/gophertrunk
rm -rf ~/.config/gophertrunk
rm -f ~/Library/Logs/gophertrunk.log ~/Library/Logs/gophertrunk.err.log
Recordings under your call-log directory are left alone — remove them manually if you want a clean slate.
Troubleshooting
| Symptom | Likely cause |
|---|---|
cannot be opened because the developer cannot be verified |
Quarantine xattr still attached — re-run the xattr -dr from step 3, or right-click → Open. |
command not found: gophertrunk |
Binary isn’t on PATH — re-check step 2, or run from the install path directly. |
sdr list prints nothing |
Another RTL-SDR app (SDR++, GQRX) is holding the device — close it and retry. |
sdr list still prints nothing with every other SDR app closed |
Re-run with RTLSDR_DEBUG_USB=1 gophertrunk sdr list 2> trace.log. Attach trace.log, sw_vers, and system_profiler SPUSBDataType \| grep -A 10 "Vendor ID" to a new issue — the trace tells us which IOKit class matched and which properties were readable. |
usb: claim interface failed |
Same — IOKit hands the dongle to whoever opened it first. |
| Audio plays as silence | audio.enabled: false by default — set true in config. CoreAudio is the default backend on Darwin. |
LaunchAgent says Load failed: 5: Input/output error |
plist syntax error — plutil -lint ~/Library/LaunchAgents/org.gophertrunk.daemon.plist will show the line. |
For anything else: open an issue at
https://github.com/MattCheramie/GopherTrunk/issues with the
gophertrunk version output and the first few lines of the daemon
log (tail ~/Library/Logs/gophertrunk.err.log if running under
launchd).