ffmpeg-skill 1.0.2 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -349,11 +349,11 @@ Benchmarks live in `tests/bench_*.py`, agent evals in [evals/](evals/), results
349
349
  ```bash
350
350
  npx ffmpeg-skill # Claude Code → ~/.claude/skills/ffmpeg-skill
351
351
  npx ffmpeg-skill --cursor # Cursor → ~/.cursor/skills/ffmpeg-skill
352
- npx ffmpeg-skill --codex # Codex → ~/.codex/skills/ffmpeg-skill
352
+ npx ffmpeg-skill --codex # Codex → ~/.agents/skills/ffmpeg-skill (Cursor reads this location too)
353
353
  npx ffmpeg-skill --all # all three
354
354
  npx ffmpeg-skill --project # this project → ./.claude/skills/ffmpeg-skill
355
355
  npx ffmpeg-skill --dir ./my-skills
356
- npx ffmpeg-skill --uninstall # remove from the selected targets
356
+ npx ffmpeg-skill --uninstall # remove from the selected targets (--codex also clears the older ~/.codex/skills location)
357
357
  ```
358
358
 
359
359
  Without Node: clone this repository and copy `SKILL.md`, `scripts/`, `references/` and `mcp/` into your agent's skills directory.
package/SKILL.md CHANGED
@@ -118,7 +118,7 @@ This skill cuts, joins, measures, syncs, exports and checks files — it execute
118
118
 
119
119
  The line in general: if the same input and the same explicit parameters always produce the same, verifiable output, it belongs here. If the "right" answer depends on taste, content understanding, or what looks or sounds good, it belongs to whichever skill or agent makes that judgement — this skill only ever executes parameters it's given, never infers them from what something looks or sounds like.
120
120
 
121
- If a request needs an FFmpeg feature none of the 28 scripts expose, say so and name the closest built-in option (`--dry-run` to show what would run, or a documented limitation) — never fall back to guessing a raw `ffmpeg`/`ffprobe` invocation or a hand-built filter graph outside `scripts/*.py`. A raw command bypasses every guarantee this skill makes (no shell, typed arguments, verification afterwards); it is exactly the failure mode this skill exists to prevent, so it is never the fallback when a script's flag doesn't cover something.
121
+ If a request needs an FFmpeg feature none of the 40 scripts expose, say so and name the closest built-in option (`--dry-run` to show what would run, or a documented limitation) — never fall back to guessing a raw `ffmpeg`/`ffprobe` invocation or a hand-built filter graph outside `scripts/*.py`. A raw command bypasses every guarantee this skill makes (no shell, typed arguments, verification afterwards); it is exactly the failure mode this skill exists to prevent, so it is never the fallback when a script's flag doesn't cover something.
122
122
 
123
123
  ## Request → script
124
124
 
package/bin/install.js CHANGED
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * npx ffmpeg-skill # Claude Code
9
9
  * npx ffmpeg-skill --cursor # Cursor (~/.cursor/skills/ffmpeg-skill)
10
- * npx ffmpeg-skill --codex # Codex (~/.codex/skills/ffmpeg-skill)
10
+ * npx ffmpeg-skill --codex # Codex (~/.agents/skills/ffmpeg-skill)
11
11
  * npx ffmpeg-skill --all # all of the above
12
12
  * npx ffmpeg-skill --dir ./skills # custom parent directory
13
13
  * npx ffmpeg-skill --project # ./.claude/skills/ffmpeg-skill in the current project
@@ -69,7 +69,10 @@ if (!want.claude && !want.cursor && !want.codex && !customDir && !project) want.
69
69
 
70
70
  if (want.claude) targets.push({ label: 'Claude Code', dir: path.join(home, '.claude', 'skills', SKILL_NAME) });
71
71
  if (want.cursor) targets.push({ label: 'Cursor', dir: path.join(home, '.cursor', 'skills', SKILL_NAME) });
72
- if (want.codex) targets.push({ label: 'Codex', dir: path.join(home, '.codex', 'skills', SKILL_NAME) });
72
+ // Codex reads user-level skills from ~/.agents/skills (its docs list $HOME/.agents/skills,
73
+ // .agents/skills up the repo tree, and /etc/codex/skills), not ~/.codex/skills -- the
74
+ // latter was this installer's original guess and is not a location current Codex scans.
75
+ if (want.codex) targets.push({ label: 'Codex', dir: path.join(home, '.agents', 'skills', SKILL_NAME), legacy: path.join(home, '.codex', 'skills', SKILL_NAME) });
73
76
  if (project) targets.push({ label: 'project (.claude/skills)', dir: path.join(process.cwd(), '.claude', 'skills', SKILL_NAME) });
74
77
  if (customDir) targets.push({ label: 'custom', dir: path.join(path.resolve(customDir), SKILL_NAME) });
75
78
 
@@ -106,6 +109,12 @@ for (const t of targets) {
106
109
  if (has('--uninstall')) {
107
110
  fs.rmSync(t.dir, { recursive: true, force: true });
108
111
  console.log(`removed ${t.label}: ${t.dir}`);
112
+ // A copy left by the installer's earlier, wrong guess at this agent's directory (see the
113
+ // Codex target above) would otherwise survive every uninstall from here on.
114
+ if (t.legacy && fs.existsSync(t.legacy)) {
115
+ fs.rmSync(t.legacy, { recursive: true, force: true });
116
+ console.log(`removed ${t.label} (older install location): ${t.legacy}`);
117
+ }
109
118
  continue;
110
119
  }
111
120
  // Copy into a scratch directory next to the real target first, then swap it into place
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ffmpeg-skill",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Agent Skill that gives coding agents (Claude Code, Cursor, Codex) a local video editor: 40 FFmpeg tools with a machine-readable contract, contract-derived MCP server, FFmpeg capability detection, probe-first / verify-last workflow. Cut, join, silence removal, fit, captions and karaoke, overlays, motion graphics, HDR to SDR, LUTs, audio clean-up and typed dynamics, sync with drift correction, multicam, loudness, delivery checks, project rendering, batch. No API keys, no cloud, no dependencies.",
5
5
  "keywords": [
6
6
  "ffmpeg",
@@ -30,23 +30,43 @@ Caught twice while adding capability metadata for new flags (`caption.py --mode
30
30
  after a test failure revealed it. Do that grep first, every time `required`/`optional`
31
31
  changes.
32
32
 
33
- ## Git tag push and GitHub Release creation are not reachable from this environment
33
+ ## Git tag push and GitHub Release creation are not reachable from this environment — so they are not done from it
34
34
 
35
35
  The git credentials available here can push to `refs/heads/*` (branches) but not
36
36
  `refs/tags/*` — confirmed by a 403 straight from the git-receive-pack endpoint, not an
37
37
  auth failure, meaning it's a deliberate scope restriction, not a bug to route around.
38
- The GitHub MCP tool surface has no `create_release`/`create_tag` equivalent either
39
- (`create_branch`, `create_pull_request`, `create_or_update_file` exist; nothing for
40
- releases). A direct call to the GitHub REST API's `/releases` endpoint with a raw token
41
- is also blocked by the outbound proxy itself (its own 403, pointing at Anthropic's docs,
42
- not GitHub's).
38
+ The GitHub MCP tool surface has no `create_release`/`create_tag` equivalent either, and a
39
+ direct call to the GitHub REST API's `/releases` endpoint with a raw token is blocked by
40
+ the outbound proxy itself.
43
41
 
44
42
  Confirmed once (retried the tag push a second time "just in case" before accepting it).
45
- Don't retry either path a second time if `git push origin <tag>` 403s, or no
46
- release-creation tool is found in one `ToolSearch` pass, say so once and hand the user
47
- the two-minute browser-only path instead (open the repo's `/releases/new`, type the new
48
- tag name in the tag fieldGitHub creates it from the target branch on publish, no git
49
- command needed).
43
+ Don't retry either path a second time. Since 0.16.11 this is moot for releases:
44
+ `.github/workflows/release.yml` creates the tag, the GitHub Release and the npm publish
45
+ from GitHub Actions on every push to `main` (README, "Development" "Releasing"), so a
46
+ session never needs to push a tag at all merging the PR is the release. The one thing
47
+ still worth knowing: that workflow's own `git push origin HEAD:main` (the automatic
48
+ version-bump commit) and its tag run under the built-in `GITHUB_TOKEN`, which by design
49
+ triggers no further workflow runs, so a red `tests` run for that bump commit is not
50
+ "missing" — it is never scheduled; the PR run before the merge is the one that counted.
51
+
52
+ ## A throwaway probe must be pointed at a copy in a directory you have just verified with `pwd`, never at "the repo, probably"
53
+
54
+ While validating the auto-bump script for `release.yml`, a scratch run was meant to
55
+ execute against a temporary copy of the repo. It ran with the real checkout as its
56
+ working directory instead — a `cd` into the scratch path happened in a shell whose
57
+ working directory was reset between commands — and its `git add -A && git commit`,
58
+ `git tag v0.16.12` and two empty commits landed on the real branch and moved the real
59
+ local `v0.16.12` tag. Nothing was pushed, and `git reflog` plus a `git fetch --force` of
60
+ the tag from `origin` restored everything, but it was only noticed because `git status`
61
+ showed files the session had not edited.
62
+
63
+ Rule: a probe that runs `git commit`, `git tag`, `rm -rf`, or writes into the tree goes
64
+ in a directory created *and* verified in the same command (`cd "$DIR" && pwd && ...`),
65
+ not one assumed from an earlier `cd`; prefer a fixture built from a few `printf` lines
66
+ over a copy of the whole checkout (the copy carries the real `.git`, so a mistake there
67
+ is a mistake in the real history); and run `git status` on the real repo before
68
+ committing anything afterwards. `.claude/skills/destructive-operations/SKILL.md` says the
69
+ same thing for the tools themselves — it applies to the person testing them too.
50
70
 
51
71
  ## A quantitative test failing three different ways across fixture redesigns means the platform, not the fixture, is the problem
52
72