Repository navigation
fix(plugin): let the Claude directory see the pre-PR hook program - #1105
Conversation
The Claude directory treats the nested plugin-root fallback as a computed program and blocks the listing. Grok Build and Codex both set CLAUDE_PLUGIN_ROOT, and Codex keeps only the command string, so one quoted path works on all three. Co-authored-by: Zach Dunn <zachdunn@users.noreply.github.com>
🦋 Changeset detectedLatest commit: b27cfb2 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (2)
🚫 Excluded labels (none allowed) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Move the catalog pin to 95ef759db58e9d4e416143a193eab3656f1873cb, the merge of buildinternet/uploads#1105. The plugin version stays 0.4.0 and the indexed components are unchanged. Co-authored-by: Zach Dunn <zachdunn@users.noreply.github.com>
The Claude plugin directory blocked the uploads plugin because the pre-PR hook computed its script path. The command was a nested fallback across
GROK_PLUGIN_ROOT,PLUGIN_ROOT, andCLAUDE_PLUGIN_ROOT, so the scanner could not see a real program and reported an unpinned launcher (UNPINNED_NPX). The hook now names the script with${CLAUDE_PLUGIN_ROOT}only. Claude Code, Grok Build, and Codex all set that variable, so the same command still runs on each of them.What it does / what it is not
"${CLAUDE_PLUGIN_ROOT}"/hooks/pre-pr-screenshot.sh. That path is the program. The only variable is${CLAUDE_PLUGIN_ROOT}.GROK_PLUGIN_ROOTand the aliasCLAUDE_PLUGIN_ROOTto the installed plugin directory. Codex setsPLUGIN_ROOTand the same alias. Both expand${CLAUDE_PLUGIN_ROOT}in the command string.commandstring and drops anargsarray. Restoring the pre-plugin: wrap .mcp.json in mcpServers and document Grok Build install #1100commandplusargsform would run bareshon Codex. The path stays insidecommandso Codex keeps it.GROK_PLUGIN_ROOTor onlyPLUGIN_ROOT, and not the Claude alias, will not find the script. Current Grok and Codex plugin hooks set the alias.$.process.runstarts, why it runs, and what that call sends and where.plugin.jsonfield was removed. See the candidates below.How to try it
After this lands on
main, re-validateplugins/claude/uploadsin the Claude directory portal. The PreToolUse finding should clear. Localclaude plugin validatechecks schema only. It does not run the directory policy scan.Installed Claude Code users pick up the hook when the plugin version bumps:
The xAI catalog entry (xai-org/plugin-marketplace#1310) is pinned to
a6f424c2, the #1100 merge. The Claude directory followsmainand does not use that pin, so a re-pin is not required for this directory check. A re-pin is required for Grok Build installs from that catalog to run this command. Re-pinning is safe: Grok setsCLAUDE_PLUGIN_ROOT. Until the pin moves, catalog installs keep the nested command, which still runs on Grok.Technical notes
The directory checklist blocks a hook command, when the plugin folder is a subfolder of the repository, that uses any variable other than
${CLAUDE_PLUGIN_ROOT}, a command substitution, a wildcard, or an inline program. The nested${GROK_PLUGIN_ROOT:-${PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}form is that case. The scanner titled it "Unpinned npx launcher" and asked to spell the program by name (node server.jsor${CLAUDE_PLUGIN_ROOT}/bin/x). Git history shows the pre-#1100 exec form (shplus anargsentry of${CLAUDE_PLUGIN_ROOT}/hooks/pre-pr-screenshot.sh) passed. Codex ignoresargs(HookHandlerConfigincodex-rs/config/src/hook_config.rs). Grok substitutes plain${CLAUDE_PLUGIN_ROOT}and leaves${VAR:-default}for the shell. The command string now matches Claude's documented shell form.Unrecognized
plugin.jsonfields, as candidates only. Claude Code 2.1.295claude plugin validate --strictaccepts every key in.claude-plugin/plugin.json, and the current manifest reference lists them. The docs say Claude Code before 2.1.281 warns on the five directory-listing fieldsicon,documentationUrl,supportUrl,privacyPolicyUrl, andtermsOfServiceUrl. This manifest sets the four URL fields and does not seticon. If the directory scanner is on that older set, the fifth warning is likelytypes, the mod declaration. Those five are the candidates. They stay.Test plan
claude plugin validate --strict plugins/claude/uploadson Claude Code 2.1.295claude plugin test plugins/claude/uploads— 36 pass inhooks/register.test.tspnpm plugin-version:checkandpnpm plugin-skills:checkCLAUDE_PLUGIN_ROOTset, the command runsuploads hook pre-pr-screenshot; the same after inline substitution of that variable; exit 0 whenuploadsis missing; exit 127 when onlyGROK_PLUGIN_ROOTis set