A long scan leaves hundreds of recordings, each with a JSON sidecar of
measurements and, where a recogniser heard speech, a transcript. Reading
that meant opening files one at a time and guessing which were worth
playing.
saunterbrowse is a second executable in the same package. Arrow keys move
through the recordings; the transcript of whichever is highlighted fills
the top of the screen, because that is the part anyone actually wants to
read. Enter plays it, handing the file to whichever player is installed
-- the recordings are ordinary WAVs, every desktop already has something
that plays them, and a browser that cannot start would be worse than one
that cannot play. t opens the whole transcript full screen when it is
longer than the panel, and says so rather than cutting the end off
silently. / filters on the frequency, the name, the identification, or
anything that was said, which is the point of it: "was the repeater
mentioned" is a question about content.
Sidecars are read only for the rows on screen, so a directory of ten
thousand recordings opens instantly. Where there is no transcript the
panel says which of the reasons applies -- Morse (decoded, and shown),
data, a bare carrier, or speech never offered to a recogniser -- because
those want different things done about them. It only ever reads.
Two things were only found by driving it through a real terminal.
sys.stdin.read(1) goes through a buffered text wrapper, which in cbreak
mode waits for more bytes than one keypress provides: the program drew its
first frame and then hung, while tests against a stand-in stream object
passed. It reads the file descriptor now, and the tests drive a pty. And
stopping playback signalled only the direct child, so a player that is a
wrapper script kept the sound going with nothing on screen to stop it; the
whole process group is signalled instead, which is what start_new_session
was there for.
man saunterbrowse ships beside man bandsaunter, and the two point at each
other.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016PsWPTweCT6pwxKngvVxcg
Every setting now carries a paragraph saying what it is in everyday terms
and why someone who does not already speak radio would turn it up, down,
on or off: what the squelch knob actually is, why automatic gain is a bad
idea for scanning, why a bias tee can damage equipment, why setting the
transcription language matters on noisy audio. The menus and
`config --describe` show it alongside the existing technical detail.
packaging/make-man.py generates bandsaunter(1) from that same table, so the
manual cannot document a setting the program lacks or miss one it has --
tests check both, that the page renders through groff without a single
warning, and that the guidance survives into the rendered output. Around
it are hand-written sections on the commands, entering frequencies, the
band plan, lock-outs, the keys during a scan, HF, single sideband, files,
environment variables and worked examples.
The .deb regenerates and installs it rather than shipping a copy, so an
installed manual always matches the installed program.
The README picks up what the last few commits added: the plain display as
a saved setting, what the settings tests now guarantee, and where to read
the manual before installing.
Version is the day's build: 2026-08-22_01.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>