Repository navigation
fix: stop the Claude Code hook from approving run_tool calls - #45
Merged
Merged
Conversation
The PreToolUse hook answered "allow" for every Glean run_tool call while ENABLE_HITL was on, to avoid a double prompt. Anthropic's plugin directory now holds any plugin whose hook can decide a permission question for the user, so v3.6.0 is held for review. The hook now only records Claude Code's permission mode, which the server uses to skip its own prompt under --dangerously-skip-permissions. It prints nothing, so Claude Code's normal permission flow always runs. The file is renamed to record-permission-mode.mjs to match what it does. Users see Claude Code's own prompt on run_tool again until they allow the tool permanently. The server's approval prompt still gates writes.
aditya-scio
previously approved these changes
Oct 28, 2026
aditya-scio
left a comment
Contributor
There was a problem hiding this comment.
Thiss makes sense. It's sad the current hook is getting blocked by marketplace submission.
Contributor
|
Thanks for this |
The hook comment said the server's prompt gates every write. It skips tools the user told it to stop asking about, so say that. The directory's check reads the hook file statically, so the test now fails on "allow" or "approve" anywhere in the file, in any case.
aditya-scio
approved these changes
Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR stops our Claude Code
PreToolUsehook from approving Gleanrun_toolcalls. Anthropic's plugin directory holds v3.6.0 for review because of that approval.Why this is needed
The directory holds v3.6.0, and it will hold every later version until the hook changes. Until a version clears review, installs from the directory stay on v3.4.2 and get none of the fixes released since.
v3.6.0 has two holds. This PR removes one of them. The other is described under "Not in this PR".
Why the hook approved calls
The local MCP server shows its own approval prompt before a
run_toolcall that needs approval (ENABLE_HITL). It skips the prompt for tools it knows are read-only, and for tools whose saved approval says not to ask, such as tools the user set to Always Allow. Claude Code also showed its own "allow this tool?" prompt for the same call. To avoid that double prompt, the hook answered"allow"for every Gleanrun_toolcall, and the server's prompt was the only one the user saw.The hook also did a second job. Before each call, it wrote Claude Code's permission mode to a per-session marker file. The server reads that marker so it can skip its own prompt when the user started Claude Code with
--dangerously-skip-permissions.Why the directory holds it
The directory's check is
HOOK_GRANTS_PERMISSION. Its rule says a hook may deny a call or leave the decision to Claude Code's normal permission flow, but it may not approve a call or change the call's input. A hook that answers"allow"decides for the user whether they are asked at all.The check reads the hook file statically. It reports a decision string even in code it can't prove runs.
The same hook shipped in v3.4.2, and the directory approved that version. The current check holds it, so the hook has to change before any new version can publish.
What this PR changes
--dangerously-skip-permissionsstill skips the server's prompt. It prints nothing, so Claude Code makes the permission decision.auto-approve-run-tool.mjstorecord-permission-mode.mjs, because the old name described the behavior this PR removes.hooks.jsonpoints to the new name.permissionDecision, "allow" or "approve" appears anywhere in the hook source, comments included, in any case. This mirrors the directory's static check.run-tool.tsandpolicy/key.tsno longer say the hook approves calls.Options considered
"ask""ask"on every call, so Claude Code would prompt every time, in every permission mode except bypass.--dangerously-skip-permissionswould get the server's prompt again.What users will notice
Results from Claude Code 2.1.312:
run_toolbeforerun_toolwith/permissions.--dangerously-skip-permissionsThe server's own approval prompt doesn't change in any mode. No call skips a check that it got before this PR. The only change is that Claude Code makes its own permission decision again.
In default mode, a write that needs approval now gets Claude Code's prompt as well as the server's, so users see one more prompt than before.
Later work moves the approval prompt from the local server to the remote server. Then the marker has no job left, and the hook can be deleted.
Not in this PR
The second directory hold is
BINARIES_NOT_INSPECTED. The check can't fully inspectmcp/dist/index.js, which is 1.63 MB, compared with 983 KB in the approved v3.4.2. A follow-up PR reduces the bundle size. Until then, a reviewer must clear that hold by hand.Testing
npm run test:bundle: 436 tests pass.npm run typecheck:bundle: clean.npm test(build pluspluginpack validatefor Claude Code, Cursor and Codex): passes.dist/claude/plugins/glean/hooks/holds onlycapture-inventory.mjs,hooks.jsonandrecord-permission-mode.mjs, and none of them contains a decision string.run_toolcall, printed nothing, exited 0 and wrote the marker.CLAUDE_CONFIG_DIR) with only this build loaded:claude -p, Claude Code 2.1.284), with the same build and the hook frommainswapped in as a baseline. With the old hook,run_toolran with no permission check. With the new hook, Claude Code required permission, and-preported a permission denial. With--allowedToolsor a saved allow rule, the call ran. With--dangerously-skip-permissions, it ran and the hook recordedbypassPermissions.