Skip to content

Add hooks support for Windows #330

Closed

Description

@bruisedsamurai

Currently hooks don’t work on Windows and that’s the biggest feature otherwise LLMs keeps forgetting to use rtk

Activity

  1. melipefello commented on Mar 5, 2026

    @melipefello

    Hey @bruisedsamurai
    I've made my own today, it works relatively well.

    I still have to fix failed calls to cd and similar since they don't pass through well to rtk, but other than that this should work fairly well.

    #!/bin/bash
    # PreToolUse hook: rewrite Bash commands to prepend rtk prefix
    # Uses updatedInput to transparently rewrite commands (like RTK's --hook-only mode)
    
    INPUT=$(cat)
    
    # Extract command from JSON input
    COMMAND=$(echo "$INPUT" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/"command"[[:space:]]*:[[:space:]]*"//;s/"$//')
    
    if [ -z "$COMMAND" ]; then
      exit 0
    fi
    
    # Check if ALL segments already have rtk prefix
    ALL_PREFIXED=true
    IFS='&&' read -ra SEGMENTS <<< "$COMMAND"
    for segment in "${SEGMENTS[@]}"; do
      trimmed=$(echo "$segment" | sed 's/^[[:space:]]*//')
      [ -z "$trimmed" ] && continue
      if [[ ! "$trimmed" =~ ^rtk[[:space:]] ]]; then
        ALL_PREFIXED=false
        break
      fi
    done
    
    # If already fully prefixed, allow as-is
    if [ "$ALL_PREFIXED" = true ]; then
      exit 0
    fi
    
    # Rewrite: prepend rtk to each segment that doesn't have it
    REWRITTEN=""
    FIRST=true
    for segment in "${SEGMENTS[@]}"; do
      trimmed=$(echo "$segment" | sed 's/^[[:space:]]*//')
      [ -z "$trimmed" ] && continue
    
      if [ "$FIRST" = true ]; then
        FIRST=false
      else
        REWRITTEN="$REWRITTEN && "
      fi
    
      if [[ "$trimmed" =~ ^rtk[[:space:]] ]]; then
        REWRITTEN="$REWRITTEN$trimmed"
      else
        REWRITTEN="${REWRITTEN}rtk $trimmed"
      fi
    done
    
    # Output JSON to rewrite the command
    cat <<EOF
    {
      "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "allow",
        "updatedInput": {
          "command": "$REWRITTEN"
        }
      }
    }
    EOF
    
    
  2. bruisedsamurai commented on Mar 5, 2026

    @bruisedsamurai
    Author

    @melipefello this is still bash right?

  3. melipefello commented on Mar 5, 2026

    @melipefello

    I'll assume if you're using claude you have bash running, on your git install there's ...\Git\bin\bash.exe.

    If you add it to your env variables you should be able to use it. If you're using claude you might need to setup the CLAUDE_CODE_GIT_BASH_PATH in case you've moved your install folder.

  4. iamseanmillare commented on Mar 6, 2026

    @iamseanmillare

    Hoping we could get a solution to this. Mine is reading the rtk-hook script as mac/unix

  5. cderv commented on Mar 13, 2026

    @cderv

    The hook script (rtk-rewrite.sh) actually works on Windows when invoked through Git Bash, which is what Claude Code uses as its shell on Windows.

    Tested on Windows 11 with rtk 0.29.0, jq 1.8.1, and GNU bash 5.2.37 (Git for Windows):

    $ echo '{"tool_name":"Bash","tool_input":{"command":"git status"}}' | bash ~/.claude/hooks/rtk-rewrite.sh
    {
      "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "allow",
        "permissionDecisionReason": "RTK auto-rewrite",
        "updatedInput": {
          "command": "rtk git status"
        }
      }
    }
    

    Commands rtk doesn't handle pass through silently (exit 0, no output), and already-prefixed commands are left alone.

    The blocker is the #[cfg(not(unix))] guard in src/init.rs — rtk init refuses to install the hook on non-Unix. The only Unix-specific thing is chmod +x via std::os::unix::fs::PermissionsExt, which isn't needed on Windows since scripts are invoked by interpreter (bash script.sh), not by execute permission.

    As a workaround, copying the hook manually and configuring Claude Code's settings.json works:

    1. Copy the hook script:

      mkdir -p ~/.claude/hooks
      cp <rtk-repo>/hooks/rtk-rewrite.sh ~/.claude/hooks/rtk-rewrite.sh
      
    2. Add to ~/.claude/settings.json:

      "hooks": {
        "PreToolUse": [
          {
            "matcher": "Bash",
            "hooks": [
              {
                "type": "command",
                "command": "bash ~/.claude/hooks/rtk-rewrite.sh"
              }
            ]
          }
        ]
      }

    The key detail is using bash ~/.claude/hooks/rtk-rewrite.sh (explicit bash invocation) rather than just the script path.

    I'll test this in a real Claude Code session and report back. Happy to help test a proper fix too if someone lifts the #[cfg(not(unix))] guard with a Windows path that skips the chmod step.

  6. cderv commented on Mar 13, 2026

    @cderv

    Tested in a real Claude Code session and it works — the hook transparently rewrote git status to rtk git status and the output came back in rtk's compact format. No errors, no warnings.

    I also tried rtk init --global on Windows to see what happens. It prints a warning about hooks requiring Unix, then falls back to --claude-md mode which appends ~130 lines of rtk instructions directly into ~/.claude/CLAUDE.md. That's pretty invasive for users who maintain a curated CLAUDE.md — the hook approach is much cleaner since it's transparent and doesn't touch any config files beyond settings.json.

    So the hook script is already cross-platform, and it's arguably the better approach on all platforms. The only thing preventing Windows users from getting it through rtk init is that ensure_hook_installed in src/init.rs gates on #[cfg(unix)] for the chmod +x call. On Windows that step could just be skipped since scripts run by interpreter, not execute permission.

  7. MagicXran commented on Mar 15, 2026

    @MagicXran

    back

    that's great ~

  8. bruisedsamurai commented on Mar 15, 2026

    @bruisedsamurai
    Author

    Actually I was trying to use it with Copilot CLI.

  9. pszymkowiak commented on Mar 20, 2026

    @pszymkowiak
    Collaborator

    wshm · Automated triage by AI

    🔍 Automated Triage

    ✨ Category feature
    🟠 Priority high
    🎯 Confidence 78%

    Summary

    Request for Windows hooks support; closely related to #1993 (hooks not firing on Windows in OpenCode) but broader in scope — recommend linking both issues rather than closing as duplicate


    Triaged automatically by wshm · This is an automated analysis, not a human review.

  10. added a commit that references this issue on Mar 29, 2026
    7308610
  11. 20 remaining items

  12. sguryev commented on Apr 29, 2026

    @sguryev

    @iamseanmillare there is the required missing tool ripgrep. There area a bunch of installation options including the winget I have chosen

  13. vinozganic commented on May 11, 2026

    @vinozganic

    Follow-up gotcha on Windows on top of this setup: works fine for single-line commands but quietly corrupts multiline ones, like the HEREDOC git commit -m "$(cat <<EOF ...)" pattern Claude uses for commit bodies. jq on Git Bash opens stdout in text mode by default, so JSON \n escapes come out as CRLF, and the CR rides through rtk rewrite back into the rewritten command and kills the HEREDOC terminator.

    Repro: echo '{"x":"a\nb"}' | jq -r '.x' | xxd prints 0d 0a where it should print 0a.

    Fix is adding -b (binary mode) to all three jq calls: jq -rb on the input read, jq -cb on the two output builders. No-op on Unix so no need to gate it. Needs jq 1.7+, winget gives you 1.8 anyway.

  14. sguryev commented on Jun 10, 2026

    @sguryev

    Release says windows fixed: https://github.com/rtk-ai/rtk/releases/tag/v0.37.2
    But readme says opposite one: https://github.com/rtk-ai/rtk#windows

    Claude Code runs commands in Git Bash. RTK is available there

    Image

    I'm thinking about removing RTK anchor from the CLAUDE.md file to save context space.

  15. gentledepp commented on Jun 28, 2026

    @gentledepp

    So this is still not fixed? :-|

    I am waiting to use RTK, but I am - sadly - a Windows user :-D
    Thank you for all your efforts!

  16. MrBill700 commented on Jul 7, 2026

    @MrBill700

    Confirming the binary hook works on native Windows: Windows 11 + Claude Code + rtk v0.43.0.

    Setup that worked:

    • rtk.exe from the release page, on the user PATH
    • rtk init -g --auto-patch -- installs the rtk hook claude PreToolUse entry in ~/.claude/settings.json and the slim ~/.claude/RTK.md (no more full CLAUDE.md injection)
    • rtk init -g --show reports [ok] for Hook, RTK.md, and settings.json

    Verified behavior (Claude Code executes hooks via Git Bash on Windows):

    • Plain commands are rewritten transparently: ls -> rtk ls, git status -> rtk git status
    • Non-rewritable commands pass through untouched
    • Multiline heredoc commands (the git commit -m "$(cat <<EOF ...)" pattern discussed above) pass through intact -- no CRLF corruption with the binary hook, unlike the old jq shell pipeline

    Adoption data point, since this issue is about LLMs forgetting to use rtk: with instructions-only (a CLAUDE.md block telling the model to prefix rtk), we measured ~29 rtk commands in a month (~2% compliance). Three days after installing the binary hook: 322 commands, 161.9K tokens saved (58%). The hook is the difference between rtk existing and rtk working.

    One small ask: the README still says hooks require Unix (https://github.com/rtk-ai/rtk#windows), which contradicts the v0.37.2 release notes and nearly stopped us from trying. Updating that section would help other Windows users find this.

  17. sguryev commented on Jul 7, 2026

    @sguryev

    Some issues for claude.md injection:

    1. @RTK.md ref gives nothing (AFAIU) because claude still reads it full so no lazy loading or similar
    2. RTK.md file has line Refer to CLAUDE.md for full command reference. which is not correct because it's a kind of circular ref.
    3. We have the PreToolUse hook now so I don't think md file is needed.

    So I have removed the @RTK.md ref from the claude.md file for now manually and don't see any problems.

    Here is the gain after couple of weeks without the claude.md injection.
    Image

    Please let me know your thoughts.

  18. pszymkowiak commented on Jul 7, 2026

    @pszymkowiak
    Collaborator

    Windows hooks have been supported natively since v0.37.2 (2026-04-20) via a native binary hook (rtk hook claude) — no Unix shell, bash, or jq required. Commands are rewritten transparently on Command Prompt, PowerShell, and Windows Terminal, just like on Linux/macOS.

    The README's Windows section was still describing the old pre-v0.37.2 "CLAUDE.md fallback" behavior, which caused confusion (see the thread below). Fixed in #2791 (merged).

    On Windows:

    • Fresh install → rtk init -g sets up the native binary hook.
    • Upgrading from before v0.37.2 → re-run rtk init -g to migrate off the legacy rtk-rewrite.sh shell hook.

    Closing as resolved — please re-open if the native hook doesn't rewrite commands on a fresh rtk init -g.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions