Terminal monitor for SDR hardware - written in Rust. Early development.
Rust
145
677 commits
updated Sep 23, 2026
A bench instrument for software defined radios, living in your terminal.
Spectrum, waterfall, and the measurements a plot cannot give you.
Via SoapySDR
Grey means written from the API, not from owning one. It should work. Nobody has told me either way yet, which is exactly as reassuring as it sounds. The honest version.
Install · Keys · Config · Roadmap · Hardware · Changelog · Full guide
Hey there! This is my take on a terminal monitor for SDR hardware. I wanted something that could hunt down every bit of diagnostic data from your radio and stream it straight to your terminal. Not a lazy *-info clone: raw, real-time metrics with a spectrum, a waterfall and a set of bench instruments, in a tmux pane, an SSH session, or the postage-stamp screen of a cyberdeck. I set out to print a few numbers. There is now a Friis noise figure model in here. I'm not entirely sure how that happened.
It's a hobby project built in my spare time, and honestly, I made it for you ❤️. Use it however you like, beat on it, and don't be shy: open issues, dig through the code, and if you've got a good idea, send it my way as a pull request or just a message. This is an open table, not my private garage.
[!IMPORTANT] Project status: early development. The TUI is feature-complete and the arc now is polish, sharper radio math and bug fixing, not more features.
HackRF One, RTL-SDR and a tinySA Ultra ZS405 are verified on hardware. Anything with a SoapySDR driver also works, and that backend is beta: it was written from the API rather than from owning the radios, so treat it as "should work, nobody has confirmed it yet". The docs say exactly which parts are confirmed. If you own one of those, an issue either way is worth a lot to me.
Known issues: plenty 😄 If something looks broken, it's either a bug or an undocumented feature. Flip a coin, then open an issue.
▶ click the screenshot to play the demo video
It's a terminal app, so brace yourself for the visual spectacle of monospace text in color. The only special effects are honest dBFS numbers.
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
Got a clean capture on your hardware? Drop it in user_docs/pics/ and send a PR. Shots from radios I don't own are the most useful ones there are.
Everything your radio knows about itself, in real time, without leaving the terminal. It's more than I planned. Every one of these started as "that'd be a nice little readout".
Enter on a peak to tune straight to it.Esc for the menu, or define your own out of any panel sdrtop draws.Measured the awkward way rather than the easy way. Bandwidth about the carrier, not across whatever span you happened to capture, so a mistuned radio confesses instead of faking a good number. The noise floor as a density, so the same receiver reads as the same receiver whatever the sample rate. And every lab panel marks itself [STALE] the moment RX stops, so a frozen number is never mistaken for a live one.
Because the only thing worse than no data is confidently wrong data.
→ Full user guide. This page is the short version; everything below is covered properly over there.
| Getting started: install & run | Keyboard shortcuts: every key | What's on screen: panels explained |
| The Lab presets: the bench-engineer views | Configuration: config.toml & layouts | Advanced features: workflows & limits |
| Tips & tricks: gain, markers, workflows | Troubleshooting: when things go sideways | Supported hardware: what works today |
| Themes: the six palettes | What's new: the checkpoint log | The demodulator: how it was built |
Requirements: Linux · a HackRF One, an RTL-SDR, or anything SoapySDR speaks to
curl -fsSL https://raw.githubusercontent.com/musithang/sdrtop/main/packaging/install.sh | sh
The installer tries the prebuilt binary on your machine. It compiles from source if the binary cannot run there. Native SDR libraries are optional runtime dependencies.
Add --hackrf or --rtlsdr to install the runtime for your radio. --soapy adds SoapySDR and its driver modules. A plain install adds none of these libraries.
sh install.sh --prefix ~/.local # install under a directory, no root anywhere
sh install.sh --version v0.4.1 # a specific release instead of the latest
sh install.sh --from-source # skip the prebuilt binary, always compile
sh install.sh --git # compile the main branch, live dangerously
sh install.sh --no-verify # skip the checksum check (say why first)
sh install.sh --hackrf # Install the HackRF runtime
sh install.sh --rtlsdr # Install the RTL-SDR runtime
sh install.sh --soapy # add SoapySDR and its driver modules
sh install.sh --deps-only --hackrf # Install only the selected runtime
sh install.sh --uninstall # remove what a previous run installed
sh install.sh --help # this list, from the script itself
Piped straight into a shell they go after sh -s --. --no-verify turns off the checksum check on a download, which is the one thing standing between you and a tarball that isn't the one I published, so have a reason. The rest are explained in Getting started.
--deps-only requires a runtime flag. It never installs build tools.
Piping a script into sh means running code you haven't read. You should read it: packaging/install.sh. I'd want to.
sdrtop is on crates.io. Cargo compiles it for your machine.
sudo apt install build-essential # Debian / Ubuntu / Mint
sudo pacman -S base-devel # Arch / Manjaro
sudo dnf install gcc # Fedora
cargo install sdrtop --locked
Building needs Rust 1.88+ and a C compiler/linker. Install Rust with rustup. No SDR libraries, development headers or pkg-config are required. At runtime, HackRF needs libhackrf 2023.01.1+ and RTL-SDR needs librtlsdr. A missing or incompatible library disables only its backend.
tinySA builds and runs without libhackrf or librtlsdr. Install native SDR runtimes only for the backends you use.
Then go make coffee: a few minutes on a laptop, considerably more on a Raspberry Pi. It's not frozen, it's just Rust.
Beta, see Hardware. Neither of these is needed to build or run sdrtop; it looks for them at startup and shrugs if they aren't there.
sudo apt install libsoapysdr0.8 soapysdr-tools soapysdr-module-all
SoapySDRUtil --find # if this can't see your radio, sdrtop can't either
That last command is the whole diagnostic. If your radio isn't in that list, the missing piece is a driver module, and no amount of shouting at sdrtop will conjure one up.
Getting started covers the release tarball, checksums and provenance attestation. The tarball needs x86_64 Linux with glibc 2.36+. Runtime loading supports both Debian's librtlsdr.so.0 and Ubuntu's librtlsdr.so.2.
First run: sdrtop opens on its menu. Enter takes a layout, Space starts receiving, Esc brings the menu back, q quits and saves.
Layouts are grouped into four sections and each section has its own numbers: Command Rail for the general views, Lab for the benches, Sweep for the band scan, Micro for the field views. So 2 is the RF bench inside Lab and the spectrum inside Command Rail. Esc opens the menu, which shows you the sections, the layouts in the one you're on, and the number that opens each. Nine keys, four times over, rather than one long row to memorise.
The eight that get you everywhere:
| Key | Action |
|---|---|
Esc | Open the menu, or leave a focused panel |
Enter | Take the highlighted layout |
Space | Start / stop RX |
1–9 | The nth layout of the section you're in |
↑ / ↓ | Primary gain |
f / s | Type a frequency / a sample rate |
c / e / l | Focus the Command Rail / spectrum / waterfall |
q | Quit and save |
Capitals work everywhere: C and c do the same thing, so you never have to think about whether Shift is down. The gain keys relabel themselves per device, and a control your radio doesn't have simply isn't offered rather than sitting there doing nothing.
Forgotten one mid-session? Esc, then Tab to Keys. That reference is generated from the same table the app dispatches on, so it cannot go stale. Full list including every focus mode: Keyboard shortcuts.
Saved to ~/.config/sdrtop/config.toml when you quit. Hand-editing is safe: a missing or broken file just falls back to defaults. Go ahead, mangle it; the parser has seen worse.
Frequency, gains, sample rate, markers, the sweep band, your theme and your layout all live there, plus any layouts of your own. Give a custom preset a section and a slot and it gets a place in the menu and a number key. Annotated example and every field: Configuration and Layout presets.
Themes: sdr (default) · nord · dracula · gruvbox · catppuccin · solarized, with per-field overrides. See Themes.
Polish over features. I have said that before and then went and wrote a demodulator, so this time there's a list. ✨
The whole story, in order: What's new.
| Device | Status | Notes |
|---|---|---|
| HackRF One | ✅ Full support | All diagnostics, gain stages, ADC metrics |
| RTL-SDR (R820T, E4000, R828D) | ✅ Full support | Single tuner gain + AGC; no VGA, no BB filter, no Friis NF |
| tinySA / Ultra / Ultra+ | ✅ Spectrum support | ZS405 verified; calibrated dBm spectrum, waterfall and native band sweeps |
| Anything with a SoapySDR driver | 🧪 Beta | Airspy, SDRplay, Pluto, Lime, bladeRF, USRP, SoapyRemote. Unconfirmed on anything but a HackRF |
| PortaPack H4M (Mayhem) | ✅ Full support | HackRF mode: all HackRF diagnostics apply |
| HackRF Pro | 🔲 Planned | Needs hardware |
Native support is added only after physical testing on real devices. No guessing from datasheets. Translation: that list moves at exactly the speed of my hobby budget.
SoapySDR is the deliberate exception, because "I don't own one" was a bad answer to give every week, and buying one of everything is not a plan, it's a fantasy with a shipping address. Nothing about your radio is hardcoded: sdrtop asks the driver for the frequency range, the gain range, whether there's an AGC, the sample format and how many of its bits mean anything. What it can't ask, it refuses rather than invents. Verified against a HackRF through SoapyHackRF: the loader, enumeration, opening, capabilities and streaming. Unverified: literally every other radio. The honest version has the full reckoning, including the gotchas I already hit.
It took me a while to stop wincing at that. Before this, every row above was green and "tested on real hardware" applied to everything I shipped, which is another way of saying it separated nothing. The grey badges are what make the green ones mean something, and a rule nobody has ever had a reason to test is not a rule, it's a habit. This one now has one marked edge on it, on purpose.
Every native backend needs the device to physically exist on my desk, and development here runs on a HackRF One and a PortaPack H4M. If sdrtop is useful to you and you'd like your radio supported properly, contributions go straight into buying it. Every radio that arrives gets a real backend: tested on hardware, documented, shipped.
| Device | Why it matters | Price |
|---|---|---|
| RTL-SDR Blog V4 | The backend is in; a unit here would let me test the clone variants | ~€25 |
| Airspy Mini | Clean 24–1700 MHz, popular with hams and scanner hobbyists | ~€80 |
| Airspy HF+ Discovery | Best budget HF receiver, dedicated listener community | ~€150 |
| LimeSDR Mini 2.0 | Full-duplex, wide range, and the obvious device to confirm the SoapySDR path on | ~€160 |
No pressure, but if this scratches an itch for you, this is where it goes.
.
/=\
( |#| )
(( |#| ))
((( |#| )))
(( |#| ))
( |#| )
|#|
/|#|\
/ |#| \
/ |#| \
/___|#|___\
/ |#| \
'''''''''''''''
Yep, it's a radio tower. I'm a simple man, I see free time, I make ASCII art.
73 de sdrtop: ham-speak for "catch you later." 📻
Rust
98.7%
Shell
1.1%
Terminal monitor for SDR hardware - written in Rust. Early development.
Rust
145
677 commits
updated Sep 23, 2026
A bench instrument for software defined radios, living in your terminal.
Spectrum, waterfall, and the measurements a plot cannot give you.
Via SoapySDR
Grey means written from the API, not from owning one. It should work. Nobody has told me either way yet, which is exactly as reassuring as it sounds. The honest version.
Install · Keys · Config · Roadmap · Hardware · Changelog · Full guide
Hey there! This is my take on a terminal monitor for SDR hardware. I wanted something that could hunt down every bit of diagnostic data from your radio and stream it straight to your terminal. Not a lazy *-info clone: raw, real-time metrics with a spectrum, a waterfall and a set of bench instruments, in a tmux pane, an SSH session, or the postage-stamp screen of a cyberdeck. I set out to print a few numbers. There is now a Friis noise figure model in here. I'm not entirely sure how that happened.
It's a hobby project built in my spare time, and honestly, I made it for you ❤️. Use it however you like, beat on it, and don't be shy: open issues, dig through the code, and if you've got a good idea, send it my way as a pull request or just a message. This is an open table, not my private garage.
[!IMPORTANT] Project status: early development. The TUI is feature-complete and the arc now is polish, sharper radio math and bug fixing, not more features.
HackRF One, RTL-SDR and a tinySA Ultra ZS405 are verified on hardware. Anything with a SoapySDR driver also works, and that backend is beta: it was written from the API rather than from owning the radios, so treat it as "should work, nobody has confirmed it yet". The docs say exactly which parts are confirmed. If you own one of those, an issue either way is worth a lot to me.
Known issues: plenty 😄 If something looks broken, it's either a bug or an undocumented feature. Flip a coin, then open an issue.
▶ click the screenshot to play the demo video
It's a terminal app, so brace yourself for the visual spectacle of monospace text in color. The only special effects are honest dBFS numbers.
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
Got a clean capture on your hardware? Drop it in user_docs/pics/ and send a PR. Shots from radios I don't own are the most useful ones there are.
Everything your radio knows about itself, in real time, without leaving the terminal. It's more than I planned. Every one of these started as "that'd be a nice little readout".
Enter on a peak to tune straight to it.Esc for the menu, or define your own out of any panel sdrtop draws.Measured the awkward way rather than the easy way. Bandwidth about the carrier, not across whatever span you happened to capture, so a mistuned radio confesses instead of faking a good number. The noise floor as a density, so the same receiver reads as the same receiver whatever the sample rate. And every lab panel marks itself [STALE] the moment RX stops, so a frozen number is never mistaken for a live one.
Because the only thing worse than no data is confidently wrong data.
→ Full user guide. This page is the short version; everything below is covered properly over there.
| Getting started: install & run | Keyboard shortcuts: every key | What's on screen: panels explained |
| The Lab presets: the bench-engineer views | Configuration: config.toml & layouts | Advanced features: workflows & limits |
| Tips & tricks: gain, markers, workflows | Troubleshooting: when things go sideways | Supported hardware: what works today |
| Themes: the six palettes | What's new: the checkpoint log | The demodulator: how it was built |
Requirements: Linux · a HackRF One, an RTL-SDR, or anything SoapySDR speaks to
curl -fsSL https://raw.githubusercontent.com/musithang/sdrtop/main/packaging/install.sh | sh
The installer tries the prebuilt binary on your machine. It compiles from source if the binary cannot run there. Native SDR libraries are optional runtime dependencies.
Add --hackrf or --rtlsdr to install the runtime for your radio. --soapy adds SoapySDR and its driver modules. A plain install adds none of these libraries.
sh install.sh --prefix ~/.local # install under a directory, no root anywhere
sh install.sh --version v0.4.1 # a specific release instead of the latest
sh install.sh --from-source # skip the prebuilt binary, always compile
sh install.sh --git # compile the main branch, live dangerously
sh install.sh --no-verify # skip the checksum check (say why first)
sh install.sh --hackrf # Install the HackRF runtime
sh install.sh --rtlsdr # Install the RTL-SDR runtime
sh install.sh --soapy # add SoapySDR and its driver modules
sh install.sh --deps-only --hackrf # Install only the selected runtime
sh install.sh --uninstall # remove what a previous run installed
sh install.sh --help # this list, from the script itself
Piped straight into a shell they go after sh -s --. --no-verify turns off the checksum check on a download, which is the one thing standing between you and a tarball that isn't the one I published, so have a reason. The rest are explained in Getting started.
--deps-only requires a runtime flag. It never installs build tools.
Piping a script into sh means running code you haven't read. You should read it: packaging/install.sh. I'd want to.
sdrtop is on crates.io. Cargo compiles it for your machine.
sudo apt install build-essential # Debian / Ubuntu / Mint
sudo pacman -S base-devel # Arch / Manjaro
sudo dnf install gcc # Fedora
cargo install sdrtop --locked
Building needs Rust 1.88+ and a C compiler/linker. Install Rust with rustup. No SDR libraries, development headers or pkg-config are required. At runtime, HackRF needs libhackrf 2023.01.1+ and RTL-SDR needs librtlsdr. A missing or incompatible library disables only its backend.
tinySA builds and runs without libhackrf or librtlsdr. Install native SDR runtimes only for the backends you use.
Then go make coffee: a few minutes on a laptop, considerably more on a Raspberry Pi. It's not frozen, it's just Rust.
Beta, see Hardware. Neither of these is needed to build or run sdrtop; it looks for them at startup and shrugs if they aren't there.
sudo apt install libsoapysdr0.8 soapysdr-tools soapysdr-module-all
SoapySDRUtil --find # if this can't see your radio, sdrtop can't either
That last command is the whole diagnostic. If your radio isn't in that list, the missing piece is a driver module, and no amount of shouting at sdrtop will conjure one up.
Getting started covers the release tarball, checksums and provenance attestation. The tarball needs x86_64 Linux with glibc 2.36+. Runtime loading supports both Debian's librtlsdr.so.0 and Ubuntu's librtlsdr.so.2.
First run: sdrtop opens on its menu. Enter takes a layout, Space starts receiving, Esc brings the menu back, q quits and saves.
Layouts are grouped into four sections and each section has its own numbers: Command Rail for the general views, Lab for the benches, Sweep for the band scan, Micro for the field views. So 2 is the RF bench inside Lab and the spectrum inside Command Rail. Esc opens the menu, which shows you the sections, the layouts in the one you're on, and the number that opens each. Nine keys, four times over, rather than one long row to memorise.
The eight that get you everywhere:
| Key | Action |
|---|---|
Esc | Open the menu, or leave a focused panel |
Enter | Take the highlighted layout |
Space | Start / stop RX |
1–9 | The nth layout of the section you're in |
↑ / ↓ | Primary gain |
f / s | Type a frequency / a sample rate |
c / e / l | Focus the Command Rail / spectrum / waterfall |
q | Quit and save |
Capitals work everywhere: C and c do the same thing, so you never have to think about whether Shift is down. The gain keys relabel themselves per device, and a control your radio doesn't have simply isn't offered rather than sitting there doing nothing.
Forgotten one mid-session? Esc, then Tab to Keys. That reference is generated from the same table the app dispatches on, so it cannot go stale. Full list including every focus mode: Keyboard shortcuts.
Saved to ~/.config/sdrtop/config.toml when you quit. Hand-editing is safe: a missing or broken file just falls back to defaults. Go ahead, mangle it; the parser has seen worse.
Frequency, gains, sample rate, markers, the sweep band, your theme and your layout all live there, plus any layouts of your own. Give a custom preset a section and a slot and it gets a place in the menu and a number key. Annotated example and every field: Configuration and Layout presets.
Themes: sdr (default) · nord · dracula · gruvbox · catppuccin · solarized, with per-field overrides. See Themes.
Polish over features. I have said that before and then went and wrote a demodulator, so this time there's a list. ✨
The whole story, in order: What's new.
| Device | Status | Notes |
|---|---|---|
| HackRF One | ✅ Full support | All diagnostics, gain stages, ADC metrics |
| RTL-SDR (R820T, E4000, R828D) | ✅ Full support | Single tuner gain + AGC; no VGA, no BB filter, no Friis NF |
| tinySA / Ultra / Ultra+ | ✅ Spectrum support | ZS405 verified; calibrated dBm spectrum, waterfall and native band sweeps |
| Anything with a SoapySDR driver | 🧪 Beta | Airspy, SDRplay, Pluto, Lime, bladeRF, USRP, SoapyRemote. Unconfirmed on anything but a HackRF |
| PortaPack H4M (Mayhem) | ✅ Full support | HackRF mode: all HackRF diagnostics apply |
| HackRF Pro | 🔲 Planned | Needs hardware |
Native support is added only after physical testing on real devices. No guessing from datasheets. Translation: that list moves at exactly the speed of my hobby budget.
SoapySDR is the deliberate exception, because "I don't own one" was a bad answer to give every week, and buying one of everything is not a plan, it's a fantasy with a shipping address. Nothing about your radio is hardcoded: sdrtop asks the driver for the frequency range, the gain range, whether there's an AGC, the sample format and how many of its bits mean anything. What it can't ask, it refuses rather than invents. Verified against a HackRF through SoapyHackRF: the loader, enumeration, opening, capabilities and streaming. Unverified: literally every other radio. The honest version has the full reckoning, including the gotchas I already hit.
It took me a while to stop wincing at that. Before this, every row above was green and "tested on real hardware" applied to everything I shipped, which is another way of saying it separated nothing. The grey badges are what make the green ones mean something, and a rule nobody has ever had a reason to test is not a rule, it's a habit. This one now has one marked edge on it, on purpose.
Every native backend needs the device to physically exist on my desk, and development here runs on a HackRF One and a PortaPack H4M. If sdrtop is useful to you and you'd like your radio supported properly, contributions go straight into buying it. Every radio that arrives gets a real backend: tested on hardware, documented, shipped.
| Device | Why it matters | Price |
|---|---|---|
| RTL-SDR Blog V4 | The backend is in; a unit here would let me test the clone variants | ~€25 |
| Airspy Mini | Clean 24–1700 MHz, popular with hams and scanner hobbyists | ~€80 |
| Airspy HF+ Discovery | Best budget HF receiver, dedicated listener community | ~€150 |
| LimeSDR Mini 2.0 | Full-duplex, wide range, and the obvious device to confirm the SoapySDR path on | ~€160 |
No pressure, but if this scratches an itch for you, this is where it goes.
.
/=\
( |#| )
(( |#| ))
((( |#| )))
(( |#| ))
( |#| )
|#|
/|#|\
/ |#| \
/ |#| \
/___|#|___\
/ |#| \
'''''''''''''''
Yep, it's a radio tower. I'm a simple man, I see free time, I make ASCII art.
73 de sdrtop: ham-speak for "catch you later." 📻
Rust
98.7%
Shell
1.1%