Skip to content

[hooks] add non-streaming (non-stdin style) shell-only PreToolUse support#15211

Merged
eternal-openai merged 9 commits intomainfrom
eternal/hooks-pretooluse-bash
Mar 23, 2026
Merged

[hooks] add non-streaming (non-stdin style) shell-only PreToolUse support#15211
eternal-openai merged 9 commits intomainfrom
eternal/hooks-pretooluse-bash

Conversation

@eternal-openai
Copy link
Contributor

@eternal-openai eternal-openai commented Mar 19, 2026

  • add PreToolUse hook for bash-like tool execution only at first
  • block shell execution before dispatch with deny-only hook behavior
  • introduces common.rs matcher framework for matching when hooks are run

example run:

› run three parallel echo commands, and the second one should echo "[block-pre-tool-use]" as a test


• Running the three echo commands in parallel now and I’ll report the output directly.

• Running PreToolUse hook: name for demo pre tool use hook

• Running PreToolUse hook: name for demo pre tool use hook

• Running PreToolUse hook: name for demo pre tool use hook

PreToolUse hook (completed)
  warning: wizard-tower PreToolUse demo inspected Bash: echo "first parallel echo"
  
PreToolUse hook (blocked)
  warning: wizard-tower PreToolUse demo blocked a Bash command on purpose.
  feedback: PreToolUse demo blocked the command. Remove [block-pre-tool-use] to continue.

PreToolUse hook (completed)
  warning: wizard-tower PreToolUse demo inspected Bash: echo "third parallel echo"

• Ran echo "first parallel echo"
  └ first parallel echo

• Ran echo "third parallel echo"
  └ third parallel echo

• Three little waves went out in parallel.

  1. printed first parallel echo
  2. was blocked before execution because it contained the exact test string [block-pre-tool-use]
  3. printed third parallel echo

  There was also an unrelated macOS defaults warning around the successful commands, but the echoes
  themselves worked fine. If you want, I can rerun the second one with a slightly modified string so
  it passes cleanly.

eternal-openai added a commit that referenced this pull request Mar 19, 2026
@eternal-openai eternal-openai force-pushed the eternal/hooks-pretooluse-bash branch from 8d3bef5 to 566a173 Compare March 19, 2026 19:45
eternal-openai added a commit that referenced this pull request Mar 19, 2026
@eternal-openai eternal-openai force-pushed the eternal/hooks-pretooluse-bash branch from 314bdc8 to 78b6865 Compare March 20, 2026 00:28
@eternal-openai eternal-openai changed the title [hooks] add bash-only PreToolUse support [hooks] add non-streaming (non-stdin style) shell-only PreToolUse support Mar 21, 2026
eternal-openai added a commit that referenced this pull request Mar 23, 2026
.await
{
return Err(FunctionCallError::RespondToModel(format!(
"Bash command blocked by hook: {reason}. Command: {command}"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this message too specific (bash)?

cmd: String,
}

fn pre_tool_use_command(tool_name: &str, payload: &ToolPayload) -> Option<String> {
Copy link
Collaborator

@pakrym-oai pakrym-oai Mar 23, 2026

Choose a reason for hiding this comment

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

I quite dislike this hardcoding and arg re-parsing here.

Copy link
Collaborator

@pakrym-oai pakrym-oai Mar 23, 2026

Choose a reason for hiding this comment

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

What do you think about individual tool handlers invoking hooks?

.features
.disable(Feature::GhostCommit)
.expect("test config should allow feature update");
config.permissions.approval_policy = Constrained::allow_any(AskForApproval::Never);
Copy link
Collaborator

@pakrym-oai pakrym-oai Mar 23, 2026

Choose a reason for hiding this comment

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

unrelated?

}
};

for group in parsed.hooks.pre_tool_use {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: is this loop just being repeated per hook type is there a way to make it into a method?

@eternal-openai eternal-openai merged commit 73bbb07 into main Mar 23, 2026
36 checks passed
@eternal-openai eternal-openai deleted the eternal/hooks-pretooluse-bash branch March 23, 2026 21:33
@github-actions github-actions bot locked and limited conversation to collaborators Mar 23, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants