YuTuTui!

● ~/yututui — Rust · ratatui · MIT

Now playing —
in your terminal.

Stable enough for daily use, still moving fast. A keyboard-driven YouTube Music client with DJ Gem streaming, live radio, terminal-aware album art fallbacks, synced lyrics, scrobbling, and one-command Spotify import. No browser. No ads.

$ brew install Ochichan/tap/yututui
🪶 One tiny binary│ 🚫 Zero ads│ 🎨 14 themes, recolorable to the last hex│ ⌨ App actions rebindable│ ⚖ MIT
YuTuTui! click to explore 7:06
Nothing playing — press s to search

● The good stuff

Everything, one key away

It's all keyboard, all fast, and all yours to rebind. Here's what you get the moment you type ytt.

Ctrl R

DJ Gem streaming that reads the room

Press Ctrl+R and a Gemini-powered Queue Director lines up songs that fit the mood — Focused, Balanced, or Discovery. Press w for its reasoning, in plain words.

album art v

Album art, lyrics — and the video

Cover art uses Kitty, Sixel or iTerm2 when your terminal supports it, with halfblock or retro fallback; time-synced lyrics scroll underneath — and v floats the music video in a little mpv window where your OS session supports it. When mpv has focus, Space/./,/q/f/m handle playback, next/previous, close, fullscreen, and mute, and those keys are remappable too.

Tab ▾

Seven catalogs, one search box

YouTube Music is home base, but the same box searches SoundCloud, Audius, Jamendo, Internet Archive, Radio Browser and your OpenSubsonic music server. Flip sources with Tab, or hit them all at once — every result tagged [SRC].

Alt ⇧ R i

Live radio that knows the song

Alt+Shift+R turns the whole app into an internet-radio tuner — true live streams that re-sync themselves to the live edge, with radio-only favorites, history, even its own theme. Press i and Gemini names what's playing right now; f favorites it. Press a for Atlas — a rotatable globe of live stations drawn in Braille dots, no image protocol needed.

ytt transfer

Move in from Spotify

Liked songs and playlists migrate to YouTube Music with one checkpointed, resumable command — CJK-safe matching, ambiguities reported instead of guessed. Works the other way too.

n d

Playlists and downloads, kept local

Build playlists in the Library (or let DJ Gem build them), and press d to save any track as a tagged m4a with cover art — Shift+D grabs the whole list, played offline from the Downloads tab or the immersive Local Deck (Alt+Shift+L).

⏯ ⏭ ⏮

Control it from everywhere

Media keys, macOS Control Center, a menu-bar / tray mini player, Linux MPRIS, ytt -r from any shell — or no terminal at all with the headless daemon.

scrobble

Every listen, on the record

Last.fm and ListenBrainz, done properly: Now Playing updates, the half-track rule, likes synced as loves — and offline listens queue on disk until you're back.

,

Unmistakably yours

14 themes, all 34 color roles hex-editable, a 10-band EQ with presets, and your pick of audio-output device — plus 40 animations, from a spinning ASCII donut to full-canvas showpieces (fireworks, Game of Life, pipes, plasma), and a retro mode for a bare Linux console.

?

The app remembers the keys

Press ? for the always-current cheat sheet — your language, your custom bindings — and a guided Beginner Mode walks first-timers through the app. Korean jamo work as-is (ㅂ = q), everything on screen is clickable, right-click opens a context menu, and Ctrl+- / Ctrl+= zooms the whole UI. Drag to select row ranges — in Search results just like the Library — and Ctrl+click (⌘+click on macOS) toggles single rows in and out of the selection.

7catalogs, one search box
14themes, yours to recolor
34hex-editable color roles
40animations, donut included
10EQ bands, with presets
3platforms — macOS · Windows · Linux

● Streaming with its reasons

It doesn't just autoplay. It can tell you why.

YuTuTui!'s streaming plans a set — a core, a bridge, a discovery — and keeps the music flowing as the queue runs dry. Press w and it shows its work, in plain language.

  • Three moods: Focused, Balanced, Discovery.
  • DJ Gem remembers the conversation now — follow-up questions just work.
  • Ask in plain words — “make me a rainy-day playlist” — and it builds it right in your Library.
Why these DJ Gem picks
1
Late Night Study — Mellocore
Stays on the tempo you've been listening to.
2
Foxtrot — Holo Beatsbridge
Keeps the key, swaps the drums — often played after this one.
3
Amber — Sundialdiscovery
New to you, adjacent to two artists you favorite.

● Internet radio · Alt+Shift+R

Tune in. Then ask what's playing.

Alt+Shift+R flips the whole app into an internet-radio tuner — proper live broadcasts, pinned to LIVE. And when a song grabs you, one key tells you what it is.

  • True live streams — drift is detected and re-synced to the live edge on its own.
  • Radio keeps its own favorites, history and theme, separate from the player's.
  • Press i — Gemini reads the live stream and names the song, right on the player.
  • f favorites the identified track; g hands it to DJ Gem for more like it.
📻 radio Night Wave FM — City Pop 24/7 LIVE:✓
[i] What's playing?from the live stream
♪ プラスティック・ラブ — 竹内まりや
Plastic Love — Mariya Takeuchi
f favorite · g more like this, via DJ Gem

● Retro mode · CP437

Runs where GUIs fear to boot.

One toggle (Settings → Graphics) makes every frame CP437-safe — exactly what a bare Linux console can draw. Great over a crusty SSH session, too.

  • Album art included — redrawn live as text-shade ASCII art.
  • Icons, borders and gauges degrade to the classic VGA charset — nothing ever reflows.
  • CJK titles get a romanized display name — the original metadata stays untouched.
  • Best tried on a real TTY: Ctrl+Alt+F3, log in, ytt.
debian login: ochi
Password:
$ ytt
╔══════════════[ YuTuTui! · Player ]══════════════╗
║                                                ║
║  ♪ Christmas Song - back number                ║
║  [██████████████░░░░░░░░░░░]  3:12 / 5:42      ║
║  >playing   vol 80%   eq:Bass   x:x  r:x       ║
║                                                ║
║              ░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░              ║
║              ▒▒▓▓████████████▓▓▒▒              ║
║              ▓▓██▒▒░░♪  ♪░░▒▒██▓▓              ║
║              ▓▓██░░  ♪♪♪♪  ░░██▓▓              ║
║              ▒▒▓▓████████████▓▓▒▒              ║
║              ░░▒▒▓▓▓▓▓▓▓▓▓▓▓▓▒▒░░              ║
║                                                ║
║  [?] keys  [s] search  [c] queue  [q] back     ║
╚════════════════════════════════════════════════╝

● Leaving Spotify?

Your library moves in with one command.

Liked songs, playlists, the lot — matched track by track, written to YouTube Music or into local playlists, with likes kept in order.

  • Checkpointed & resumable — rate limit, Ctrl-C or power cut, resume continues where it stopped.
  • CJK-safe matching — K-pop and J-pop metadata survive intact.
  • Nothing ambiguous is silently guessed — it lands in a report you review.
  • In-app too: Settings → Accounts imports in the background — exports and CSV/JSON backups included.
ytt transfer
$ ytt auth spotify --client-id <your-app> # one time, PKCE — no secret
$ ytt transfer import liked --to likes
sp2yt-1751443200-a3f1 · fetching liked songs… 512
[███████████████░░░░░] matching 389/512
✓ 486 matched · 19 ambiguous · 7 not found → report saved
interrupted? — ytt transfer resume sp2yt-1751443200-a3f1
$ ytt transfer backup --dir ~/music-backup --csv # every YTM playlist → JSON + CSV

● Last.fm · ListenBrainz

Your listening history, wherever you keep it.

Now Playing as the song starts, the scrobble at the classic half-track-or-4-minutes mark, likes synced to Last.fm as loves. Connect in Settings → Accounts, or with ytt auth lastfm.

  • Written to a crash-safe queue on disk before any network attempt.
  • Flights, dead Wi-Fi, kill -9 — nothing is lost; it delivers itself when you're back.
  • The headless daemon scrobbles too.
  • Self-hosted ListenBrainz? Point api_url at it.
scrobble log — one evening
21:04
Now playing → クリスマスソング
Last.fm ✓ · ListenBrainz ✓
21:07
✓ scrobbled at 2:51
half-track rule — no waiting for the outro
21:09
♥ liked in-app → loved on Last.fm
one keypress, both places
23:30
✈ offline — 14 listens queued
scrobble-queue.jsonl
07:12
✓ back online — 14/14 delivered
automatically, oldest first

● Remote control · daemon · OS integration

The player is wherever you are

Once ytt is playing — or the headless daemon is — boss it around from any shell, your media keys, Control Center or the tray. One command, one tidy line back.

ytt -r ppPlay / pause
ytt -r nextSkip to the next song
ytt -r volume 40Set the volume outright
ytt -r seek-to 90Jump to a timestamp
ytt -r streaming onSwitch endless streaming on
ytt -r status --jsonNow-playing snapshot, script-ready
ytt -r infoOwner mode, protocol and safe capabilities
ytt -r queue-listNumbered queue (1-based)
ytt -r queue-play 2Play the second queue row
ytt -r settings-showCompact, non-secret settings summary
ytt -r watch --jsonPlayer/queue/system events; all adds settings
ytt daemon start --resumeHeadless: restore the saved queue and play
ytt -r play "lofi"Daemon: search and play the first hit
ytt daemon stopStop the daemon and reap mpv
ytt -r status →
[playing] クリスマスソング — back number • vol 80% • 1/4 • streaming on
# wire it to your media keys (i3 / sway)
bindsym XF86AudioPlay exec ytt -r pp
bindsym XF86AudioNext exec ytt -r next

Launching ytt twice never starts a second player — it just hands you the controls. The daemon restores queue, cursor, shuffle/repeat and streaming state, and keeps scrobbling.

Remote control is same-machine, same-OS-user IPC only — never expose its runtime directory as a LAN or HTTP remote.

Control Center macOS

The real Now Playing card: artwork, a working scrubber, even a Like button — and the same mini player rides your menu bar via yututray, shipped with the macOS build.

SMTC + tray mini player Windows

Media overlay with artwork and seek, plus a tray companion: left-click for the mini player, right-click for the full menu. yututray --install-startup if you want it at login.

MPRIS Linux

A first-class org.mpris.MediaPlayer2 citizen: playerctl, GNOME and KDE widgets, waybar — they all just see a music player, because it is one.

mpv bound to its owner

ytt's mpv launches are protected by a heartbeat guardian. POSIX adds an inherited mpv fd lease, Linux also adds PDEATHSIG, and Windows instead uses Job Objects. Recognized Unix terminal/multiplexer loss and normal Windows console events fail closed. Retained ConPTY brokers and repeated Screen/Zellij nesting need the daemon or a host-side lifetime supervisor/lease.

Instant skips

The next track's stream URL is resolved while the current one plays, so "next" starts in a blink, not in three seconds. Gapless by default.

Crash-safe by paranoia

Scrobbles hit disk before the network. Transfers checkpoint every few tracks. Config saves are atomic. Your data assumes the worst so you don't have to.

Self-healing yt-dlp

YouTube changes weekly. ytt keeps its own current yt-dlp (SHA-256-verified), swaps it in when a track breaks, and retries — automatically. ytt doctor checks everything else.

● Two minutes to music

Pick your platform. Paste one line.

The package managers pull in ytt's helpers (mpv, yt-dlp, ffmpeg) for you; the direct installer and source build check for them and tell you what's missing. Then type three letters and you're listening.

ytt@macos ~
$ brew install Ochichan/tap/yututui

Homebrew pulls in mpv, yt-dlp and ffmpeg automatically — and installs yututray, the menu-bar companion, alongside. Don't have Homebrew? Grab it at brew.sh first.

> scoop bucket add extras
> scoop bucket add yututui https://github.com/Ochichan/scoop-bucket
> scoop install yututui

Uses Scoop (scoop.sh). Installs ytt plus mpv, yt-dlp, ffmpeg — and the YuTuTray! mini player, which stays out of your way until you want it.

# Nix — the most reproducible option (helpers included)
$ nix run github:Ochichan/Yututui
# Arch (AUR)
$ yay -S yututui-bin
# Any other distro — prebuilt binary
$ curl -fsSL https://raw.githubusercontent.com/Ochichan/Yututui/main/install.sh | bash

The curl one-liner verifies the checksum and adds ytt to your PATH. It installs only ytt — run ytt doctor afterwards to check the helpers.

# macOS / Linux — needs Rust (rustup.rs)
$ ./install.sh --build
# Windows (PowerShell)
> powershell -ExecutionPolicy Bypass -File .\install.ps1 --build

Clone the repo first. Building takes a few minutes — a great excuse to make coffee.

Then run it: $ ytt …and press ? at any time for every key. The app teaches you the rest.

Something off? Run ytt doctor — it checks mpv, yt-dlp and ffmpeg and tells you exactly what to fix. No YouTube account needed; public tracks play anonymously, and your own account is one cookies.txt away if you want it.