-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add Copilot and Codex hook parity #1788
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0331f12
da2f6d5
8939e4b
eb15569
8c35dbd
af749ae
7e1604c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||||||||||||||
| # rtk-hook-version: 3 | ||||||||||||||||||||||||||||||||||||||||||||||
| # RTK auto-rewrite hook for Claude Code PreToolUse:Bash | ||||||||||||||||||||||||||||||||||||||||||||||
| # RTK auto-rewrite hook for Claude/Codex/Copilot PreToolUse shell commands. | ||||||||||||||||||||||||||||||||||||||||||||||
| # Transparently rewrites raw commands to their RTK equivalents. | ||||||||||||||||||||||||||||||||||||||||||||||
| # Uses `rtk rewrite` as single source of truth — no duplicate mapping logic here. | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,7 +32,15 @@ fi | |||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| INPUT=$(cat) | ||||||||||||||||||||||||||||||||||||||||||||||
| CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty') | ||||||||||||||||||||||||||||||||||||||||||||||
| CMD=$(echo "$INPUT" | jq -r ' | ||||||||||||||||||||||||||||||||||||||||||||||
| .tool.input.command | ||||||||||||||||||||||||||||||||||||||||||||||
| // .tool_input.command | ||||||||||||||||||||||||||||||||||||||||||||||
| // (.toolArgs | if type == "object" then .command else empty end) | ||||||||||||||||||||||||||||||||||||||||||||||
| // (.toolArgs | if type == "string" then (fromjson? | .command) else empty end) | ||||||||||||||||||||||||||||||||||||||||||||||
| // .toolInput.command | ||||||||||||||||||||||||||||||||||||||||||||||
| // .command | ||||||||||||||||||||||||||||||||||||||||||||||
| // empty | ||||||||||||||||||||||||||||||||||||||||||||||
| ') | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$CMD" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| _rtk_audit_log "skip:empty" "-" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -78,11 +86,37 @@ esac | |||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| _rtk_audit_log "rewrite" "$CMD" "$REWRITTEN" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Build the updated tool_input with all original fields preserved, only command changed. | ||||||||||||||||||||||||||||||||||||||||||||||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | ||||||||||||||||||||||||||||||||||||||||||||||
| # Build the updated tool input with all original fields preserved, only command changed. | ||||||||||||||||||||||||||||||||||||||||||||||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c ' | ||||||||||||||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||||||||||||||
| .tool_input | ||||||||||||||||||||||||||||||||||||||||||||||
| // .tool.input | ||||||||||||||||||||||||||||||||||||||||||||||
| // .toolArgs | ||||||||||||||||||||||||||||||||||||||||||||||
| // .toolInput | ||||||||||||||||||||||||||||||||||||||||||||||
| // {} | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | if type == "string" then (fromjson? // {}) else . end | ||||||||||||||||||||||||||||||||||||||||||||||
| ') | ||||||||||||||||||||||||||||||||||||||||||||||
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | ||||||||||||||||||||||||||||||||||||||||||||||
| IS_COPILOT_INPUT=$(echo "$INPUT" | jq -r 'has("toolName") and has("toolArgs")') | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+90
to
+100
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two issues in this block:
Adding a type check and including
Suggested change
References
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$IS_COPILOT_INPUT" = "true" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| jq -n \ | ||||||||||||||||||||||||||||||||||||||||||||||
| --argjson modified "$UPDATED_INPUT" \ | ||||||||||||||||||||||||||||||||||||||||||||||
| '{ | ||||||||||||||||||||||||||||||||||||||||||||||
| "permissionDecision": "ask", | ||||||||||||||||||||||||||||||||||||||||||||||
| "modifiedArgs": $modified | ||||||||||||||||||||||||||||||||||||||||||||||
| }' | ||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||
| jq -n \ | ||||||||||||||||||||||||||||||||||||||||||||||
| --argjson modified "$UPDATED_INPUT" \ | ||||||||||||||||||||||||||||||||||||||||||||||
| '{ | ||||||||||||||||||||||||||||||||||||||||||||||
| "permissionDecision": "allow", | ||||||||||||||||||||||||||||||||||||||||||||||
| "permissionDecisionReason": "RTK auto-rewrite", | ||||||||||||||||||||||||||||||||||||||||||||||
| "modifiedArgs": $modified | ||||||||||||||||||||||||||||||||||||||||||||||
| }' | ||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||
| elif [ "$EXIT_CODE" -eq 3 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | ||||||||||||||||||||||||||||||||||||||||||||||
| jq -n \ | ||||||||||||||||||||||||||||||||||||||||||||||
| --argjson updated "$UPDATED_INPUT" \ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,8 +8,12 @@ oss_provider = "lmstudio" | |
| apply_patch_freeform = true | ||
| apply_patch_streaming_events = true | ||
| apps = true | ||
| apps_mcp_path_override = true | ||
| artifact = true | ||
| auth_elicitation = true | ||
| browser_use = true | ||
| browser_use_external = true | ||
| builtin_mcp = true | ||
| child_agents_md = true | ||
| chronicle = true | ||
| code_mode = true | ||
|
|
@@ -18,6 +22,7 @@ codex_git_commit = true | |
| computer_use = true | ||
| default_mode_request_user_input = true | ||
| enable_fanout = true | ||
| enable_mcp_apps = true | ||
| enable_request_compression = true | ||
| exec_permission_approvals = true | ||
| external_migration = true | ||
|
|
@@ -34,12 +39,15 @@ memories = true | |
| multi_agent = true | ||
| multi_agent_v2 = true | ||
| personality = true | ||
| plugin_hooks = true | ||
| plugins = true | ||
| prevent_idle_sleep = true | ||
| realtime_conversation = true | ||
| remote_compaction_v2 = true | ||
| remote_control = true | ||
| remote_plugin = true | ||
| request_permissions_tool = true | ||
| responses_websocket_response_processed = true | ||
| runtime_metrics = true | ||
| shell_snapshot = true | ||
| shell_tool = true | ||
|
|
@@ -50,6 +58,7 @@ tool_call_mcp_elicitation = true | |
| tool_search = true | ||
| tool_search_always_defer_mcp_tools = true | ||
| tool_suggest = true | ||
| terminal_resize_reflow = true | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out of alphabetical order — the rest of |
||
| unavailable_dummy_tools = true | ||
| undo = true | ||
| unified_exec = true | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| #!/usr/bin/env bash | ||||||||||||||||||||||||||||||||||||||||||||||
| # rtk-hook-version: 3 | ||||||||||||||||||||||||||||||||||||||||||||||
| # RTK auto-rewrite hook for Claude Code PreToolUse:Bash | ||||||||||||||||||||||||||||||||||||||||||||||
| # RTK auto-rewrite hook for Claude/Codex/Copilot PreToolUse shell commands. | ||||||||||||||||||||||||||||||||||||||||||||||
| # Transparently rewrites raw commands to their RTK equivalents. | ||||||||||||||||||||||||||||||||||||||||||||||
| # Uses `rtk rewrite` as single source of truth — no duplicate mapping logic here. | ||||||||||||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,7 +32,15 @@ fi | |||||||||||||||||||||||||||||||||||||||||||||
| set -euo pipefail | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| INPUT=$(cat) | ||||||||||||||||||||||||||||||||||||||||||||||
| CMD=$(echo "$INPUT" | jq -r '.tool_input.command // empty') | ||||||||||||||||||||||||||||||||||||||||||||||
| CMD=$(echo "$INPUT" | jq -r ' | ||||||||||||||||||||||||||||||||||||||||||||||
| .tool.input.command | ||||||||||||||||||||||||||||||||||||||||||||||
| // .tool_input.command | ||||||||||||||||||||||||||||||||||||||||||||||
| // (.toolArgs | if type == "object" then .command else empty end) | ||||||||||||||||||||||||||||||||||||||||||||||
| // (.toolArgs | if type == "string" then (fromjson? | .command) else empty end) | ||||||||||||||||||||||||||||||||||||||||||||||
| // .toolInput.command | ||||||||||||||||||||||||||||||||||||||||||||||
| // .command | ||||||||||||||||||||||||||||||||||||||||||||||
| // empty | ||||||||||||||||||||||||||||||||||||||||||||||
| ') | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if [ -z "$CMD" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| _rtk_audit_log "skip:empty" "-" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -78,11 +86,37 @@ esac | |||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| _rtk_audit_log "rewrite" "$CMD" "$REWRITTEN" | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| # Build the updated tool_input with all original fields preserved, only command changed. | ||||||||||||||||||||||||||||||||||||||||||||||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c '.tool_input') | ||||||||||||||||||||||||||||||||||||||||||||||
| # Build the updated tool input with all original fields preserved, only command changed. | ||||||||||||||||||||||||||||||||||||||||||||||
| ORIGINAL_INPUT=$(echo "$INPUT" | jq -c ' | ||||||||||||||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||||||||||||||
| .tool_input | ||||||||||||||||||||||||||||||||||||||||||||||
| // .tool.input | ||||||||||||||||||||||||||||||||||||||||||||||
| // .toolArgs | ||||||||||||||||||||||||||||||||||||||||||||||
| // .toolInput | ||||||||||||||||||||||||||||||||||||||||||||||
| // {} | ||||||||||||||||||||||||||||||||||||||||||||||
| ) | if type == "string" then (fromjson? // {}) else . end | ||||||||||||||||||||||||||||||||||||||||||||||
| ') | ||||||||||||||||||||||||||||||||||||||||||||||
| UPDATED_INPUT=$(echo "$ORIGINAL_INPUT" | jq --arg cmd "$REWRITTEN" '.command = $cmd') | ||||||||||||||||||||||||||||||||||||||||||||||
| IS_COPILOT_INPUT=$(echo "$INPUT" | jq -r 'has("toolName") and has("toolArgs")') | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+90
to
+100
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two issues in this block:
Adding a type check and including
Suggested change
References
|
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$IS_COPILOT_INPUT" = "true" ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$EXIT_CODE" -eq 3 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| jq -n \ | ||||||||||||||||||||||||||||||||||||||||||||||
| --argjson modified "$UPDATED_INPUT" \ | ||||||||||||||||||||||||||||||||||||||||||||||
| '{ | ||||||||||||||||||||||||||||||||||||||||||||||
| "permissionDecision": "ask", | ||||||||||||||||||||||||||||||||||||||||||||||
| "modifiedArgs": $modified | ||||||||||||||||||||||||||||||||||||||||||||||
| }' | ||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||
| jq -n \ | ||||||||||||||||||||||||||||||||||||||||||||||
| --argjson modified "$UPDATED_INPUT" \ | ||||||||||||||||||||||||||||||||||||||||||||||
| '{ | ||||||||||||||||||||||||||||||||||||||||||||||
| "permissionDecision": "allow", | ||||||||||||||||||||||||||||||||||||||||||||||
| "permissionDecisionReason": "RTK auto-rewrite", | ||||||||||||||||||||||||||||||||||||||||||||||
| "modifiedArgs": $modified | ||||||||||||||||||||||||||||||||||||||||||||||
| }' | ||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||
| elif [ "$EXIT_CODE" -eq 3 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||
| # Ask: rewrite the command, omit permissionDecision so Claude Code prompts. | ||||||||||||||||||||||||||||||||||||||||||||||
| jq -n \ | ||||||||||||||||||||||||||||||||||||||||||||||
| --argjson updated "$UPDATED_INPUT" \ | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,18 +1,29 @@ | ||||||
| #!/usr/bin/env bash | ||||||
|
|
||||||
| # Codex Security Hook | ||||||
| # Codex/Copilot Security Hook | ||||||
| # Blocks dangerous Bash commands by checking against deny patterns. | ||||||
| # Returns exit code 2 to block, exit code 0 to allow. | ||||||
|
|
||||||
| set -euo pipefail | ||||||
|
|
||||||
| input=$(cat) | ||||||
|
|
||||||
| # Only process Bash commands | ||||||
| tool_name=$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null) | ||||||
| [[ $tool_name != "Bash" ]] && exit 0 | ||||||
|
|
||||||
| command=$(echo "$input" | jq -r '.tool_input.command // empty' 2>/dev/null) | ||||||
| # Only process shell commands when the hook input includes a tool name. | ||||||
| tool_name=$(echo "$input" | jq -r '.tool.name // .tool_name // .toolName // empty' 2>/dev/null) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Unsafe jq field access can abort the security hook when Prompt for AI agents
Suggested change
|
||||||
| case "$tool_name" in | ||||||
| "" | Bash | bash | shell) ;; | ||||||
| *) exit 0 ;; | ||||||
| esac | ||||||
|
|
||||||
| command=$(echo "$input" | jq -r ' | ||||||
| .tool.input.command | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: The first command-path in the jq fallback chain is not type-safe; it can fail fast and skip all fallback parsing. Prompt for AI agents |
||||||
| // .tool_input.command | ||||||
| // (.toolArgs | if type == "object" then .command else empty end) | ||||||
| // (.toolArgs | if type == "string" then (fromjson? | .command) else empty end) | ||||||
| // .toolInput.command | ||||||
| // .command | ||||||
| // empty | ||||||
| ' 2>/dev/null) | ||||||
| [[ -z $command ]] && exit 0 | ||||||
|
|
||||||
| # Hardcoded deny patterns (mirrors claude settings.json deny list) | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #!/usr/bin/env bash | ||
| # Copy managed Copilot config into the mutable runtime location. | ||
| # Usage: activate.sh <config_json> | ||
| set -euo pipefail | ||
|
|
||
| CONFIG_JSON="$1" | ||
|
|
||
| mkdir -p ~/.copilot | ||
| cp -f "$CONFIG_JSON" ~/.copilot/config.json | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wipes Copilot-written state on every activation: If preserving Copilot's mutations matters, merge instead of overwrite, e.g.: (or restrict the merge to just |
||
| chmod 600 ~/.copilot/config.json | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,34 @@ | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| "disableAllHooks": false, | ||||||||||||||||||||||||
| "hooks": { | ||||||||||||||||||||||||
| "preToolUse": [ | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| "type": "command", | ||||||||||||||||||||||||
| "matcher": "bash|shell|Bash", | ||||||||||||||||||||||||
| "command": "$HOME/.copilot/hooks/rtk-rewrite.sh", | ||||||||||||||||||||||||
| "timeout": 5 | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| "type": "command", | ||||||||||||||||||||||||
| "command": "command -v dcg >/dev/null 2>&1 && dcg", | ||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing {
"type": "command",
"matcher": "bash|shell|Bash",
"command": "command -v dcg >/dev/null 2>&1 && dcg",
"timeout": 5
} |
||||||||||||||||||||||||
| "timeout": 5 | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
|
Comment on lines
+11
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restrict This is the only pre-tool hook in this chain without a matcher, so Copilot will run it for every tool call. The stack contract for this PR keeps 💡 Proposed fix {
"type": "command",
+ "matcher": "bash|shell|Bash",
"command": "command -v dcg >/dev/null 2>&1 && dcg",
"timeout": 5
},📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| "type": "command", | ||||||||||||||||||||||||
| "matcher": "bash|shell|Bash", | ||||||||||||||||||||||||
| "command": "$HOME/.copilot/hooks/security.sh", | ||||||||||||||||||||||||
| "timeout": 5 | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| "type": "command", | ||||||||||||||||||||||||
| "command": "$HOME/dotfiles/config/shared/hooks/block-git-push.sh", | ||||||||||||||||||||||||
| "timeout": 5 | ||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||
| { | ||||||||||||||||||||||||
| "type": "command", | ||||||||||||||||||||||||
| "command": "$HOME/dotfiles/config/shared/hooks/block-gh-settings.sh", | ||||||||||||||||||||||||
| "timeout": 5 | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { lib, pkgs, ... }: | ||
| { | ||
| # Copilot CLI mutates config.json, so copy the managed file into place. | ||
| home.activation.copilotConfig = lib.hm.dag.entryAfter [ "writeBoundary" ] '' | ||
| $DRY_RUN_CMD ${pkgs.bash}/bin/bash "${./activate.sh}" "${./config.json}" | ||
| ''; | ||
|
|
||
| home.file.".copilot/hooks/rtk-rewrite.sh" = { | ||
| source = ../codex/hooks/rtk-rewrite.sh; | ||
| executable = true; | ||
| force = true; | ||
| }; | ||
|
|
||
| home.file.".copilot/hooks/security.sh" = { | ||
| source = ../codex/hooks/security.sh; | ||
| executable = true; | ||
| force = true; | ||
| }; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ in | |
| ./ccs | ||
| ./cliproxyapi | ||
| ./codex | ||
| ./copilot | ||
| ./crush | ||
| ./cursor | ||
| ./claude | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,5 +1,5 @@ | ||||||
| #!/usr/bin/env bash | ||||||
| # block-git-push.sh - Shared hook for Claude Code + Codex | ||||||
| # block-git-push.sh - Shared hook for Claude Code + Codex + Copilot | ||||||
| # Blocks git push to main/master unless repo is in the allowlist. | ||||||
| # Exit 2 = block (Codex), JSON decision output (Claude). | ||||||
| set -euo pipefail | ||||||
|
|
@@ -13,8 +13,8 @@ ALLOWED_REPOS=( | |||||
| # Read tool input from stdin | ||||||
| input=$(cat) | ||||||
|
|
||||||
| # Extract command (works for both Claude and Codex input formats) | ||||||
| command=$(echo "$input" | jq -r '.tool_input.command // .command // empty' 2>/dev/null) | ||||||
| # Extract command (works for Claude, Codex, and Copilot hook input formats) | ||||||
| command=$(echo "$input" | jq -r '.tool.input.command // .tool_input.command // .toolArgs.command // .toolInput.command // .command // empty' 2>/dev/null) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: This jq path can throw on valid inputs (e.g. when Prompt for AI agents
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copilot string toolArgs not blocked: this only reads Reproduce: Replace the extraction with the same union expression used in |
||||||
| [[ -z $command ]] && exit 0 | ||||||
|
|
||||||
| # Only check git push commands | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changing
|| echo 0to|| truereduces the robustness of the script. Whilegrep -ctypically outputs0even when no matches are found (exiting with status 1), using|| truemeans that ifgrepfails to produce any output (e.g., due to an internal error or being killed),ACCOUNT_COUNTwill be assigned an empty string. This will cause a syntax error in the subsequent numeric comparison[ "$ACCOUNT_COUNT" -lt 2 ]. Reverting to|| echo 0ensures a valid numeric fallback.