Skip to content

fix(hook): cursor hook fails to rewrite commands due to incorrect exit code handling#1075

Open
sebastiancichos wants to merge 1 commit intortk-ai:developfrom
sebastiancichos:fix/cursor-hook-exit-code
Open

fix(hook): cursor hook fails to rewrite commands due to incorrect exit code handling#1075
sebastiancichos wants to merge 1 commit intortk-ai:developfrom
sebastiancichos:fix/cursor-hook-exit-code

Conversation

@sebastiancichos
Copy link
Copy Markdown

Summary

The Cursor agent hook (~/.cursor/hooks/rtk-rewrite.sh) fails to rewrite shell commands because it incorrectly handles the exit code from rtk rewrite. The hook treats exit code 3 (which indicates a successful rewrite) as a failure condition.

Bug Description

Current Behavior (Broken)

All shell commands pass through unchanged - RTK never rewrites them.

Expected Behavior

Shell commands like git status, ls, cat, etc. should be automatically rewritten to their RTK equivalents.

Root Cause

In hooks/cursor/rtk-rewrite.sh (line 43):

# Delegate all rewrite logic to the Rust binary.
# rtk rewrite exits 1 when there's no rewrite — hook passes through silently.
REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null) || { echo '{}'; exit 0; }

The problem: The comment says "exits 1 when there's no rewrite", but rtk rewrite actually returns exit code 3 when it successfully rewrites a command.

The || operator treats ANY non-zero exit code as failure, so:

  • Exit 0 (no rewrite needed) → OK, hook continues
  • Exit 3 (successfully rewritten) → TREATED AS FAILURE, hook exits with {}
  • Exit 1 (actual error) → TREATED AS FAILURE, hook exits with {}

Result: Commands are never rewritten because the hook always exits early.

Evidence

Test showing rtk rewrite exit codes:

# Command that should be rewritten
$ rtk rewrite "git status"
rtk git status
$ echo $?  
3  # ← This is "success", not failure!

# Command with no rewrite needed  
$ rtk rewrite "unknown-command"
unknown-command
$ echo $?
0

Hook behavior with current code:

$ echo '{"tool_input": {"command": "git status"}}' | ~/.cursor/hooks/rtk-rewrite.sh
{}  # ← Always returns empty object, never rewrites

Fix

Replace the incorrect exit code handling:

Before:

REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null) || { echo '{}'; exit 0; }

After:

# rtk rewrite returns exit 3 on successful rewrite, 0 when no rewrite needed.
REWRITTEN=$(rtk rewrite "$CMD" 2>/dev/null)
RTK_EXIT=$?

# Exit 0 = no rewrite needed, exit 3 = successfully rewritten
# Any other exit code indicates an actual error
if [ "$RTK_EXIT" -ne 0 ] && [ "$RTK_EXIT" -ne 3 ]; then
  echo '{}'
  exit 0
fi

Testing

After applying the fix:

$ echo '{"tool_input": {"command": "git status"}}' | ~/.cursor/hooks/rtk-rewrite.sh
{
  "permission": "allow",
  "updated_input": {
    "command": "rtk git status"
  }
}

Hook now correctly rewrites commands and RTK tracking works:

$ rtk gain
RTK Token Savings (Global Scope)
════════════════════════════════════════════════════════════

Total commands:    1
Input tokens:      77
Output tokens:     76
Tokens saved:      1 (1.3%)

Impact

Without this fix:

  • Cursor users get 0% token savings from the auto-rewrite feature
  • Hook appears installed but does nothing
  • Users must manually prefix commands with rtk

With this fix:

  • 60-90% token savings on shell commands as advertised
  • Transparent command rewriting works as designed
  • Full RTK adoption for Cursor users

Checklist

  • Fix implemented in hooks/cursor/rtk-rewrite.sh
  • Tested locally with rtk rewrite commands
  • Verified hook output format matches Cursor requirements

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 7, 2026

CLA assistant check
All committers have signed the CLA.

@sebastiancichos sebastiancichos changed the base branch from master to develop April 7, 2026 14:58
@sebastiancichos sebastiancichos changed the title Fix: Cursor hook fails to rewrite commands due to incorrect exit code handling fix(hook): Cursor hook fails to rewrite commands due to incorrect exit code handling Apr 7, 2026
@sebastiancichos sebastiancichos changed the title fix(hook): Cursor hook fails to rewrite commands due to incorrect exit code handling fix(hook): cursor hook fails to rewrite commands due to incorrect exit code handling Apr 7, 2026
The Cursor agent hook failed to rewrite shell commands because it
treated exit code 3 from `rtk rewrite` as a failure condition.

Exit code 3 actually indicates a successful rewrite, but the `||`
operator treated ANY non-zero exit as failure, causing the hook
to always exit early with an empty JSON response.

Changes:
- Capture exit code explicitly instead of using `||`
- Accept both exit 0 (no rewrite) and exit 3 (rewritten) as success
- Only treat other exit codes as actual errors

Before: Commands were never rewritten, 0% token savings
After: Transparent command rewriting works as designed, 60-90% savings
@sebastiancichos sebastiancichos force-pushed the fix/cursor-hook-exit-code branch from a4fea51 to 3aa08b2 Compare April 7, 2026 22:05
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