Repository navigation
fix(skills): plugin launcher and media helpers run the pinned CLI, not a project copy - #7552
Conversation
…t a project copy The plugin launcher now starts npx from the home folder, so the project's node_modules, package.json bin and .npmrc cannot choose which CLI npm runs or how it starts it. It names the project in HYPERFRAMES_PLUGIN_CWD and the CLI's bin moves into that folder before anything else runs, then drops the variable so nested runs keep the folder their caller gives them. In --script mode the launcher hands itself over as HYPERFRAMES_CLI_ENTRY. The media helpers (Kokoro voice, transcription, the resolve shim) run the CLI they were handed, and stop with an actionable message when none was, instead of resolving `npx hyperframes` from the project. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Verdict: APPROVE · 0 blocker · 1 important · 1 nit · head 2956757
The isolation works: npx starts in home, helpers go through the launcher, and the standalone transcribe.mjs/audio.mjs path stops with the actionable message (checked locally). Both findings are inline. The PWD one is a small user-visible regression on preview and is worth fixing before merge.
Scope
Read end-to-end: bin/hyperframes.mjs, plugin-cli.mjs, both npx-sync.mjs copies, tts.mjs spawn path, tts-local-provider.mjs, resolve.mjs, transcribe.mjs error path, docs. Grepped every npx/"hyperframes" spawn under skills/ and packages/cli/src/media-use; none remain outside the hand-over. Ran a real npx -p hyperframes@0.9.33 from home with PWD=<project> and got PWD=$HOME INIT_CWD=$HOME. CI green on head.
— Genesis
The CLI bin now sets PWD to the project folder after moving into it, because npm's shell resets PWD to the folder npx started in and preview names the project from PWD. The plugin launcher no longer falls back to the temp folder when there is no home folder; it stops with an error instead, and only when it is about to start npx. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The plugin launcher and the media helpers now always run the CLI the plugin pins, or the one their caller hands over. Before, npm could pick it up from the user's project folder.
What
skills/hyperframes/scripts/plugin-cli.mjsstartsnpx --yes hyperframes@<plugin version>from the home folder rather than the project. It passes the project folder inHYPERFRAMES_PLUGIN_CWD.packages/cli/bin/hyperframes.mjschanges intoHYPERFRAMES_PLUGIN_CWDbefore anything else runs, and removes the variable so nested CLI runs keep the folder their caller gives them.--scriptmode the launcher setsHYPERFRAMES_CLI_ENTRYto itself.transcribeWavintts.mjs,transcribe.mjsthroughnpx-sync.mjs, and the resolve shim. Each runs the handed-over CLI. When no CLI is handed over, each stops with a message that says how to supply one, and no longer resolvesnpx hyperframes. The CLI's ownmedia-usecommand already hands over its entry (fix(cli): keep project folders from choosing the programs and config the CLI runs #7511), so nothing changes when the CLI runs them.Why
npm reads the package, its bin links and
.npmrcfrom the folder npx starts in. The CLI that runs should depend only on the plugin release, or on what the user chose explicitly.Related work
Refs #7511 (CLI hands its entry to the media-use engine) and #7524 (helper programs are taken only from install locations).
How
hyperframes skillsalready does fornpx skills@<pin>(fix(cli): keep project folders from choosing the programs and config the CLI runs #7511), so npm only reads config the user owns.checkclient anddist/cli.jsload. The plugin release and the CLI release share one version, so the launcher always runs a CLI that has this bin.HYPERFRAMES_CLI_ENTRYhand-over. The launcher's--scriptmode passes its own path, so a helper runsnode plugin-cli.mjs tts ...and gets the same pinned, isolated resolution.audio.mjsortranscribe.mjsdirectly now has to setHYPERFRAMES_CLI_ENTRY(to its installedbin/hyperframes.mjs) for the Kokoro, transcription and whisper fallback steps. The docs and the error message both say so.Claude Opus 5.5
What I measured
npxagainst a temp project. The project hadnode_modules/hyperframes@0.9.33with a bin that writes a marker,node_modules/.bin/hyperframes, apackage.jsonbin namedhyperframes, and an.npmrcwithregistry=http://127.0.0.1:9/and a marker-writingscript-shell. Each run wasplugin-cli.mjs --version:.npmrcscript-shellran (marker written).node_modulesonly: it ran the project's copy and printedFAKE.hyperframes: not found.0.9.33from the registry CLI, and no marker was written.plugin-cli.mjs --script <plugin>/skills/media-use/scripts/resolve.mjs --doctorin the same project. It ran the genuine CLI's doctor and wrote no marker. Running the shim with no launcher printed the hand-over message and exited 1.HYPERFRAMES_PLUGIN_CWD=/x npx -p hyperframes@0.9.33 node -e ...run from home confirms that npm exec passes the variable through. The child's cwd was home, and the.binfrom the npx cache came first on PATH.Tests
plugin-cli.test.mjs: npx starts outside a project that has.npmrc, a.binentry and apackage.jsonbin, and receives the project folder.--scripthands over the launcher.binEntry.test.tsruns the real bin over stub dist files. It checks that the bin moves into the named project and does not pass the variable on, and that it stays put when no folder is named.tts.test.mjs,tts.spawn.test.mjs,transcribe.test.mjs,resolve-plugin.test.mjs,tts-local-provider.test.mjs,npx-sync.test.mjs: these use the handed-over CLI. A missing or relative hand-over fails with the message, and a stubnpxon PATH is never run.tts.cleanup.test.mjsandgemini-pipeline.test.mjsnow hand over a stub CLI instead of a stubnpx.--scripthand-over (1), project folder hand-over (2), binchdir(1), bin variable removal (1),tts.mjsnpx fallback (4),npx-sync.mjsnpx fallback (2), and the origin/main resolve shim (2).find skills packages/cli/src/media-use -name '*.test.mjs'plus the parity tests) pass. So do the CLI vitest filesbinEntry,media-useandinstallerDetection, pluslint:skills,gen-skills-manifest --check, oxfmt and oxlint.What I did NOT exercise
npxrun of a CLI built from this branch. The published 0.9.33 does not have the bin change, so I covered the folder move with the bin test and the env pass-through check above.cwdand env, and its unit test covers that, but I did not run it on Windows..tsentry),media-usedoes not hand over an entry (unchanged from fix(cli): keep project folders from choosing the programs and config the CLI runs #7511). Kokoro then falls through with the hand-over message instead of running the published CLI.resolveSpawnCommand's Windows npx-cli rerouting is now reachable only for npx packages other thanhyperframes, and nothing calls it that way today. I kept it and pointed its tests at a neutral package name. Removing it can be a follow-up.Test plan
npxrun against a project with a decoy package,.binentry,package.jsonbin and.npmrc)plugin-installation.md,media-use/references/audio.md,operations.md)— Rames Jusso
🤖 Generated with Claude Code