#!/usr/bin/env swift // winctx — print the frontmost app + focused-window title as JSON, for autotrack. // // Uses the Accessibility (AX) API, which exposes window titles that AppleScript's // "System Events … name of front window" misses for many apps (Electron, some // native apps). Falls back to an empty title when AX is denied or the app has // none — the daemon then tries its osascript path. // // Output: {"app":"","title":""} // Requires Accessibility permission (System Settings → Privacy → Accessibility) // for the process that runs it; without it, title comes back empty (app still works). import Cocoa import ApplicationServices func jsonEsc(_ s: String) -> String { var o = "" for u in s.unicodeScalars { switch u { case "\"": o += "\\\"" case "\\": o += "\\\\" case "\n": o += "\\n" case "\r": o += "\\r" case "\t": o += "\\t" default: if u.value < 0x20 { o += String(format: "\\u%04x", u.value) } else { o.unicodeScalars.append(u) } } } return o } func focusedTitle(_ pid: pid_t) -> String { let axApp = AXUIElementCreateApplication(pid) var winRef: CFTypeRef? guard AXUIElementCopyAttributeValue(axApp, kAXFocusedWindowAttribute as CFString, &winRef) == .success, let win = winRef else { return "" } var titleRef: CFTypeRef? guard AXUIElementCopyAttributeValue(win as! AXUIElement, kAXTitleAttribute as CFString, &titleRef) == .success, let t = titleRef as? String else { return "" } return t } guard let app = NSWorkspace.shared.frontmostApplication else { print("{\"app\":\"\",\"title\":\"\"}") exit(0) } let name = app.localizedName ?? "" let title = focusedTitle(app.processIdentifier) print("{\"app\":\"\(jsonEsc(name))\",\"title\":\"\(jsonEsc(title))\"}")