From 011df7797f563205505e06cf62e712f7ace11447 Mon Sep 17 00:00:00 2001 From: davidacimovic Date: Fri, 27 Mar 2026 22:47:51 -0400 Subject: [PATCH] Fix Terminal.app window scanning on macOS 15 Sequoia MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On macOS 15, Terminal.app's AppleScript bridge breaks when iterating windows with `repeat with w in windows` — accessing `id of w` or `name of w` throws error -1700. This causes the app to show "No terminals open" despite Terminal.app running with open windows. Fix by using bulk property fetch (`name of every window`) combined with index-based access (`window i`, `tab j of window i`), which works correctly on both macOS 14 and 15. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Adapters/TerminalAppAdapter.swift | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/Sources/Services/Adapters/TerminalAppAdapter.swift b/Sources/Services/Adapters/TerminalAppAdapter.swift index 2bda440..45a2b7b 100644 --- a/Sources/Services/Adapters/TerminalAppAdapter.swift +++ b/Sources/Services/Adapters/TerminalAppAdapter.swift @@ -23,26 +23,30 @@ final class TerminalAppAdapter { hasLoggedPermissionError = false // Full scan — uses ||| as delimiter and ASCII char 10 (LF) for line breaks - // AppleScript does NOT interpret \t or \n as escape sequences + // macOS 15+: window iterators lose properties, so use bulk name fetch + index-based access let script = """ tell application "Terminal" set output to "" set lf to (ASCII character 10) - repeat with w in windows - set winID to (id of w as text) - set winName to name of w - set tabCount to count of tabs of w - repeat with i from 1 to tabCount - set t to tab i of w - set tabTTY to tty of t - set tabBusy to (busy of t as text) - set tabProcs to processes of t - set procList to "" - repeat with p in tabProcs - if procList is not "" then set procList to procList & "," - set procList to procList & (p as text) - end repeat - set output to output & winID & "|||" & winName & "|||" & i & "|||" & tabTTY & "|||" & tabBusy & "|||" & procList & lf + set wNames to name of every window + set wCount to count windows + repeat with i from 1 to wCount + set winName to item i of wNames + repeat with j from 1 to 20 + try + set t to tab j of window i + set tabTTY to tty of t + set tabBusy to (busy of t as text) + set tabProcs to processes of t + set procList to "" + repeat with p in tabProcs + if procList is not "" then set procList to procList & "," + set procList to procList & (p as text) + end repeat + set output to output & i & "|||" & winName & "|||" & j & "|||" & tabTTY & "|||" & tabBusy & "|||" & procList & lf + on error + exit repeat + end try end repeat end repeat return output