Skip to content

feat(hook): native Claude Code hook for Windows (no bash/jq required)#954

Closed
Warrio111 wants to merge 4 commits intortk-ai:developfrom
Warrio111:feat/windows-native-hook-rewrite
Closed

feat(hook): native Claude Code hook for Windows (no bash/jq required)#954
Warrio111 wants to merge 4 commits intortk-ai:developfrom
Warrio111:feat/windows-native-hook-rewrite

Conversation

@Warrio111
Copy link
Copy Markdown

@Warrio111 Warrio111 commented Mar 31, 2026

Problem

On Windows, `rtk init -g` prints a warning and silently falls back to `--claude-md` mode because the Claude Code hook was implemented as a bash script (`rtk-rewrite.sh`) requiring `bash` + `jq` — neither available natively on Windows.

```
[warn] Hook-based mode requires Unix (macOS/Linux).
Windows: use --claude-md mode for full injection.
Falling back to --claude-md mode.
```

This means Windows users get no automatic command rewriting in Claude Code sessions.

Solution

Add `rtk hook claude` — a native Rust subcommand that reads Claude Code's `PreToolUse` JSON from stdin, checks permission rules, and rewrites commands with zero external dependencies.

On Windows, `rtk init -g` now installs `"<rtk.exe>" hook claude` directly in `settings.json` instead of falling back.

Changes

File Change
`src/hooks/hook_cmd.rs` `run_claude()` — standalone implementation (not a delegate to `run_copilot()`); respects deny/ask rules; only handles Claude Code's snake_case format; `build_claude_response()` helper for testability
`src/hooks/hook_check.rs` `native_hook_in_settings()` — detects native hook in `settings.json` so `status()` returns `Ok` on Windows instead of spurious "No hook installed" warning
`src/hooks/init.rs` `native_hook_command()`, `patch_settings_native()`, Windows `run_default_mode` installs native hook; `hook_already_present` detects any RTK hook variant (bash or native) to prevent double-install
`src/main.rs` `HookCommands::Claude` subcommand routing

Permission protocol

`run_claude()` mirrors the exit-code contract of `rewrite_cmd.rs`:

Verdict Behavior
Deny Silent passthrough — Claude Code enforces its own deny rules
Ask Emit `updatedInput` but omit `permissionDecision` — Claude Code prompts user
Allow / Default Emit `updatedInput` with `permissionDecision: "allow"`

Before / After

Before (Windows):
```
$ rtk init -g
[warn] Hook-based mode requires Unix (macOS/Linux).
Falling back to --claude-md mode.
```

After (Windows):
```
$ rtk init -g
RTK hook installed (Windows native).

Hook: "C:\Users...\rtk.exe" hook claude
RTK.md: C:\Users....claude\RTK.md (10 lines)
CLAUDE.md: @RTK.md reference added
settings.json: hook added
```

Relation to PR #150

PR #150 proposes a similar fix with a full standalone reimplementation (~1126 lines). This PR reuses existing infrastructure (`permissions.rs`, `registry`, `init.rs`) and adds ~350 lines of changes with no new dependencies.

Test plan

  • `cargo test --all` — 1367 tests, 0 failures
  • `rtk hook claude` subcommand routes correctly
  • deny/ask/allow/default verdicts tested via `build_claude_response()`
  • Copilot CLI camelCase format rejected (no cross-format leak)
  • `hook_already_present` detects bash hook when installing native (no double-install)
  • `native_hook_in_settings()` tested with real tempdir JSON fixtures
  • `test_status_returns_valid_variant` updated to include native hook detection
  • CLA signed, rebased on latest `develop` (commit `a919335`)

Copilot AI review requested due to automatic review settings March 31, 2026 18:59
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Windows-native Claude Code hook entrypoint so rtk init -g can install a hook without relying on bash/jq, enabling automatic command rewriting in Claude Code on Windows.

Changes:

  • Add rtk hook claude subcommand routing (native hook processor).
  • Update Windows rtk init -g default path to install a native hook command into ~/.claude/settings.json.
  • Extend hook detection/removal logic to recognize "hook claude" entries.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.

File Description
src/main.rs Adds hook claude subcommand to the CLI router and documents intended settings.json usage.
src/hooks/init.rs Implements Windows-native hook install flow (native_hook_command, patch_settings_native) and recognizes/removes hook claude entries.
src/hooks/hook_cmd.rs Adds run_claude() wrapper that reuses existing Copilot/Claude-compatible hook JSON handling.

Comment thread src/hooks/init.rs
Comment on lines +918 to +924
println!("\n MANUAL STEP: Add this to ~/.claude/settings.json:");
println!(" {{");
println!(" \"hooks\": {{ \"PreToolUse\": [{{");
println!(" \"matcher\": \"Bash\",");
println!(" \"hooks\": [{{ \"type\": \"command\",");
println!(" \"command\": \"{}\"", hook_command);
println!(" }}]");
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In PatchMode::Skip, the manual settings.json snippet prints the hook_command inside JSON quotes, but hook_command itself contains embedded double-quotes ("") so the resulting example line is invalid JSON (unescaped quotes). Consider JSON-escaping the command when printing (e.g., serialize hook_command as a JSON string) or avoid embedding quotes in the displayed snippet.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread src/hooks/init.rs
Comment on lines +976 to +981
let claude_dir = resolve_claude_dir()?;
let rtk_md_path = claude_dir.join("RTK.md");
let claude_md_path = claude_dir.join("CLAUDE.md");

// 1. Write RTK.md
write_if_changed(&rtk_md_path, RTK_SLIM, "RTK.md", verbose)?;
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Windows run_default_mode writes ~/.claude/RTK.md and ~/.claude/CLAUDE.md via write_if_changed/patch_claude_md, but unlike the unix path it never creates the ~/.claude directory first. If the user runs rtk init -g before Claude has created the folder, these writes will fail. Consider fs::create_dir_all(&claude_dir) right after resolve_claude_dir() (and/or ensure parents exist before each write).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread src/hooks/init.rs Outdated
Comment thread src/hooks/init.rs Outdated
Comment on lines +990 to +1007
println!("\nRTK hook installed (Windows native).\n");
println!(" Hook: {} hook claude", hook_command);
println!(" RTK.md: {} (10 lines)", rtk_md_path.display());
println!(" CLAUDE.md: @RTK.md reference added");

if migrated {
println!("\n [ok] Migrated: removed RTK block from CLAUDE.md, replaced with @RTK.md");
}

match patch_result {
PatchResult::Patched => {}
PatchResult::AlreadyPresent => {
println!("\n settings.json: hook already present");
println!(" Restart Claude Code. Test with: git status");
}
PatchResult::Declined | PatchResult::Skipped => {}
}

Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This success banner is printed unconditionally, even when patch_settings_native returns Declined/Skipped (user opted out or manual mode). That can mislead users into thinking the hook is installed when settings.json wasn’t patched. Consider tailoring the message based on PatchResult (e.g., only say “installed” on Patched/AlreadyPresent, and otherwise say “manual step required”).

Suggested change
println!("\nRTK hook installed (Windows native).\n");
println!(" Hook: {} hook claude", hook_command);
println!(" RTK.md: {} (10 lines)", rtk_md_path.display());
println!(" CLAUDE.md: @RTK.md reference added");
if migrated {
println!("\n [ok] Migrated: removed RTK block from CLAUDE.md, replaced with @RTK.md");
}
match patch_result {
PatchResult::Patched => {}
PatchResult::AlreadyPresent => {
println!("\n settings.json: hook already present");
println!(" Restart Claude Code. Test with: git status");
}
PatchResult::Declined | PatchResult::Skipped => {}
}
match patch_result {
PatchResult::Patched => {
println!("\nRTK hook installed (Windows native).\n");
println!(" Hook: {} hook claude", hook_command);
println!(" RTK.md: {} (10 lines)", rtk_md_path.display());
println!(" CLAUDE.md: @RTK.md reference added");
println!(" settings.json: hook added");
println!(" Restart Claude Code. Test with: git status");
}
PatchResult::AlreadyPresent => {
println!("\nRTK hook installed (Windows native).\n");
println!(" Hook: {} hook claude", hook_command);
println!(" RTK.md: {} (10 lines)", rtk_md_path.display());
println!(" CLAUDE.md: @RTK.md reference added");
println!(" settings.json: hook already present");
println!(" Restart Claude Code. Test with: git status");
}
PatchResult::Declined | PatchResult::Skipped => {
println!("\nRTK hook not installed into settings.json (user opted out / manual mode).\n");
println!(" Hook command (for manual setup): {} hook claude", hook_command);
println!(" RTK.md: {} (10 lines)", rtk_md_path.display());
println!(" CLAUDE.md: @RTK.md reference added");
println!(" Next step: update settings.json manually to call the hook command above.");
}
}
if migrated {
println!("\n [ok] Migrated: removed RTK block from CLAUDE.md, replaced with @RTK.md");
}

Copilot uses AI. Check for mistakes.
Comment thread src/main.rs Outdated
Comment thread src/hooks/init.rs Outdated
Comment on lines 865 to 870
.any(|cmd| {
// Exact match OR both contain rtk-rewrite.sh
// Exact match OR both contain same hook fingerprint
cmd == hook_command
|| (cmd.contains("rtk-rewrite.sh") && hook_command.contains("rtk-rewrite.sh"))
|| (cmd.contains("hook claude") && hook_command.contains("hook claude"))
})
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hook_already_present now treats any command containing hook claude as an installed RTK hook, but the existing unit tests only cover the rtk-rewrite.sh fingerprint. Please add a test case for a native Windows command (e.g., "C:\\...\\rtk.exe" hook claude) to ensure idempotency works for the new hook path.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread src/hooks/init.rs Outdated
Comment on lines 472 to 476
if let Some(hooks_array) = entry.get("hooks").and_then(|h| h.as_array()) {
for hook in hooks_array {
if let Some(command) = hook.get("command").and_then(|c| c.as_str()) {
if command.contains("rtk-rewrite.sh") {
if command.contains("rtk-rewrite.sh") || command.contains("hook claude") {
return false; // Remove this entry
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove_hook_from_json now removes entries whose command contains hook claude, but the existing remove_hook_from_json tests only cover removal of rtk-rewrite.sh. Please add a test that verifies native hook commands are removed on uninstall without affecting other hooks.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

@Warrio111 Warrio111 changed the base branch from master to develop March 31, 2026 19:06
@Warrio111 Warrio111 force-pushed the feat/windows-native-hook-rewrite branch from b6abc40 to e831a63 Compare March 31, 2026 19:14
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 31, 2026

CLA assistant check
All committers have signed the CLA.

@Warrio111 Warrio111 force-pushed the feat/windows-native-hook-rewrite branch from e831a63 to 02d9683 Compare March 31, 2026 19:20
@Warrio111
Copy link
Copy Markdown
Author

@copilot apply changes based on the comments in this thread

@aeppling
Copy link
Copy Markdown
Contributor

aeppling commented Apr 3, 2026

Hello, i have a few things to solve on others PR then i can get to you for this review

You can run all test on your machine and repush once solved because you got failing a check

@Warrio111 Warrio111 force-pushed the feat/windows-native-hook-rewrite branch from e96e4a3 to f631af6 Compare April 3, 2026 18:54
@Warrio111
Copy link
Copy Markdown
Author

Sorry @aeppling I didn't saw the failure last day.

@marcoalc-uco
Copy link
Copy Markdown

Hi,
Like a Windows user I've been following this issue closely, hook-based mode not working on
Windows has been a real pain point, so I was happy to see this PR land. I also think this approach
(native binary as hook, no bash/jq required) is a significant improvement over what was attempted
in #150, both in architecture and robustness.

I went through the code carefully and the installation-side fixes look solid the JSON escaping,
the create_dir_all, and the conditional banner are all the right calls. That said, while
reviewing the runtime behavior of run_claude() I found a few things worth discussing before
this merges.


🔴 The hook silently ignores deny and ask rules

This is the main one. run_claude() is currently an alias for run_copilot(), which routes
through get_rewritten()registry::rewrite_command(). The problem is that this path skips
check_command()
from src/hooks/permissions.rs.

The existing bash hook doesn't do the rewrite logic itself — it delegates to rtk rewrite, which
lives in rewrite_cmd.rs and does call check_command() first. That's where the exit-code
protocol lives:

Exit Meaning
0 Rewrite found, auto-allow
1 No RTK equivalent, passthrough
2 Deny rule matched — passthrough, let Claude Code handle it
3 Ask rule matched — rewrite but omit permissionDecision so Claude Code prompts

run_claude() never goes through this. It always emits "permissionDecision": "allow" regardless.
In practice this means: any deny or ask rules a user has configured in their settings.json are
silently ignored on Windows
. Commands they explicitly blocked get auto-allowed. That's a
meaningful security regression.

The fix would be giving run_claude() its own implementation that mirrors rewrite_cmd.rs::run():
call check_command(), branch on PermissionVerdict, and emit the right response for each case
(allow with permissionDecision, ask without it, or silent passthrough for deny).


🟡 A few smaller things worth noting

updatedInput drops extra tool_input fields
The bash hook patches .command inside the full tool_input object, preserving any other fields.
handle_vscode replaces the whole thing with { "command": rewritten }. Low risk today but the
two implementations aren't equivalent, and it could bite if Claude Code adds fields to tool_input.

Copilot CLI format can leak through run_claude()
Because run_claude() delegates to run_copilot(), a payload with camelCase toolName (not
Claude Code's format, but possible with malformed input) would route to handle_copilot_cli and
emit a deny response in the wrong format — no hookSpecificOutput, which Claude Code wouldn't
understand.

Silent double-install when migrating from bash hook
hook_already_present uses separate fingerprints (rtk-rewrite.sh vs hook claude). If someone
shares a settings.json between WSL and Windows and already has the bash hook installed, running
rtk init -g on Windows adds the native hook alongside it — both fire on every Bash command.
Uninstall correctly cleans both (line 485 handles it), but the install path doesn't detect or
migrate the old one.


🟡 Test coverage gaps

The idempotency and removal tests that were added cover the happy path well. But the functional
contract of the hook itself — what it actually outputs at runtime — isn't tested:

Path Covered
run_claude() output format
run_claude() with deny/ask rules
patch_settings_native() end-to-end
native_hook_command() with spaces in path
Bash hook + native hook coexistence on install

Per the contributing guide: "Every change must include tests." A test for the deny rule case
would also make the critical issue above immediately visible — it would fail with the current
implementation.


Overall the direction is right and the install-side is clean. The permission bypass is the blocker
worth resolving before merge. Happy to help draft the fix for run_claude() if that would be
useful.

@Warrio111
Copy link
Copy Markdown
Author

@marcoalc-uco Thanks for the thorough analysis — all points addressed in the latest push.

🔴 Permission bypass — fixed

run_claude() now has its own implementation instead of delegating to run_copilot(). It calls check_command() before rewriting, mirroring the logic in rewrite_cmd.rs:

Verdict Behavior
Deny Silent passthrough — Claude Code enforces its own deny rules
Ask Emit updatedInput but omit permissionDecision — Claude Code prompts
Allow / Default Emit updatedInput with permissionDecision: "allow"

🟡 Copilot CLI format leak — fixed

run_claude() now only handles Claude Code's snake_case format (tool_name/tool_input). camelCase Copilot CLI payloads (toolName/toolArgs) are silently ignored instead of being routed through handle_copilot_cli which emits a deny response Claude Code wouldn't understand.

🟡 Double-install on bash → native migration — fixed

hook_already_present() now returns true if any RTK hook is found (either rtk-rewrite.sh or hook claude). This prevents adding the native hook alongside an existing bash hook when settings.json is shared between WSL and Windows.

🟡 Tests added

Case Covered
run_claude() with deny verdict → no output
run_claude() with ask verdict → no permissionDecision
run_claude() with allow verdict → permissionDecision: "allow"
run_claude() with default verdict → auto-allow
hookEventName present in response
Unsupported command → no output
Already-rtk command → no output
Bash hook detected when installing native (no double-install)
Native hook detected when installing bash (no double-install)

updatedInput dropping extra fields

Left as-is for now — the current behavior (replacing the whole tool_input with { "command": rewritten }) matches what the bash hook produces today, and there are no other fields in tool_input in the current Claude Code protocol. Happy to revisit if that changes.

@marcoalc-uco
Copy link
Copy Markdown

@Warrio111 Thanks for the fast turnaround — went through the new commit and everything checks out.

Permission bypass : run_claude() is now a proper standalone implementation. The
build_claude_response() helper makes the deny/ask/allow branching easy to follow and the
new tests cover all four verdicts cleanly. The Default → allow decision is also the right
call, matching the least-surprise behavior when no rules are configured.

Copilot CLI leak : the explicit tool_name: "Bash" guard is the right fix. Simpler and
more correct than relying on format detection downstream.

Double-install : the new hook_already_present() is cleaner than the previous version.
Dropping the hook_command parameter entirely and unifying on a single .any() check removes
the fingerprint ambiguity completely.

Tests : 9 new tests, all passing (1357 total). The coexistence cases
(test_bash_hook_detected_when_installing_native / test_native_hook_detected_when_installing_bash)
are exactly what was missing.

On the updatedInput note agreed, leaving it as-is is fine for now. If Claude Code ever extends tool_input, the delta will be obvious.

LGTM from my side. 👍

Copy link
Copy Markdown

@1llum1n4t1s 1llum1n4t1s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: hook_check.rs doesn't detect the native hook — "No hook installed" warning on every invocation

hook_installed_path() (src/hooks/hook_check.rs, L93-104) determines hook status solely by checking whether ~/.claude/hooks/rtk-rewrite.sh exists. However, the native hook introduced in this PR writes directly to settings.json ("rtk.exe" hook claude) without deploying a bash script, so status() always returns HookStatus::Missing.

Reproduction (Windows 11 Pro, rtk 0.34.1 built from this branch, Rust 1.94.1)

$ rtk init -g              # installs native hook into settings.json ✅
$ rtk git status           # hook works correctly, command is rewritten ✅
[rtk] /!\ No hook installed — run `rtk init -g` for automatic token savings   # ← spurious warning ❌

Root cause

hook_check.rs checks only for the bash script file:

fn hook_installed_path() -> Option<PathBuf> {
    // ...
    let path = home.join(CLAUDE_DIR).join(HOOKS_SUBDIR).join(REWRITE_HOOK_FILE); // "rtk-rewrite.sh"
    if path.exists() { Some(path) } else { None }
}

Meanwhile, init.rs L864 (hook_already_present()) already detects both variants correctly:

.any(|cmd| cmd.contains(REWRITE_HOOK_FILE) || cmd.contains("hook claude"))

This inconsistency means init knows the native hook is installed, but hook_check does not.

Suggested fix

Add a settings.json check to status() in hook_check.rs — if PreToolUse hooks contain "hook claude", return HookStatus::Ok. Reusing the same predicate as hook_already_present() keeps the detection logic consistent.

// Pseudocode for the additional path in status():
// 1. ~/.claude/hooks/rtk-rewrite.sh exists → existing version check
// 2. settings.json PreToolUse contains "hook claude" → HookStatus::Ok
// 3. Neither → HookStatus::Missing

@Warrio111
Copy link
Copy Markdown
Author

@1llum1n4t1s Good catch — fixed in the latest commit.

Root cause: status() in hook_check.rs only checked for ~/.claude/hooks/rtk-rewrite.sh. Since rtk init -g on Windows writes directly to settings.json without deploying a bash script, status() always returned HookStatus::Missing.

Fix: Added native_hook_in_settings() which reads ~/.claude/settings.json and checks whether any PreToolUse hook contains "hook claude". status() now checks this before the file-existence path:

1. ~/.claude/ doesn't exist         → Ok (Claude Code not installed)
2. settings.json has "hook claude"  → Ok (native hook active)  ← new
3. rtk-rewrite.sh exists            → version check (Ok / Outdated)
4. Neither                          → Missing

Three unit tests added for the new helper (native hook detected, bash-only returns false, missing file returns false). The existing test_status_returns_valid_variant integration test was also updated to recognise the native hook as a valid installed state.

…red)

Adds `rtk hook claude` subcommand that reads Claude Code PreToolUse JSON
from stdin and rewrites commands natively — no bash or jq dependency.

On Windows, `rtk init -g` now installs `rtk hook claude` directly in
settings.json instead of printing a warning and falling back to --claude-md.

Changes:
- src/hooks/hook_cmd.rs: add run_claude() (wraps run_copilot(), same format)
- src/main.rs: add HookCommands::Claude routing to run_claude()
- src/hooks/init.rs:
  - native_hook_command(): resolves rtk binary path
  - patch_settings_native(): installs command string in settings.json
  - fs::create_dir_all before writing RTK.md/CLAUDE.md on Windows
  - JSON-escape hook_command in manual snippet to avoid invalid JSON
  - Conditional banner based on PatchResult (not unconditional)
  - hook_already_present/remove_hook_from_json recognize 'hook claude'
  - Tests: hook_already_present and remove_hook_from_json for native hook
…install

- run_claude() now has its own implementation instead of delegating to
  run_copilot(). It only handles Claude Code's snake_case format, avoiding
  accidental routing of Copilot CLI camelCase payloads through the wrong
  response format.

- Permission rules are now checked before rewriting (mirrors rewrite_cmd.rs):
  * Deny verdict  → silent passthrough, Claude Code enforces natively
  * Ask verdict   → emit updatedInput but omit permissionDecision so
                     Claude Code prompts the user
  * Allow/Default → emit updatedInput with permissionDecision: "allow"

- hook_already_present() now treats any RTK hook (bash or native) as
  installed, preventing double-installation when a shared settings.json
  already contains rtk-rewrite.sh and the user runs rtk init -g on Windows.

- Added tests: deny/ask/allow/default verdicts, format validation,
  unsupported command passthrough, and bash+native coexistence detection.
…arning

rtk init -g on Windows installs hook claude directly in settings.json
without writing rtk-rewrite.sh, so status() returned HookStatus::Missing
and printed "No hook installed" on every command invocation.

Add native_hook_in_settings() which reads ~/.claude/settings.json and
checks for a PreToolUse hook containing "hook claude". status() consults
this before the file-existence check, returning Ok immediately when the
native hook is active.

Updated test_status_returns_valid_variant to recognise the native hook
as a valid installed state; added three unit tests for the new helper.
@Warrio111 Warrio111 force-pushed the feat/windows-native-hook-rewrite branch from 4d4feff to 46f8f5f Compare April 5, 2026 19:09
@Warrio111 Warrio111 requested a review from 1llum1n4t1s April 5, 2026 19:11
…pdate docs

- Replace contains("hook claude") with ends_with("hook claude") in
  hook_check.rs, init.rs (hook_already_present, remove_hook_from_json)
  and init.rs (run_uninstall_mode) — anchored suffix match avoids
  theoretical false positives from unrelated commands that happen to
  contain the substring.

- Add test_claude_excluded_command_returns_none: verifies that commands
  in the exclude list produce no hook output via build_claude_response().

- Fix misleading comment: "Explicit allow" → "Allow (explicit) or Default
  (no rules configured)" to accurately describe both handled verdicts.

- Update src/hooks/README.md: document Windows native hook installation
  mode in the Installation Modes table, add Windows native hook section
  with example settings.json snippet, and update per-tool support table
  to distinguish Unix bash hook from Windows native hook.
Copy link
Copy Markdown

@1llum1n4t1s 1llum1n4t1s left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Warrio111
Copy link
Copy Markdown
Author

@aeppling Do you see improvements that i have to implement?

@Warrio111 Warrio111 mentioned this pull request Apr 8, 2026
4 tasks
Copy link
Copy Markdown

@SweetAries0409 SweetAries0409 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Warrio111
Copy link
Copy Markdown
Author

@pszymkowiak It looks good to you?

@miirK1
Copy link
Copy Markdown

miirK1 commented Apr 13, 2026

Looking for it

@Warrio111
Copy link
Copy Markdown
Author

Superseded by #956
(feat-hook-engine)

@Warrio111 Warrio111 closed this Apr 16, 2026
@Warrio111 Warrio111 deleted the feat/windows-native-hook-rewrite branch April 27, 2026 05:34
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.

8 participants