feat(hooks): auto-allow Read for skill reference files#81
feat(hooks): auto-allow Read for skill reference files#81
Conversation
Add PreToolUse hook that automatically grants permission for Read tool calls targeting skills/*/references/*.md under each plugin root, eliminating per-file permission prompts when Claude loads skill references. - hooks/allow-skill-references.sh: common hook script with path canonicalization and glob matching against plugin root - plugins/*/hooks/hooks.json: PreToolUse entry (matcher: Read) for 18 plugins that contain skills/*/references/ directories - plugins/*/hooks/allow-skill-references.sh: symlinks to common script Plugins updated: agent-browser, ai-sdk, antfu, claude-md-management, mastra, nuxt, nuxt-ui, pinia, pnpm, prisma, slidev, supabase, unocss, vite, vitepress, vitest, vue, vueuse
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly improves the user experience by automating permission grants for Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a shared hook to auto-allow reading skill reference files, which is a great improvement to reduce repetitive permission prompts. A security audit of the hooks/allow-skill-references.sh script found no security vulnerabilities, noting its robust implementation with multiple layers of defense against file-system-related attacks. However, there are a few suggestions to improve the efficiency and readability of the main hook script, and a discrepancy regarding symlink creation in the plugins' hook directories needs to be addressed.
| input=$(cat) | ||
|
|
||
| tool_name=$(echo "$input" | jq -r '.tool_name // empty') | ||
|
|
||
| if [ "$tool_name" != "Read" ]; then | ||
| exit 0 | ||
| fi | ||
|
|
||
| file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty') |
There was a problem hiding this comment.
The script currently reads the entire standard input into a variable and then invokes jq twice to parse it. This is inefficient due to multiple process forks. You can parse the input and assign variables in a single, more efficient step using eval with jq's @sh formatter. This is a common and safe pattern for this task.
| input=$(cat) | |
| tool_name=$(echo "$input" | jq -r '.tool_name // empty') | |
| if [ "$tool_name" != "Read" ]; then | |
| exit 0 | |
| fi | |
| file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty') | |
| eval "$(cat | jq -r '@sh "tool_name=\(.tool_name // \"\") file_path=\(.tool_input.file_path // \"\")"')" | |
| if [ "$tool_name" != "Read" ]; then | |
| exit 0 | |
| fi |
| @@ -0,0 +1 @@ | |||
| ../../../hooks/allow-skill-references.sh No newline at end of file | |||
There was a problem hiding this comment.
The pull request description mentions creating symlinks, but this file is a regular text file containing a relative path. The hooks.json configuration points directly to the central script at ${CLAUDE_PLUGIN_ROOT}/hooks/allow-skill-references.sh, so this file appears to be unused and may cause confusion. If a symlink was intended, it should be created using ln -s. This comment applies to all 18 similar allow-skill-references.sh files added under plugins/*/hooks/.
| case "$abs_path" in | ||
| "${plugin_root}/skills/"*/references/*.md) | ||
| # Verify no extra path segments between skills/ and references/ | ||
| remainder="${abs_path#${plugin_root}/skills/}" | ||
| skill_name="${remainder%%/*}" | ||
| after_skill="${remainder#${skill_name}/}" | ||
| if [[ "$after_skill" == references/*.md && "$after_skill" != *"/"*"/"* ]]; then | ||
| echo '{"hookSpecificOutput":{"permissionDecision":"allow"}}' | ||
| fi | ||
| ;; | ||
| esac |
There was a problem hiding this comment.
The path matching logic using a case statement and shell parameter expansion is complex and can be hard to follow. Using a single regular expression would make the intent clearer and the code more maintainable by precisely defining the expected path structure.
| case "$abs_path" in | |
| "${plugin_root}/skills/"*/references/*.md) | |
| # Verify no extra path segments between skills/ and references/ | |
| remainder="${abs_path#${plugin_root}/skills/}" | |
| skill_name="${remainder%%/*}" | |
| after_skill="${remainder#${skill_name}/}" | |
| if [[ "$after_skill" == references/*.md && "$after_skill" != *"/"*"/"* ]]; then | |
| echo '{"hookSpecificOutput":{"permissionDecision":"allow"}}' | |
| fi | |
| ;; | |
| esac | |
| if [[ "$abs_path" =~ ^${plugin_root}/skills/[^/]+/references/[^/]+\.md$ ]]; then | |
| echo '{"hookSpecificOutput":{"permissionDecision":"allow"}}' | |
| fi |
Summary
hooks/allow-skill-references.sh: a common PreToolUse hook script that automatically grantsallowpermission when Claude readsskills/*/references/*.mdfiles under a plugin root, eliminating repeated permission prompts during skill reference loadingplugins/*/hooks/hooks.jsonwith aPreToolUseentry (matcher: Read) for 18 plugins that containskills/*/references/directoriesplugins/*/hooks/allow-skill-references.shsymlinks pointing to the common scriptPlugins updated: agent-browser, ai-sdk, antfu, claude-md-management, mastra, nuxt, nuxt-ui, pinia, pnpm, prisma, slidev, supabase, unocss, vite, vitepress, vitest, vue, vueuse
How it works
The hook script:
tool_nameandtool_input.file_pathfrom stdin JSONReadtools${CLAUDE_PLUGIN_ROOT}/skills/<skill>/references/<file>.md{"hookSpecificOutput":{"permissionDecision":"allow"}}on matchTest plan
allowdecisionhooks.jsonfiles passjqvalidity checkSummary by cubic
Auto-approve Read tool calls for skill reference files under each plugin to remove repeated permission prompts when loading skills. Adds a safe, common PreToolUse hook with path canonicalization.
New Features
Migration
Written for commit 14c4c1e. Summary will update on new commits.