Skip to content

Latest commit

 

History

History
177 lines (144 loc) · 6.96 KB

File metadata and controls

177 lines (144 loc) · 6.96 KB

ytcli

TUI client for yt music
search, browse, and play from your terminal

ytcli searching, browsing, and playing

version MIT

zig 0.16, single binary

  • libmpv for audio
  • shells out to curl and yt-dlp
  • astats lavfi filter for visualizer via ffmpeg

version

v0.1.6

  • fix crash on non-UTF-8 autocomplete (the suggest endpoint answers in latin-1 without ie/oe=utf-8)
  • remote text is scrubbed of control bytes before it reaches your terminal or your history/playlist files
  • autoplay skips rows with no video id instead of calling yt-dlp with an empty one
  • your history file keeps one line per search instead of piling up duplicates
  • a stream that fails to open now says so in the status bar instead of sitting at 00:00
  • curl/yt-dlp calls now have timeouts and an output cap
  • playback needs a current yt-dlp: stale versions get 403'd by youtube and sit at 00:00
v0.1.5
  • playlists: build as you browse: P saves the selected result, Ctrl+A saves whatever is playing; create a new list or add to an existing list
  • your playlists sit above recent searches on the search screen
  • Ctrl+X twice deletes the selected playlist or forgets the selected past search; d/Ctrl+X removes a track from an open playlist
  • ytcli playlists [name] prints them for piping
  • CJK/emoji titles no longer break the layout
  • long queries scroll with the cursor instead of vanishing off the edge
  • 5 new themes (tokyonight, catppuccin, matrix, rosepine, solarized)
  • frames drawn inside synchronized output — no tearing on theme switch
  • recoverable failures land in log and status bar instead of dropping you out
previous

v0.1.4

  • m mute toggle (now-playing meter reads mute, visualizer idles while muted)
  • Ctrl+R repeat mode: off → track → queue (autoplay loops per mode)
  • volume persists across sessions (saved to config alongside theme)
  • tracks over an hour render h:mm:ss

v0.1.3

  • selecting a track stops audio immediately + shows connecting to YouTube… in the now-playing footer
  • fix album view mislabeling tracks with a related artist (reads album header, not first channel link)
  • fix freeBSD release build (zig 0.16 translate-c: headers pulling <sys/time.h>, and __ssp fortify wrappers → std.c + _FORTIFY_SOURCE=0)
  • macOS release is now one universal binary (arm64 + x86_64), cross-built + lipo'd on a single runner
  • release CI timeout-minutes

v0.1.2

  • failures log to ~/.local/share/ytcli/log (timestamp + cause)
  • ctrl+c restores cleanly to terminal in all cases
  • play video ids beginning with - (yt-dlp -- arg fix)
  • fix freeBSD build (terminal size via std, not <sys/ioctl.h>)
  • readme fix: brew install mpv already pulls in yt-dlp, libmpv-dev however does not

v0.1.1

  • github actions for release builds
  • prebuilt binaries: macOS, linux, freeBSD
  • hardened temp writes (mkstemp, 0600)

v0.1

  • autoplays through result list
  • drills into albums
  • handful of color themes

build/install

zig build                              # → zig-out/bin/ytcli
zig build install --prefix ~/.local    # → ~/.local/bin/ytcli

dependencies

install ex.
brew install mpv ffmpeg                # macOS (mpv pulls in yt-dlp)
apt install libmpv-dev yt-dlp ffmpeg   # Debian/Ubuntu

[ ! ] currently requires mpv, ffmpeg and yt-dlp particularly on PATH — keep yt-dlp updated, youtube breaks old versions

releases

macOS (universal: arm64 + x86_64), Linux (arm64/x86_64), and FreeBSD binaries are attached to each release. windows: run under WSL (no native build currently).

run

ytcli               # TUI
ytcli <query>       # play first hit
ytcli -s <query>    # search, print results
ytcli history       # past queries
ytcli playlists     # saved playlists (add a name to print its tracks)
ytcli --theme cyan  # red (default) | cyan | mono | dracula | nord | gruvbox
                    # tokyonight | catppuccin | matrix | rosepine | solarized
ytcli --themes      # list themes
ytcli -h | -v

commands

made an effort to use commands that felt intuitive

view

search screen: (your playlists, then recent searches — one list)

  • text to query, ↑/↓ move
  • opens the selected playlist, or searches the selected/typed query
  • tab/ accept completion (or open the selected playlist)
  • Ctrl+X twice — deletes the selected playlist, or forgets the selected past search
  • esc clear
  • Ctrl+T cycle filter (all/songs/videos/albums/artists)

results:

  • j/k or ↑/↓ move
  • g/G top/end
  • Ctrl+F/B page
  • h/esc back
  • P save to a playlist — never starts playback (pick one, or type a name for a new one)

inside a playlist:

  • /l play, queueing the rest of the list
  • d or Ctrl+X remove the selected track
  • P copy it into another playlist
  • Ctrl+A saves whatever is playing, from any screen

playback/anytime:

  • Ctrl+P/space pause
  • Ctrl+N next
  • Ctrl+S stop
  • [/] seek ±10s
  • {/} ±60s
  • -/= volume ±5 (persists)
  • m mute
  • Ctrl+R repeat (off/track/queue)
  • Ctrl+Y theme

storage/config

  • $XDG_DATA_HOME/ytcli/history - query log (falls back to ~/.local/share/ytcli/history).
  • $XDG_DATA_HOME/ytcli/log - timestamped failures (search/album/stream) with the underlying error and any curl/yt-dlp stderr. check here first when something says (see log).
  • $XDG_DATA_HOME/ytcli/playlists - saved playlists: [name] header, then one video_id⇥title⇥artist⇥kind line per track. tab-separated, editable by hand.
  • $XDG_CONFIG_HOME/ytcli/config - key=value settings.

history is just newline-delimited text - grep/cat it, or seed it so the TUI autocompletes your favorites from the first keystroke:

ex.
printf '%s\n' "elephant gym" "autechre" "john zorn" >> ~/.local/share/ytcli/history
grep -i jazz ~/.local/share/ytcli/history

[ ! ] loads newest-first and dedups, so re-seeding or reordering is harmless.

ytcli -s <query> prints title — artist [video_id], one per line; pipe it anywhere. YTCLI_THEME sets the theme without a flag.

[ ! ] requests written to /tmp/ytcli_body* (mkstemp, 0600, unlinked after) per call + audio streamed/buffered via mpv; not written to disk.

visualizer

simple spectrum bars via astats lavfi filter
dB to linear/modulated per bar - not a true per-band FFT

contribution

please feel free to contribute, not a guarantee it will be merged

[ ! ] thank you for your attention