345345# cannot be affected by broken rule files. ToolSearch and other CC-internal
346346# tools stay in the step 7 passthrough list (they use {"continue": true}).
347347case " $TOOL_NAME " in
348- Agent|Skill|Glob)
348+ Agent|Skill|Glob|WebSearch )
349349 emit_decision " allow" " passthru internal: ${TOOL_NAME} "
350350 audit_write_line " allow" " $TOOL_NAME " " passthru internal: ${TOOL_NAME} " " " " " " $TOOL_USE_ID " " passthru-internal"
351351 exit 0
@@ -751,6 +751,40 @@ export PASSTHRU_OVERLAY_TOOL_NAME="$TOOL_NAME"
751751export PASSTHRU_OVERLAY_TOOL_INPUT_JSON=" $TOOL_INPUT "
752752export PASSTHRU_OVERLAY_CWD=" $CC_CWD "
753753
754+ # --- Overlay queue lock -------------------------------------------------------
755+ # CC can fire multiple PreToolUse hooks concurrently (parallel tool calls).
756+ # Only one overlay popup can be visible at a time in a given multiplexer.
757+ # Without serialization, the second+ hook falls through to CC's native dialog.
758+ # We use a mkdir-based lock to queue concurrent overlay invocations.
759+ _OVERLAY_LOCK=" ${_tmpdir} /passthru-overlay.lock.d"
760+ _OVERLAY_LOCK_TIMEOUT=" ${PASSTHRU_OVERLAY_LOCK_TIMEOUT:- 90} "
761+ _overlay_lock_acquired=0
762+
763+ _release_overlay_lock () {
764+ if [ " $_overlay_lock_acquired " -eq 1 ]; then
765+ rm -rf " $_OVERLAY_LOCK " 2> /dev/null || true
766+ _overlay_lock_acquired=0
767+ fi
768+ }
769+
770+ # Acquire the lock. Poll at 200ms intervals up to the timeout.
771+ _lock_start=" $( date +%s) "
772+ while true ; do
773+ if mkdir " $_OVERLAY_LOCK " 2> /dev/null; then
774+ _overlay_lock_acquired=1
775+ # Ensure lock is released even on unexpected exits (ERR trap, signals).
776+ trap ' _release_overlay_lock; printf "[passthru] unexpected error in pre-tool-use.sh\n" >&2; emit_passthrough; exit 0' ERR
777+ trap ' _release_overlay_lock' EXIT
778+ break
779+ fi
780+ _now=" $( date +%s) "
781+ if [ $(( _now - _lock_start)) -ge " $_OVERLAY_LOCK_TIMEOUT " ]; then
782+ printf ' [passthru] overlay lock timeout after %ds; falling back to native dialog\n' " $_OVERLAY_LOCK_TIMEOUT " >&2
783+ emit_ask_fallback " overlay lock timeout"
784+ fi
785+ sleep 0.2
786+ done
787+
754788# Send a desktop notification so the user knows a permission prompt is waiting.
755789# OSC 777 is supported by Ghostty, iTerm2, and other modern terminals.
756790printf ' \033]777;notify;passthru;permission prompt: %s\a' " $TOOL_NAME " 2> /dev/null || true
@@ -764,7 +798,10 @@ set +e
764798bash " $OVERLAY_SH "
765799OVERLAY_RC=$?
766800set -e
767- trap ' printf "[passthru] unexpected error in pre-tool-use.sh\n" >&2; emit_passthrough; exit 0' ERR
801+ trap ' _release_overlay_lock; printf "[passthru] unexpected error in pre-tool-use.sh\n" >&2; emit_passthrough; exit 0' ERR
802+
803+ # Release the lock so the next queued overlay can proceed.
804+ _release_overlay_lock
768805
769806if [ " $OVERLAY_RC " -ne 0 ]; then
770807 # Launch failure (rc 1 = no multiplexer detected at launch time, rc 2 =
0 commit comments