Skip to content

fix(plugin): let the Claude directory see the pre-PR hook program - #1105

Merged
Zach Dunn (zachdunn) merged 1 commit into
mainfrom
cursor/fix-plugin-hook-command-2493
Oct 9, 2026
Merged

Zach Dunn (zachdunn) merged 1 commit into
mainfrom
cursor/fix-plugin-hook-command-2493

Conversation

@zachdunn

Copy link
Copy Markdown
Member

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, and CLAUDE_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

  • The PreToolUse command is "${CLAUDE_PLUGIN_ROOT}"/hooks/pre-pr-screenshot.sh. That path is the program. The only variable is ${CLAUDE_PLUGIN_ROOT}.
  • Grok Build sets GROK_PLUGIN_ROOT and the alias CLAUDE_PLUGIN_ROOT to the installed plugin directory. Codex sets PLUGIN_ROOT and the same alias. Both expand ${CLAUDE_PLUGIN_ROOT} in the command string.
  • Codex's hook schema is a single command string and drops an args array. Restoring the pre-plugin: wrap .mcp.json in mcpServers and document Grok Build install #1100 command plus args form would run bare sh on Codex. The path stays inside command so Codex keeps it.
  • A shell that has only GROK_PLUGIN_ROOT or only PLUGIN_ROOT, and not the Claude alias, will not find the script. Current Grok and Codex plugin hooks set the alias.
  • The staged-media mod is unchanged. The plugin README now lists every program $.process.run starts, why it runs, and what that call sends and where.
  • The "Uses a credential from the user's machine" warnings are unchanged. The report does not name the two sites, and the plugin source does not read an environment credential by name.
  • No plugin.json field was removed. See the candidates below.

How to try it

After this lands on main, re-validate plugins/claude/uploads in the Claude directory portal. The PreToolUse finding should clear. Local claude plugin validate checks schema only. It does not run the directory policy scan.

Installed Claude Code users pick up the hook when the plugin version bumps:

/plugin marketplace update uploads
/plugin update uploads@uploads

The xAI catalog entry (xai-org/plugin-marketplace#1310) is pinned to a6f424c2, the #1100 merge. The Claude directory follows main and 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 sets CLAUDE_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.js or ${CLAUDE_PLUGIN_ROOT}/bin/x). Git history shows the pre-#1100 exec form (sh plus an args entry of ${CLAUDE_PLUGIN_ROOT}/hooks/pre-pr-screenshot.sh) passed. Codex ignores args (HookHandlerConfig in codex-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.json fields, as candidates only. Claude Code 2.1.295 claude plugin validate --strict accepts 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 fields icon, documentationUrl, supportUrl, privacyPolicyUrl, and termsOfServiceUrl. This manifest sets the four URL fields and does not set icon. If the directory scanner is on that older set, the fifth warning is likely types, the mod declaration. Those five are the candidates. They stay.

Test plan

  • claude plugin validate --strict plugins/claude/uploads on Claude Code 2.1.295
  • claude plugin test plugins/claude/uploads — 36 pass in hooks/register.test.ts
  • pnpm plugin-version:check and pnpm plugin-skills:check
  • Smoke test: with CLAUDE_PLUGIN_ROOT set, the command runs uploads hook pre-pr-screenshot; the same after inline substitution of that variable; exit 0 when uploads is missing; exit 127 when only GROK_PLUGIN_ROOT is set
  • Re-validate in the Claude directory portal
Open in Web Open in Cursor 

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-bot

changeset-bot Bot commented Oct 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b27cfb2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@uploads/plugin Patch

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

@coderabbitai

coderabbitai Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (2)
  • coderabbit:review
  • review
🚫 Excluded labels (none allowed) (1)
  • wip

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 87328869-1ce1-4123-b08d-105cc81df15b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@zachdunn
Zach Dunn (zachdunn) marked this pull request as ready for review October 9, 2026 00:21
@zachdunn
Zach Dunn (zachdunn) merged commit 95ef759 into main Oct 9, 2026
3 checks passed
@zachdunn
Zach Dunn (zachdunn) deleted the cursor/fix-plugin-hook-command-2493 branch October 9, 2026 00:24
cursor Bot pushed a commit to buildinternet/plugin-marketplace that referenced this pull request Oct 9, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants