You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
rtk hook claude omits permissionDecision in updatedInput responses, causing Claude Code to silently ignore command rewrites #3018
Environment
RTK version: 0.42.1 and 0.42.4 (confirmed present in both)
Platform: Windows 11, Git Bash
Claude Code hooks: PreToolUse matcher Bash → rtk hook claude
Summary
When RTK's Claude Code hook rewrites a Bash command, it emits a hookSpecificOutput object containing updatedInput but without the permissionDecision field. Per Claude Code's hook schema, updatedInput is only applied when permissionDecision is explicitly set (e.g. "allow"). Without it, Claude Code silently discards updatedInput and executes the original, unrewritten command — so RTK's token-saving rewrite never actually takes effect, even though the hook itself runs without error.
Steps to reproduce
Configure the Claude Code hook: PreToolUse → matcher Bash → command rtk hook claude.
Simulate the exact payload Claude Code sends on a Bash tool call:
echo '{"session_id":"test","transcript_path":"/tmp/x","cwd":"/some/path","hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"git status","description":"test"}}' | rtk hook claude
Observe the output.
Actual output
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecisionReason":"RTK auto-rewrite","updatedInput":{"command":"rtk git status","description":"test"}}}
Expected output
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"RTK auto-rewrite","updatedInput":{"command":"rtk git status","description":"test"}}}
Impact
Every Bash command routed through the hook runs unmodified, with zero token savings.
rtk gain / rtk gain --history never record real interceptions — the local history.db only ever contains a single stale fallback entry, regardless of how many Bash commands are run or how many times the Claude Code session is restarted.
This effectively makes the "transparent, 0 tokens overhead" rewrite behavior described in RTK's docs non-functional under current Claude Code versions.
Root cause
Per the Claude Code hooks documentation, updatedInput under hookSpecificOutput is only honored when permissionDecision is also present (typical value: "allow"). RTK's hook claude subcommand does not set this field.
Suggested fix
In the hook claude (and likely cursor, gemini, copilot, droid) subcommands, add "permissionDecision": "allow" to the hookSpecificOutput object whenever updatedInput is returned.
rtk's Claude Code hook output omits the required permissionDecision field alongside updatedInput, so Claude Code silently discards the rewritten command and executes the original — nullifying RTK's token-saving rewrite; fix by adding "permissionDecision": "allow" whenever updatedInput is emitted.
This looks like a simple fix that could be auto-resolved. Repo maintainers can use /wshm fix to attempt it.
📁 Relevant files
src/hook/claude.rs
Triaged automatically by wshm · This is an automated analysis, not a human review.
Fresh rtk 0.45.0 retest (Linux x86_64 / WSL2, 2026-08-08): the original
single-command form now includes permissionDecision: "allow", so that part
has changed since the issue was filed.
A residual mixed multiline case still emits updatedInput without a decision:
printf'%s''{"tool_name":"Bash","tool_input":{"command":"git status\ntrue"}}' \
| rtk hook claude
For comparison, a fully rewritable two-line block (git status + git diff --stat) includes permissionDecision: "allow".
I am not asserting that mixed blocks should be auto-allowed. The remaining
question is whether Claude applies updatedInput without a decision on current
supported versions, and the dry-run currently does not expose this distinction.
I filed #3476 as a separate diagnostic request to make hook check report the
actual host decision, rather than overloading this bug thread with a new UX
surface.
When a PreToolUse hook returns updatedInput without a permissionDecision field, according to the documentation:
The tool input is modified with the updatedInput values, but the tool call then proceeds through the normal permission flow (permission rules, auto-mode classifier, or user prompt).
So if it's silently discarded that's because automode classifier or Claude permission rules discarded it. Forcing ask bypass Claude's permission flow, notably the "remember" part that's not possible with permissionDecision "ask"
Do you have situations where it silently dropped a rewritten command that was genuine, not blocked by Claude's configured permission rules nor automode classifier?
We only emit permissionDecision when a definitive decision can be made (for example, when Claude's permissions explicitly allow or deny a command). It isn't rtk's role to unconditionally allow everything; however, you can configure Claude's behavior to achieve that if it fits your needs.
Activity
pszymkowiak commentedon Jul 16, 2026
🔍 Automated Triage
bughighSummary
rtk's Claude Code hook output omits the required permissionDecision field alongside updatedInput, so Claude Code silently discards the rewritten command and executes the original — nullifying RTK's token-saving rewrite; fix by adding "permissionDecision": "allow" whenever updatedInput is emitted.
📁 Relevant files
src/hook/claude.rsTriaged automatically by wshm · This is an automated analysis, not a human review.
pavelbe commentedon Aug 8, 2026
Fresh
rtk 0.45.0retest (Linux x86_64 / WSL2, 2026-08-08): the originalsingle-command form now includes
permissionDecision: "allow", so that parthas changed since the issue was filed.
A residual mixed multiline case still emits
updatedInputwithout a decision:Observed (abridged):
{"updatedInput":{"command":"rtk git status\ntrue"}}For comparison, a fully rewritable two-line block (
git status+git diff --stat) includespermissionDecision: "allow".I am not asserting that mixed blocks should be auto-allowed. The remaining
question is whether Claude applies
updatedInputwithout a decision on currentsupported versions, and the dry-run currently does not expose this distinction.
I filed #3476 as a separate diagnostic request to make
hook checkreport theactual host decision, rather than overloading this bug thread with a new UX
surface.
KuSh commentedon Aug 9, 2026
According to Claude himself
So if it's silently discarded that's because automode classifier or Claude permission rules discarded it. Forcing ask bypass Claude's permission flow, notably the "remember" part that's not possible with permissionDecision "ask"
Do you have situations where it silently dropped a rewritten command that was genuine, not blocked by Claude's configured permission rules nor automode classifier?
KuSh commentedon Sep 5, 2026
I'm closing this as it's working as intended.
We only emit
permissionDecisionwhen a definitive decision can be made (for example, when Claude's permissions explicitly allow or deny a command). It isn't rtk's role to unconditionally allow everything; however, you can configure Claude's behavior to achieve that if it fits your needs.Give Claude Code subagents an actor of their own