From f00167de105887f3fae1e3b6129b218871c0de8d Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sat, 22 Aug 2026 17:17:02 +0000 Subject: [PATCH] Document genrewatch, img and vid; stop vitest walking into worktrees MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three new commands were on PATH and in `cli-tools list` — which reads bin/ — but absent from both hand-maintained tables. Added, with a section each, plus the two new system requirements: ffmpeg is a hard dependency for `vid` rather than a degradation, and ImageMagick covers what sharp cannot (PDF, PSD, animated GIF). The vitest config is the part worth reading. There was none, so the default glob walked into `.claude/worktrees/` — which is *inside* the repository — and collected other branches' tests as if they were ours. With one worktree open here, `pnpm test` reported 21 files and 427 tests against a real suite of 14 and 284. The inflated count is the harmless half. Those files belong to somebody's in-progress branch, so a run can fail on code that is not on this branch at all, or pass because a half-finished test over there happened to cover the thing you just broke. Either way the suite stops describing the checkout you are in. Verified both directions: a deliberately failing decoy at .claude/worktrees/probe/test/ fails the run without the config and is not collected with it. The default excludes are restated because setting `exclude` replaces them rather than extending them. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 63 +++++++++++++++++++++++++++++++ plugins/tools/commands/install.md | 3 ++ vitest.config.ts | 28 ++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 vitest.config.ts diff --git a/README.md b/README.md index abdcd39..b689f7f 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,9 @@ TypeScript, installed as executables on `PATH`. | [`ask-web`](#ask-web) | Answer a question from the live web, with its sources | | [`tts`](#tts) | Read text aloud and keep the audio | | [`affiliate`](#affiliate) | Work through a list of programs you mean to sign up for | +| [`genrewatch`](#genrewatch) | What is coming out, and whether it exists at all | +| [`img`](#img) | Resize, convert and inspect images, with sharp or ImageMagick | +| [`vid`](#vid) | Inspect, thumbnail, clip and shrink video, through ffmpeg | ## Requirements @@ -25,6 +28,10 @@ TypeScript, installed as executables on `PATH`. - **`dig`** at `/usr/bin/dig` — `domainjson` only - **[OpenRDAP](https://github.com/openrdap/rdap)** (`rdap` on `PATH`, or `~/go/bin/rdap`) — `domainjson` only, and it degrades to DNS-only without it +- **`ffmpeg`** — `vid` only, and it is a hard requirement rather than a + degradation: nothing on npm decodes video the way sharp handles images +- **ImageMagick** (`magick`) — `img` only, and only for what sharp cannot do + (PDF, PSD, animated GIF); sharp ships with this repo as an optional dependency ## Install @@ -572,6 +579,62 @@ someone's behalf — and every one of these is behind an email-verification loop regardless, so a form-filler would stop at the same wall with one more moving part. +### `genrewatch` + +What is coming out, and whether a thing exists at all: + +```sh +genrewatch search blade runner # back catalogue as well as the calendar +genrewatch upcoming -c film -n 10 +genrewatch categories # tv | film | anime | music | space +genrewatch upcoming -g drama-tv --json +``` + +Search reaches the back catalogue, so a film from 1999 is a valid answer, and +anything the site does not already hold is looked up live. `--base` points at +another deployment. + +A date with no time prints as a date. The API says which is which, and a release +genuinely has no hour — printing one would be inventing it. + +### `img` + +Image work without opening an editor: + +```sh +img info logo.png # dimensions, format, size +img resize hero.jpg -w 1200 -o hero@2x.jpg +img convert shot.png --to webp +img icons logo.png --out public/ # the favicon/PWA set +``` + +**It never enlarges by default.** Scaling a 96px mark up to 512 produces a +blurry file that looks like a bug in whatever renders it, so that needs +`--force`. + +Two engines: `sharp` arrives with this repo as an optional dependency and is +fast; ImageMagick is a system binary and handles PDF, PSD and animated GIF, +which sharp does not. `--engine` picks. + +### `vid` + +The four things anybody actually needs ffmpeg for: + +```sh +vid info clip.mp4 # duration, streams, size +vid thumb talk.mp4 --at 00:01:30 +vid clip talk.mp4 --from 00:01:00 --to 00:02:00 +vid shrink talk.mp4 --height 720 # --crf 28 by default +vid audio talk.mp4 # → talk.m4a +``` + +`clip` copies streams rather than re-encoding, so it is nearly instant and cuts +at the nearest keyframe — which can be a second or two off what you asked for. +That is the trade: re-encoding to hit an exact frame takes as long as the clip. + +Needs `ffmpeg` on `PATH`. There is no bundled fallback — nothing on npm decodes +video the way sharp handles images. + ## As a moshcode plugin This repo is also a plugin marketplace: diff --git a/plugins/tools/commands/install.md b/plugins/tools/commands/install.md index 985ccb4..5a9afc7 100644 --- a/plugins/tools/commands/install.md +++ b/plugins/tools/commands/install.md @@ -41,11 +41,14 @@ The installer clones to `~/.local/share/cli-tools` (override with | `domainfree` | Which of these domains you can actually register | | `domainjson` | whois-style, JSON-first name lookup | | `generate-names` | Turn a sentence about a product into candidate names | +| `genrewatch` | What is coming out, and whether it exists at all | | `gh-prs` | Every open PR across the owners you name | | `gh-prs-fix-all` | Repair the open scan PRs that are broken because of us | | `gh-prs-merge` | Squash-merge the PRs that are genuinely ready | +| `img` | Resize, convert and inspect images, with sharp or ImageMagick | | `tcfeed` | Find repositories worth scanning, scan them, print a shortlist | | `tts` | Read text aloud and keep the audio | +| `vid` | Inspect, thumbnail, clip and shrink video, through ffmpeg | Rather than listing them by hand, `cli-tools list` reads `bin/` — a new command is a new file there and nothing else has to be edited, so that output is right diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..5c2dfd7 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,28 @@ +import { defineConfig } from 'vitest/config'; + +/** + * Keep the suite to this checkout's own tests. + * + * `EnterWorktree` and `git worktree add` both put working trees under + * `.claude/worktrees/`, which is *inside* the repository — so vitest's default + * glob walks into them and collects their `test/*.test.ts` as if they were + * ours. With one worktree open here that turned a 14-file, 284-test run into 21 + * files and 427 tests, and the count is the harmless half: those files are + * somebody's in-progress branch, so a run can fail on code that is not on this + * branch at all, or pass because a half-finished test on another branch + * happened to cover the thing you just broke. + * + * The default excludes are restated because setting `exclude` replaces them + * rather than adding to them. + */ +export default defineConfig({ + test: { + exclude: [ + '**/node_modules/**', + '**/dist/**', + '**/cypress/**', + '**/.{idea,git,cache,output,temp}/**', + '**/.claude/**', + ], + }, +});