1#!/bin/bash
2# Crush Hook Helper Functions
3# These functions are automatically available in all hooks.
4# No need to source this file - it's prepended automatically.
5
6# Permission helpers
7
8# Approve the current tool call.
9# Usage: crush_approve ["message"]
10crush_approve() {
11 export CRUSH_PERMISSION=approve
12 [ -n "$1" ] && export CRUSH_MESSAGE="$1"
13}
14
15# Deny the current tool call.
16# Usage: crush_deny ["message"]
17crush_deny() {
18 export CRUSH_PERMISSION=deny
19 export CRUSH_CONTINUE=false
20 [ -n "$1" ] && export CRUSH_MESSAGE="$1"
21 exit 2
22}
23
24# Ask user for permission (default behavior).
25# Usage: crush_ask ["message"]
26crush_ask() {
27 export CRUSH_PERMISSION=ask
28 [ -n "$1" ] && export CRUSH_MESSAGE="$1"
29}
30
31# Context helpers
32
33# Add raw text content to LLM context.
34# Usage: crush_add_context "content"
35crush_add_context() {
36 export CRUSH_CONTEXT_CONTENT="$1"
37}
38
39# Add a file to be loaded into LLM context.
40# Usage: crush_add_context_file "/path/to/file.md"
41crush_add_context_file() {
42 if [ -z "$CRUSH_CONTEXT_FILES" ]; then
43 export CRUSH_CONTEXT_FILES="$1"
44 else
45 export CRUSH_CONTEXT_FILES="$CRUSH_CONTEXT_FILES:$1"
46 fi
47}
48
49# Modification helpers
50
51# Modify the user prompt (UserPromptSubmit hooks only).
52# Usage: crush_modify_prompt "new prompt text"
53crush_modify_prompt() {
54 export CRUSH_MODIFIED_PROMPT="$1"
55}
56
57# Modify tool input parameters (PreToolUse hooks only).
58# Values are parsed as JSON when valid, supporting strings, numbers, booleans, arrays, objects.
59# Usage: crush_modify_input "param_name" "value"
60# Examples:
61# crush_modify_input "command" "ls -la"
62# crush_modify_input "offset" "100"
63# crush_modify_input "run_in_background" "true"
64# crush_modify_input "ignore" '["*.log","*.tmp"]'
65crush_modify_input() {
66 local key="$1"
67 local value="$2"
68 if [ -z "$CRUSH_MODIFIED_INPUT" ]; then
69 export CRUSH_MODIFIED_INPUT="$key=$value"
70 else
71 export CRUSH_MODIFIED_INPUT="$CRUSH_MODIFIED_INPUT:$key=$value"
72 fi
73}
74
75# Modify tool output (PostToolUse hooks only).
76# Usage: crush_modify_output "field_name" "value"
77crush_modify_output() {
78 local key="$1"
79 local value="$2"
80 if [ -z "$CRUSH_MODIFIED_OUTPUT" ]; then
81 export CRUSH_MODIFIED_OUTPUT="$key=$value"
82 else
83 export CRUSH_MODIFIED_OUTPUT="$CRUSH_MODIFIED_OUTPUT:$key=$value"
84 fi
85}
86
87# Stop execution.
88# Usage: crush_stop ["message"]
89crush_stop() {
90 export CRUSH_CONTINUE=false
91 [ -n "$1" ] && export CRUSH_MESSAGE="$1"
92 exit 1
93}
94
95# Input parsing helpers
96# These read from the JSON context saved in _CRUSH_STDIN
97
98# Get a field from the hook context.
99# Usage: VALUE=$(crush_get_input "field_name")
100crush_get_input() {
101 echo "$_CRUSH_STDIN" | jq -r ".$1 // empty"
102}
103
104# Get a tool input parameter.
105# Usage: COMMAND=$(crush_get_tool_input "command")
106crush_get_tool_input() {
107 echo "$_CRUSH_STDIN" | jq -r ".tool_input.$1 // empty"
108}
109
110# Get the user prompt.
111# Usage: PROMPT=$(crush_get_prompt)
112crush_get_prompt() {
113 echo "$_CRUSH_STDIN" | jq -r '.prompt // empty'
114}
115
116# Logging helper.
117# Writes to stderr which is captured by Crush.
118# Usage: crush_log "debug message"
119crush_log() {
120 echo "[CRUSH HOOK] $*" >&2
121}