AI & ML
I built a radio station with one listener, and it runs in a terminal
zhiyi guo DEV Community
1 views
The film above is 86 seconds, and the middle of it is a real on-air moment. There is a longer unedited recording at the top of the repo README. Watch either first, with the sound on. The rest of this post is why it exists and how it is put together.
What it is
murmur runs in a terminal window and behaves like a radio station whose only listener is you. It picks a topic on its own and talks about it in a voice that sounds like a person. Then it plays a song, comes back, and keeps going. At the right hours it says good morning and good night. You do not have to answer any of it.
When you do type something, the host replies in character. You chat for a bit. Then it eases back into the program.
There is one host. A few questions on the first run write its character to a file. After that, nothing rewrites that file except you. What grows over time is a separate thing: what it knows about you.
Why I built it
Every AI tool on my machine wants me to go faster. That is fine for work, and it is exhausting as company. I wanted something that sits closer to the person than to the task. A late-night radio host does that. They talk whether or not you are listening, they never ask you to respond, and when you do call in, they are glad and then they get back to the show.
Nothing I found did the proactive half. Chat assistants wait for a prompt. Voice tools want to drive my editor. So the bet was simple: what if the AI speaks first and needs nothing back?
How it is built
It is TypeScript on Node 24, no build step, run straight from source.
The brain is Claude, opened through the Claude Agent SDK. It reuses your local Claude Code login, so there is no API key and no separate bill. It is a harnessed agent rather than a one-shot call. murmur gives it a small set of its own tools: search for a song, judge the candidates, commit a pick, update memory, run the setup guide. It is sealed off from your own Claude Code setup. None of your CLAUDE.md files, skills, MCP servers, or hooks reach it.
The voice is fish-speech, reached over a hosted HTTP endpoint you point it at. That is the reason it sounds like a person and not a screen reader. It is also the reason murmur is not a local tool, and I want to say that plainly: the brain and the voice are network services. What stays on your machine is the program logic, the keyboard, the mixer, the persona, and the memory.
Music comes through yt-dlp. The rules it picks by live in a markdown file under ~/.murmur. The pick task re-reads that file before every song, so if you write "more Cantonese, no covers" while a track is playing, the change reaches the next pick or the one after.
The mixer is a Web Audio graph on node-web-audio-api. Voice and music share one output stream. A gain envelope ducks the song under the host, so the lead-in is spoken over the head of the track and the back-announce over its tail. The song never stops for the voice.
Two processes. The engine owns the program and the audio. The TUI is a separate process on OpenTUI under Bun, attached over a unix socket carrying newline-delimited JSON. Without Bun it falls back to a plain text host in the same process, and every command still works typed in full.
The decision people ask about
The host's character does not evolve. I built the evolving version first. A background loop watched the conversation and rewrote the persona to fit the listener better. Within days it had drifted into the same generic assistant voice every chatbot has. Language-model rewrite loops mean-revert, and there was no checkpoint where a person could catch the drift.
So the persona is frozen. It is a text file. You can open it and rewrite it whenever you like, and nothing changes it behind your back. The memory of you is a separate tier that does grow, with dates the code owns and citations back to the conversation that produced each fact.
What is rough
It needs a Claude Code subscription for the real brain. --brain stub gives you a canned stand-in brain for a look around, and that is all it is.
The voice is hosted. If you have no endpoint configured, it prints its lines instead of speaking. A local TTS is on the list, not in the code.
Music picks sometimes stall or run long. There is an open issue with measurements.
It is developed on macOS. Linux should be fine. Windows is untested.
Onboarding is still being tuned by ear, and one path after /quit misbehaves.
Try it
Node 24 or newer:
npm install -g murmur-radio
murmur
It launches even with pieces missing and offers to walk you through installing ffmpeg, yt-dlp, and a voice endpoint by talking to you. Say no once and it stops asking.
Repo: https://github.com/wine-fall/murmur (MIT). Landing page: https://wine-fall.github.io/murmur/.
If you leave it on for an afternoon, I would like to know one thing: did it feel like radio, or like a chatbot with a timer?
Read original: https://dev.to/fawinell/i-built-a-radio-station-with-one-listener-and-it-runs-in-a-terminal-4g7h
← Previous
Kimi ครอง Design Arena, แต่แพ้ 4 ใน 5 รอบในคลิปเดียวกัน
Next →
what do you do with code that clearly exists for a reason but nobody documented why?
Related
DeepSeek R1: The Open-Source Reasoning Revolution That Changes Everything
AI & ML
1
DEV Community
Multi-Modal AI: From Text to Vision and Beyond — The Unified Future
AI & ML
1
DEV Community
AI Safety and Alignment: Building Trustworthy Agents That Do Not Fail You
AI & ML
2
DEV Community
🐢 and 🐇 in My Claude Code Status Line: Now Watching Fable
AI & ML
3
DEV Community
Comments0
No comments yet — be the first