Repository navigation
Releases: servitola/nowplayingseek
Releases · servitola/nowplayingseek
Release list
nowplayingseek 2026.10.04.2
Changed
- Nothing in what the tool does. Its source is rearranged — every command is one entry in a table, the core sits in
src/core/— and this release puts that code on real machines.
nowplayingseek 2026.10.04.1
Fixed
- The Karabiner-Elements rules in the docs end every command in
>/dev/null 2>&1 &. Karabiner stops a command still running when the next one starts, so a knob spun fast moved only by its last click or two.
Changed
forwardandbackwardmove 5 s by default, was 10 — the same as one click of a knob. A held key starts from 5 s too and grows from there.forward 10still moves 10 s.
nowplayingseek 2026.10.04
Changed
- A knob turns the way a hand expects: a careful turn moves 5 s a click, a fast spin up to 20 s a click. Tuned on recordings of a real knob.
- A knob click is 5 s by default, was 2. Keys and scripts still move 10 s.
- The Karabiner-Elements knob rules in the docs also work when a modifier key comes with the click.
Added
- A dash typed in place of two hyphens works:
forward —knobisforward --knob. - A compatibility page and a macOS badge in the README: the macOS versions the live tests passed on.
nowplayingseek 2026.09.20
Changed
- An unknown
[section]or key inconfig.iniis ignored, once named on stderr with its line
number, instead of stopping every command with exit 78 — a config file outlives the version
that reads it, so a setting only a newer (or older) release knows about must not brick this one.
A known key with a value that does not parse is still exit 78: that is a mistake this build can
prove, not a version gap.
Added
artwork [path]writes the cover art to a file (a temp one by default) and prints where;
media-control getandstreamcarry it too, as base64artworkData, unless--no-artwork.
Needs a small compiled helper loaded into/usr/bin/perl—make build/installbuild it,
seedocs/how-it-works.md#artwork.make distbuilds a release tarball — the script, the universal artwork bundle,LICENSE,
README.md— beside its.sha256, and pushing a tag now builds and attaches it to the GitHub
release with build provenance. Releases used to carry only GitHub's source archives, so there
was nothing to download without Homebrew;docs/install.mdwalks that path.docs/shortcuts.md: binding a key in the Shortcuts app, step by step, with screenshots, for
someone who has never opened Terminal. Karabiner assumes a comfort with automation tools that
most people do not have.- For development:
make test-speedruns--help,status,getandforward21 times each
against the fake player and fails when the median goes past a budget, so a slowercli.jsor a
cache that stopped caching is caught before it doubles the time a hotkey takes to answer.
nowplayingseek 2026.09.11
Added
config set <setting> <value>changes one setting without opening the file:config set knob.fast 24. A bad name or value is refused before anything is written, a missing file is started from theconfig inittemplate, and a symlinked config stays a symlink.
nowplayingseek 2026.09.10
Changed
- The help page fits 80 columns, and the exit codes are a table of their own, not a line that wraps.
nowplayingseek 2026.09.09
Changed
- One way to answer, for every command. No flag: a line for people.
--json: the same as JSON, indented — in a pipe as well, where it used to be one line.--minify(or--compact): JSON on one line; a script that reads pipedstatus --jsonline by line wants this now.--raw: the keys macOS itself holds. The order of the flags does not matter. play,pause,toggle,nextandpreviousanswer with the status line, asseekalways did; they used to say nothing.
Added
--json,--minifyand--rawonseek,forward,backward,play,pause,toggle,next,previous,position,duration,doctorandconfig— they werestatusonly.pause --jsonpauses and says where it stopped, in one call.
nowplayingseek 2026.09.07
Changed
- Colour says something now. Playing is green and paused is yellow — the sign, the bar, the line in the log; a seek is blue, a new item magenta, nothing playing red. In JSON a key is blue, a string green, a number yellow,
trueandfalsemagenta. Headings of the help and sections ofconfigare yellow. Only the terminal's own sixteen colours are used, so the reader's theme decides what green is. A pipe,NO_COLORandTERM=dumbget plain text, as before. streamandwatchin a terminal write a log, one line for one event: the time, what happened, and where —13:06:54 ⏸ paused 05:19 / 08:47 ━━━━━━━━━───────. The name of the item is a line of its own, written when it changes. Before, an event and a full status line took turns, and it was hard to tell which line a pause belonged to. A pipe gets what it got.
Added
- For development:
make coverage(lines of logic the unit tests never reach — none now),make typecheck(TypeScript's checker over the built file) andmake globals, which writes the lists inbiome.jsonthat were kept by hand.
Fixed
watchleft its first line on the screen in terminals that draw ▶ two cells wide: a line that reaches the edge wraps, and the redraw clears only its last row. The line now stops four cells short of the edge.watchandstreamend when their reader does. They used to learn of a closed pipe from their next write, and with nothing changing in the player there was none:stream | head -2left a process behind until the next play or pause.- A setting that is a multiplier or a pace no longer takes a clock:
max_multiplier = 1:30was 90. watchwith no controlling terminal printed the shell's/dev/tty: Device not configuredinto its line every second.
nowplayingseek 2026.09.05
Changed
config initwrites every key commented out. A file of live defaults kept its owner on the numbers of the day it was written: the fuse stayed at 10 s on the very machine it was raised on.- What a person reads next to a value — a clock, the app's name, the local time — is one
humanobject at the end ofstatus --jsonand--raw, in a pipe as well. Written after the values in a terminal, as it briefly was, it made the copied text invalid JSON. The object repeats the namesapp,position,durationandtimestamp:jqis not affected, a script that cuts"app":out with a regular expression must take the first one. - A hold goes on for a minute before it ends by itself, not ten seconds (
[hold] max_time). Ten seconds cut a long seek short and made the hand start over from a slow step. The fuse is for a release that never arrives, and that can no longer be lost on the way — it has a file of its own — so the worst a stuck key does is reach the end of the item, where a step stops 5 s short. status --rawputs first what one looks for first — title, length, position, chapter — and folds the four artwork keys into oneArtworkobject at the end.
Fixed
stream --debounceheld back a play or a pause as well; media-control reports those at once.- A step waiting to see itself land could send its target again to an app elected in the meantime: seen once in three tries, a second player thrown 10 s back while a hold on the first was ending. The wait now ends when the elected app changes, and a re-send never crosses apps.
status --rawwrote a file's URL as{}.
Added
- Tests that were attacked before they were trusted: 454 deliberate breakages of the code, of which the suites caught 68 %. The survivors now have tests (294 unit cases, was 207), and the argument cases run against a player that is a file, so a broken check can no longer reach a real one.
watch: stays, and shows where the item is, redrawn once a second, with a line for whatever happens to it — played, paused, seeked to, a new item, nothing playing. The line is redrawn with a carriage return and nothing else, becauseosascriptcannot catch Ctrl-C to tidy a terminal up; a long title is cut to the terminal's width.[watch] intervalsets the pace.streamin a terminal shows the same events in words instead of raw JSON. A pipe gets the media-control protocol byte for byte, as before.make test-world: what the project believes about software it does not own, checked against it — that a binary of our own reads nothing of Now Playing and one signedcom.apple.*does, that VLC reports a rate of 1 while paused and keeps whole seconds, that QuickTime does neither, that nowplaying-cli reads the position as 0, that Homebrew trusts a formula named in full. When one stops holding it says which workaround or sentence it made obsolete.- In a terminal everything is painted for the eye: the help page in sections with the commands in one colour and their arguments dim,
status --jsonand--rawindented with keys, numbers and nulls told apart,configwith its comments dim, an error with its first word in red. A pipe gets exactly what it got before. - In a terminal the status line is painted: the position bold, the length dim, a bar of where you are, the title bold, the chapter when the player tells it (
ch 6/13), the app by its name —· IINA, not(com.colliderli.iina). A pipe gets the line it always got, andNO_COLORorTERM=dumbswitch the paint off. nps, a short name for the same tool:nps forward,nps status. Free in Homebrew; an npm package of that name exists, and whichever comes first inPATHwins.
nowplayingseek 2026.08.19
Added
- The command lines of the tools people used before are understood, so that moving over is a change of one word: nowplaying-cli (
get,get --json,get-raw,togglePlayPause) and media-control (get,stream, its fourteen commands,send,shuffle,repeat,speed) directly; playerctl, mpc and shpotify behind their names —nowplayingseek playerctl position 30+. What is and is not supported: docs/migrating.md. make test-live: the live checklist as a script — VLC on generated silence, paused, 72 cases.status --raw: every key macOS holds for the item, as JSON — chapters, media type, the size of the artwork, the file's URL where the player gives one.
Changed
- The knob is gentler: 2 s a click, up to ×4, and
fast = 18clicks a second — reasoned from encoder datasheets and keyboard firmware, where a quick turn is 8–15 clicks a second and a flick 20–40. With the old numbers one quick rotation crossed three and a half minutes. forward, a hold and the knob stop 5 s short of the end: landing on the very end finished the item, and a page with autoplay loaded the next one.seek <time>stays exact.- A hold ends by itself after 10 s, not 30 (
[hold] max_time): that is ten minutes of film, and a release that never arrives costs that much less.
Fixed
seekto the position the player is already at exited 2 on a paused web page; it exits 0.- Presses 30 ms apart — key repeat, a knob — lost one press in two runs out of three: separate processes read the same last seek, took a refresh meant for an older seek as their own, and the player received the seeks out of order. A lock, a stricter reading of a refresh, and a re-send by the newest process: five presses are +50 s in twenty runs out of twenty.
- A hold stops when another app becomes Now Playing, instead of sending it the old app's targets.
pause,toggle,play,next,previousexit 1 when nothing is playing; they exited 0.forward 0is refused (exit 64); with--holdit was a stack trace.- A player that reports no playback rate while playing no longer has its position stand still.
- Rolling from one held key to the other: letting go of the first stopped the second.
releasenow takes a direction —release forward,release backward— and the recipes pass it; a barereleasestill stops both. - VLC keeps
PlaybackRateat 1 while paused, sostatusshowed it playing with a position that ran ahead, andpause/togglepaused it and then exited 2. The play state now comes from macOS's own flag, not from the rate.