chill
Terminal lofi radio. 24/7 streams from YouTube.

Install
Homebrew (macOS and Linux)
brew install willibrandon/tap/chill
Scoop (Windows)
scoop bucket add willibrandon https://github.com/willibrandon/scoop-bucket
scoop bucket add extras
scoop install chill
Both packages include mpv, FFmpeg, yt-dlp, and Deno.
Go or release binary
Install mpv, FFmpeg, yt-dlp,
and Deno first.
macOS:
brew install mpv ffmpeg yt-dlp deno
Linux:
sudo apt install mpv ffmpeg pipx
pipx install yt-dlp
Also install Deno.
Windows:
choco install mpv ffmpeg yt-dlp deno
Then install chill:
go install github.com/willibrandon/chill@latest
Or download a release binary
and put it in your PATH.
For Go installs, add the Go bin directory to your PATH:
- macOS/Linux:
export PATH="$HOME/go/bin:$PATH"
- Windows: Add
%USERPROFILE%\go\bin to your PATH
Update
Use chill update for Go installs and release binaries,
brew upgrade willibrandon/tap/chill for Homebrew, or scoop update chill for Scoop.
Usage
chill # play default station (starts daemon automatically)
chill chillhop # play specific station
chill -i # interactive mode (repl)
chill --skip # skip to random station
chill --toggle # pause/resume
chill --vol 60 # set volume (also +5, -10, up, down)
chill --mute # toggle mute
chill --status # show what's playing
chill --status --json # show status as JSON
chill doctor # check mpv, FFmpeg, yt-dlp, runtime, and daemon versions
chill doctor --stations # check station streams
chill doctor --stream n # check one station
chill doctor --logs # show startup logs
chill --stop # stop playback
chill --list # show all stations
chill add n url desc # save your own station
chill remove n # remove a custom station or restore a built-in
chill default n # choose the station played by chill
chill --sleep 45m # stop playback after 45 minutes
chill --sleep off # cancel the sleep timer
chill --version # show version
chill --help # show help
chill update # install the latest release
chill --fg # run in foreground (no daemon)
Architecture
chill runs mpv in the background, so music keeps playing when you close the
terminal. You can control it from another terminal.
yt-dlp resolves → FFmpeg decodes → daemon PCM pipe → mpv audio output
│
bounded audio tap
│
FFT / stereo levels
│
CLI/REPL ←── control IPC ──→ daemon ── snapshots ──→ REPL visualizer
After an update, the next control command restarts an older daemon and restores
your playback settings. Volume is saved between sessions.
The daemon decodes one stream into 48 kHz stereo PCM. Visualizers analyze the
same samples sent to playback; they do not open another network stream or capture
system audio. FFT work runs only while a REPL is subscribed. doctor checks the
new FFmpeg dependency as well as mpv, yt-dlp, and the YouTube JavaScript runtime.
If a stream disconnects, chill keeps reconnecting with increasing delays, capped
at 30 seconds. --status and the REPL show the retry count and countdown; JSON
status includes state: "reconnecting" and retry_at while waiting. Volume,
mute, pause, and the sleep deadline survive reconnects. Stop playback or switch
stations to cancel a reconnect.
Sleep timer
chill --sleep 45m stops playback after 45 minutes. Durations such as 1h30m
work too. The timer keeps running while paused or switching stations.
Use chill --sleep off to cancel it.
Stations
| Station |
Description |
lofi-girl |
Lofi Girl - beats to relax/study to |
chillhop |
Chillhop Radio - jazzy & lofi hip hop |
chillout |
Chillout Lounge - calm & relaxing |
code-radio |
Code Radio - beats to study & code to |
sleep |
Lofi - beats to sleep/relax to |
study |
Lofi - beats to study/relax to |
The default is lofi-girl. Change it with chill default <name>.
Your own stations
Add a YouTube stream with chill add <name> <url> [description], or edit the config:
- macOS:
~/Library/Application Support/chill/stations.json
- Linux:
~/.config/chill/stations.json (or $XDG_CONFIG_HOME/chill/stations.json)
- Windows:
%AppData%\chill\stations.json
{
"default_station": "synthwave",
"stations": [
{
"name": "synthwave",
"url": "https://www.youtube.com/watch?v=4xDzrJKXOOY",
"desc": "Synthwave Radio - retro electronic beats"
}
]
}
A custom station with a built-in name overrides it. chill remove <name> removes
the custom station and restores any built-in. After editing the file by hand,
run reload in the REPL.
Interactive Mode
chill -i opens the REPL. Type help for commands or press F1 for keys.
A station name starts playback. doctor takes the same options as the CLI.
Diagnostic findings appear as each check finishes. Press Ctrl+C (when nothing
is selected) or type cancel to cancel diagnostics and discard queued commands.
Quitting also cancels diagnostics; music keeps playing.
sleep plays the station. sleep 45m sets the timer.
| Key |
|
Tab |
complete with the highlighted suggestion |
→ |
take the ghost text |
↑ / ↓ |
pick a suggestion or browse history |
Enter |
run the line, or take a suggestion picked with ↑ / ↓ |
Esc |
dismiss the suggestions |
PgUp / PgDn |
scroll the transcript |
Shift+↑ / Shift+↓ |
select lines of the transcript |
y / Enter / Ctrl+C |
copy what is selected |
| mouse |
drag to select, right click to copy, or to paste when nothing is selected |
Ctrl+C |
cancel diagnostics, otherwise clear the line (when nothing is selected) |
Ctrl+L |
clear the screen |
F1 |
help |
F2 |
open/focus the visualizer; return to the prompt when focused |
Ctrl+Q |
quit, music keeps playing |
Visualizers
Type viz or press F2 to open a compact visualizer below the transcript.
While it has focus, v cycles modes, ← goes back, and V toggles
fullscreen. Space pauses/resumes, Esc returns from fullscreen and then
to the prompt, and o turns visualization off. The panel keeps animating
while you type commands. These letter shortcuts apply only when the visualizer
has focus, so typing vol and station names works normally.
viz spectrum # select a mode (Tab completes names)
viz led # independent left/right LED peak meters
viz fullscreen # toggle fullscreen
viz next # next mode
viz list # list all 31 modes
viz off # close and unsubscribe
Modes: spectrum, bars, mirror, skyline, dots, peaks, ribbon, waterfall,
spectrogram, scope, stereo-scope, wave, filled-wave, vectorscope, lissajous,
orbit, rings, radar, spiral, particles, rain, matrix, flame, embers, pulse,
diamonds, tunnel, starburst, led, vu, balance.
The display uses live Hann-windowed FFT data with logarithmic frequency bands,
waveforms, and independent stereo peak/RMS levels. Meters are labeled source
audio: they measure decoded samples before mpv volume, mute, and user audio
filters. LED meters include peak hold and a dBFS scale; these are sample peaks,
not oversampled inter-sample true-peak measurements. Playback/output buffering
can introduce a small visual lead. Paused, disconnected, and stale streams clear
the display. Help and terminals too small for a panel suspend the subscription.
See the visualizer architecture for extension points and
lifecycle details.
Foreground Mode
Use --fg to run in the terminal with mpv controls:
| Key |
Action |
q |
quit |
m |
mute |
9 / 0 |
volume down / up |
← / → |
seek |
Build and test
Install mpv and FFmpeg first. The normal test suite includes real playback
integration tests using generated local audio and null output—no audio device,
network access, or test opt-in environment variables are needed. Missing test
dependencies fail with installation instructions.
go build .
go test ./...
License
MIT