feat(tools): install yt-dlp, ffmpeg and ImageMagick - #448
Merged
Conversation
The three odd ones out in TOOLS: not workflow CLIs, but the media toolchain the rest of the roster is built on. cli-tools fronts all of them — `dl` for yt-dlp, `vid` for ffmpeg, `img` for ImageMagick — and every one of those used to answer a missing binary by telling you to go and install a system package by hand. Now the registry that installs cli-tools installs what it runs on. Each arrives the way it actually ships, which is three different ways: yt-dlp comes from its own releases as a self-contained PyInstaller binary, so it needs no python and no package manager and lands in ~/.local/bin like gh/supabase/doctl. Deliberately not the distro package: extractors break whenever a site changes its markup, upstream ships a fix within days, and a distro package is frozen for the life of a release. Its upgrade is `yt-dlp -U`, the project's own updater. release-install.mjs grew a `bare` flag for it — the asset is the executable, with no archive to unpack — and it must be `unversioned`, because yt-dlp tags by date with no leading "v" and the versioned URL would be /download/v2026.08.19/, a 404 on every release. ffmpeg and ImageMagick exist only as distro packages. Static rebuilds are floating around, but they are unsigned third-party redistributions of somebody else's codec stack, on the two tools most likely to be pointed at a file from the internet — trading a sudo prompt for that is not a trade worth making. So src/pkg-install.mjs dispatches to apt/dnf/zypper/pacman/apk, or Homebrew on macOS. Everything that decides what to run is pure and unit-tested; only the loop that runs it is not. Three things in there are facts about somebody else's archive rather than preference. apt refreshes its index first, because a box that has not updated in months 404s on the archive and the error names a URL instead of the problem. Every manager is invoked non-interactively, because a "continue? [Y/n]" inside `moshcode upgrade tools` parks the whole sweep. And Fedora ships `ffmpeg-free` in its own repositories with the full `ffmpeg` only in RPM Fusion, so package names are a list tried in order rather than one string. `bin` can now be a list of names. ImageMagick is why: the command is `magick` on version 7 and `convert` on 6, both current across supported distros under the same package name, so a single name reports a good install as missing on half the fleet. resolveExecutable tries each; primaryBin() is what reaches a spawn fallback or a message, so a list never gets printed or executed as one. Two existing tests moved with it, both because their assumption expired rather than because they were wrong. `tools --json` promises `binary` as a string, so it emits primaryBin. And the install-plan test asserted a plan mentions curl/wget/npm/pip/brew — yt-dlp is the first entry with both a native updater and one of our own installers, which fetch with node and with the system package manager and so spell neither. Verified end to end: all three release assets resolve 200, and installing yt-dlp into a temp MOSHCODE_BIN produces a working binary (2026.08.19). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LkEHoAhsoDhqVeJ1MJH9yD
ThreatCrush Security Scan0 finding(s) in the 10 file(s) this pull request changes. Nothing in the files this pull request changes. 81 pre-existing finding(s) elsewhere in the repository — **HIGH/CRITICAL**: 5 | **MEDIUM**: 67 | **LOW**: 9Not introduced by this pull request. The full set is in the Security tab.
…and 61 more. Full results in the Security tab. Snippets are redacted; ThreatCrush never prints matched credential material. |
This was referenced Aug 29, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The three odd ones out in
TOOLS: not workflow CLIs, but the media toolchain the rest of the roster is built on.cli-toolsfronts all of them —dlfor yt-dlp,vidfor ffmpeg,imgfor ImageMagick — and every one of those used to answer a missing binary by telling you to go and install a system package by hand. Now the registry that installscli-toolsinstalls what it runs on.Each arrives the way it actually ships, which is three different ways
yt-dlp comes from its own releases as a self-contained PyInstaller binary — no python, no package manager. Deliberately not the distro package: extractors break whenever a site changes its markup, upstream ships a fix within days, and a distro package is frozen for the life of a release. Its upgrade is
yt-dlp -U, the project's own updater.release-install.mjsgrew abareflag for it — the asset is the executable, with no archive to unpack — and yt-dlp must beunversioned, because it tags by date with no leadingv, so the versioned URL would be/download/v2026.08.19/: a 404 on every release.ffmpeg and ImageMagick exist only as distro packages. Static rebuilds are floating around, but they are unsigned third-party redistributions of somebody else's codec stack, on the two tools most likely to be pointed at a file from the internet — trading a sudo prompt for that is not a trade worth making. So
src/pkg-install.mjsdispatches to apt/dnf/zypper/pacman/apk, or Homebrew on macOS, withneedsRoot: { except: ["darwin"] }since brew refuses to run as root.Three things in there are facts about someone else's archive rather than preference:
continue? [Y/n]insidemoshcode upgrade toolsparks the whole sweep.ffmpeg-freein its own repositories with the fullffmpegonly in RPM Fusion, so package names are a list tried in order rather than one string.bincan now be a list of namesImageMagick is why: the command is
magickon version 7 andconverton 6, both current across supported distros under the same package name, so a single name reports a good install as missing on half the fleet.resolveExecutabletries each;primaryBin()is what reaches a spawn fallback or a message, so a list never gets printed or executed as one.Two existing tests moved
Both because their assumption expired, not because they were wrong.
tools --jsonpromisesbinaryas a string, so it now emitsprimaryBin. And the install-plan test asserted a plan mentionscurl|wget|npm|pip|brew— yt-dlp is the first entry with both a native updater and one of our own installers, which fetch with node and with the system package manager and so spell neither.Testing
node --test— 2651 tests, 0 failures (12 new intest/pkg-install.test.mjs, plus yt-dlp and multi-name-bin coverage).Verified against the real world rather than only the suite: all three yt-dlp release assets resolve 200, and installing into a temp
MOSHCODE_BINproduced a working binary reporting2026.08.19.🤖 Generated with Claude Code
https://claude.ai/code/session_01LkEHoAhsoDhqVeJ1MJH9yD