Skip to content

Command Line (nokkvi CLI)

nokkvi <verb> sends a single command to the running Nokkvi instance over a Unix socket and exits. Use it from shell scripts, window manager keybinds, or any external tool — there’s no GUI startup cost because the CLI path returns before iced initializes.

The CLI is an alternative to MPRIS. MPRIS covers the standard transport surface and works with any MPRIS controller; the CLI adds verbs that MPRIS doesn’t expose (switch-view, love, rate, clear-queue, consume, queue-push, queue-pull, theater, preset).

VerbArgAction
play—Start playback
pause—Pause playback
play-pause—Toggle play / pause
stop—Stop and reset the playhead
next—Skip to the next track
previous—Return to the previous track
seek<value>Seek the playing track — see Seek syntax
volume<value>Set volume — see Volume syntax
VerbArgAction
shuffle—Toggle random mode
repeat—Cycle repeat: off → one → queue
consume—Toggle consume mode
clear-queue—Empty the queue and stop playback
add-to-queue—Add the focused list item to the queue — the in-app Shift+A
remove-from-queue—Remove the centered queue song — Ctrl+D; errors not_in_queue_view outside the queue view
queue-push—Save the queue to the server — the sync menu’s Push row. Errors empty_queue; unsupported if the server lacks the indexBasedQueue extension; unavailable during radio. See Queue sync
queue-pull—Restore the server’s saved queue without starting playback — the sync menu’s Pull row. Same guards as queue-push, minus the empty-queue check
VerbArgAction
switch-view<view>Switch the top pane — see View names
VerbArgAction
nav-up—Move the focused list selection up — Backspace
nav-down—Move the focused list selection down — Tab
enter—Activate the centered item — play / expand / edit

nav-up, nav-down, and enter are fire-and-forget; the move is async, so query selection afterward to read where focus landed.

These are pure reads — they print JSON and change nothing.

VerbArgAction
status—Print playback state, track, album, position, duration, volume, the three modes, whether Theater Mode is on (theater), the visualizer mode (visualizer) and the MilkDrop preset on screen (preset, or null) as JSON
selection—Print the focused view’s centered item as JSON: view, kind, name, artist, rating, starred; kind is null when nothing is selectable

These act on whatever’s currently playing and exit 1 with a no_playing_track error if nothing is loaded.

VerbArgAction
love—Toggle Navidrome star on the playing track
rate<delta-or-abs>Adjust the playing track rating — see Rating syntax
VerbArgAction
ping—Probe the running instance. Prints pong and exits 0.
show—Bring the window back: reopens it after it was closed to the tray ({"window":"opened"}), flags an open window for attention ({"window":"already-open"}), or does nothing while a window is already opening ({"window":"opening"}). The same action as MPRIS Raise.
theater—Toggle Theater Mode, the same as F11. Prints {"theater":true} or {"theater":false}. Refuses with an unavailable error on the login screen or while the window is closed to the tray.
preset<action>Control MilkDrop presets: next, previous, lock, unlock, favorite, unfavorite or hide. Prints {"preset":…,"loading":…,"locked":bool}: preset is the one on screen (as status reports it) and loading names a newly requested preset still being prepared (or null). lock and favorite set the state rather than toggling it, so a script gets the same result every time. Refuses with unavailable on the login screen, outside MilkDrop mode, when MilkDrop isn’t playing on screen (next, previous), with no preset on screen (favorite, unfavorite, hide), when every preset is hidden (next) or when there’s nothing to go back to (previous); an unknown action is invalid_args.
-h, --help—Print usage and the full verb catalog, then exit 0.
-V, --version—Print nokkvi <version>, then exit 0.

Running nokkvi with no arguments while an instance is up forwards show to it and exits 0, so a launcher entry or keybind that starts Nokkvi brings back a window closed to the tray instead of failing. Any unrecognized argument (nokkvi nexxt) still refuses with exit 1.

On Wayland an already-open window can only be flagged, not focused: the compositor shows the request as an urgency hint and decides whether to switch to it (on Hyprland, misc:focus_on_activate = true makes it switch).

The <value> arg accepts two shapes:

  • Delta — +N or -N, added to the current volume and clamped silently to 0.0..=1.0. Repeated volume +0.05 at the ceiling is a no-op.
  • Absolute — N in 0.0..=1.0. Out-of-range values error rather than clamp.
Terminal window
nokkvi volume +0.05 # bump 5%
nokkvi volume -0.1 # drop 10%
nokkvi volume 0.5 # set to 50%

The <value> arg accepts two shapes:

  • Relative — +N or -N, in seconds, moved from wherever the track currently is. +0 and -0 do nothing. Past the end ends the track (the next one plays, as if you had dragged the slider there); past the start parks at 0:00.
  • Absolute — N, in seconds from the start of the track.

Fractions are fine (+2.5). nan, inf, 1:30 and anything else that is not a finite number are rejected.

Terminal window
nokkvi seek +10 # jump 10s ahead
nokkvi seek -10 # jump 10s back
nokkvi seek 90 # go to 1:30

Relative calls that arrive faster than the audio engine can apply them add up rather than piling on top of each other, so holding a media-key binding or firing playerctl position 5+ in a loop scrubs smoothly.

An absolute seek answers with where it was sent ({"position":90}); a relative one answers with the offset it dispatched ({"offset":10}), because the landing point is not known until the engine applies it. Ask nokkvi status for the resulting position.

Seeking is unavailable during radio playback — the verb returns an unavailable error.

The <delta-or-abs> arg accepts two shapes:

  • Delta — +N or -N, added to the current rating and clamped to 0..=5.
  • Absolute — 0 through 5. Out-of-range values error.
Terminal window
nokkvi rate +1 # bump by one star
nokkvi rate -1 # drop by one star
nokkvi rate 5 # set to five stars
nokkvi rate 0 # clear the rating

To confirm each change with a desktop notification — useful when you’ve bound these to a window-manager keybind — enable rating_change_notification_enabled.

switch-view accepts one of: albums, queue, songs, artists, genres, playlists, radios, harbour, settings. Anything else errors with the full list in the message.

Terminal window
nokkvi switch-view albums
nokkvi switch-view queue
nokkvi switch-view harbour # jump to the Harbour home view

Each running Nokkvi daemon binds a per-PID socket so multiple instances can coexist:

EnvironmentSocket path
$XDG_RUNTIME_DIR set$XDG_RUNTIME_DIR/nokkvi-{pid}.sock
Unset (fallback)/tmp/nokkvi-{uid}-{pid}.sock

The {uid} in the fallback path comes from the $UID environment variable, not the kernel uid. When $UID is unset it falls back to the literal default (e.g. /tmp/nokkvi-default-{pid}.sock).

The CLI auto-discovers the live socket — you don’t pass a path. If no instance is running, the command exits 1 with a message listing the directory it searched.

CodeMeaning
0Server accepted the verb. Any payload is printed to stdout (e.g. ping prints pong).
1No live instance found, or the server returned an error (e.g. invalid_args, no_playing_track, unsupported, unavailable, empty_queue, not_in_queue_view). Error message goes to stderr.

Hyprland’s Lua config is the current binding API — hl.bind(keys, hl.dsp.exec_cmd(cmd), opts?) matches the shape from the upstream example/hyprland.lua. The Lua block below is the author’s actual ~/.config/hypr/keybinds.lua for nokkvi; the legacy .conf tab is for stable distros still on the older Hyprland.

-- ~/.config/hypr/keybinds.lua
local mod_alt = "SUPER + ALT"
-- Transport
hl.bind(mod_alt .. " + space", hl.dsp.exec_cmd("nokkvi play-pause"))
hl.bind(mod_alt .. " + right", hl.dsp.exec_cmd("nokkvi next"))
hl.bind(mod_alt .. " + left", hl.dsp.exec_cmd("nokkvi previous"))
-- Volume — { repeating = true } repeats while held
hl.bind(mod_alt .. " + up", hl.dsp.exec_cmd("nokkvi volume +0.01"), { repeating = true })
hl.bind(mod_alt .. " + down", hl.dsp.exec_cmd("nokkvi volume -0.01"), { repeating = true })
-- Rating + love on the currently playing track
hl.bind(mod_alt .. " + L", hl.dsp.exec_cmd("nokkvi love"))
hl.bind(mod_alt .. " + equal", hl.dsp.exec_cmd("nokkvi rate +1"))
hl.bind(mod_alt .. " + minus", hl.dsp.exec_cmd("nokkvi rate -1"))

Add { locked = true } (Lua) or use bindl/bindle (.conf) on any bind you want to keep working while the session is locked — the upstream example sets it on XF86Audio* keys.

The CLI is a plain executable — use whatever your compositor’s exec-keybind syntax is (sway’s bindsym, i3’s bindsym, dwm’s config.h, etc.) and call nokkvi <verb> from it.