-
Notifications
You must be signed in to change notification settings - Fork 629
Description
Context
Using rtk v0.31.0 with the official Claude Code PreToolUse hook (rtk rewrite).
The hook is correctly rewriting commands — rtk gain confirms 567 commands processed with 51.8K tokens saved (54.5%).
Problem 1
rtk discover scans Claude Code session history and matches against original command text, not the actually-executed commands. When the PreToolUse hook rewrites find ... → rtk find ..., the session log still records the original find command.
Result: discover reports these already-rewritten commands as "missed savings":
Scanned: 125 sessions (last 30 days), 1841 Bash commands
Already using RTK: 6 commands (0%)
MISSED SAVINGS:
find 471 rtk find ~137.0K tokens
git add 181 rtk git ~33.2K tokens
grep -r 169 rtk grep ~19.4K tokens
ls -la 189 rtk ls ~4.4K tokens
composer 8 rtk composer ~4.1K tokens
cat 38 rtk read ~2.8K tokens
tree 9 rtk tree ~1.4K tokens
Total: 1066 commands -> ~202.4K tokens saveable
Most of these 1066 "missed" commands were actually handled by the hook. The 6 "already using RTK" only counts commands where the LLM explicitly wrote rtk ... in the Bash call.
I confirmed that rtk rewrite does handle all the "missed" commands correctly:
cat /tmp/file.txt → rtk read /tmp/file.txt ✅
composer update → rtk composer update ✅
tree -L 2 → rtk tree -L 2 ✅
git status → rtk git status ✅
git log --oneline -5 → rtk git log --oneline -5 ✅
git diff → rtk git diff ✅
find ... -name *.php → rtk find ... ✅
grep -r 'pattern' src → rtk grep ... ✅
ls -la → rtk ls -la ✅
Expected behavior
discover should account for hook-based rewrites. Possible approaches:
- Cross-reference with
rtk gaindata (which logs all actually-processed commands) - Detect that the hook is configured (check
~/.claude/settings.jsonforrtk-rewritein PreToolUse hooks) and adjust the report - Show a separate "likely handled by hook" category instead of "missed"
Problem 2: high-volume commands not handled by rtk rewrite
These commands fail rtk rewrite (exit 1) but could be mapped to existing generic handlers:
| Command | Count | Existing handler | Notes |
|---|---|---|---|
php vendor/bin/pest ... |
276 | rtk test |
Test runner — verbose output with stack traces |
./vendor/bin/pest ... |
14 | rtk test |
Direct invocation |
vendor/bin/phpstan analyse ... |
12 | rtk err |
Static analysis — can output hundreds of lines |
composer show ... |
3 | rtk composer |
composer update works, but not show |
Local workaround
Until native support is added, I worked around this with a second PreToolUse hook (local-rewrite.sh) placed before rtk-rewrite.sh in the Claude Code
hook chain. It doesn't modify rtk-rewrite.sh (no integrity conflict):
#!/usr/bin/env bash
# local-rewrite.sh — maps unhandled commands to generic rtk handlers
# Runs BEFORE rtk-rewrite.sh in the PreToolUse hook chain.
command -v jq &>/dev/null || exit 0
INPUT=$(cat)
CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
[ -z "$CMD" ] && exit 0
case "$CMD" in
"php vendor/bin/pest "*) REWRITTEN="rtk test $CMD" ;;
"./vendor/bin/pest "*) REWRITTEN="rtk test $CMD" ;;
"vendor/bin/pest "*) REWRITTEN="rtk test $CMD" ;;
"vendor/bin/phpstan analyse"*) REWRITTEN="rtk err $CMD" ;;
"./vendor/bin/phpstan analyse"*) REWRITTEN="rtk err $CMD" ;;
"composer show"*) REWRITTEN="rtk composer ${CMD#composer }" ;;
*) exit 0 ;;
esac
ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input')
UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd')
jq -n --argjson updated "$UPDATED_INPUT" '{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"permissionDecisionReason": "Local rtk rewrite",
"updatedInput": $updated
}
}' settings.json config (local hook before rtk hook):
"PreToolUse": [
{ "hooks": [{ "command": "~/.claude/hooks/local-rewrite.sh", "type": "command" }], "matcher": "Bash" },
{ "hooks": [{ "command": "~/.claude/hooks/rtk-rewrite.sh", "type": "command" }], "matcher": "Bash" }
] Ideally, rtk rewrite could handle these mappings natively (pest/phpstan → rtk test/rtk err) so this workaround wouldn't be needed.
Environment
- rtk 0.31.0
- Claude Code with PreToolUse hook via
rtk rewrite - Linux (Ubuntu)