#!/usr/bin/env python3 """Cursor hook script that notifies the cursor-flasher daemon via Unix socket. Installed as a Cursor hook to trigger a window flash when the agent needs user attention. Reads hook JSON from stdin, extracts workspace and event info, and sends it to the daemon's socket. Shell-specific hook mapping (beforeShellExecution -> shellApproved, afterShellExecution -> shellCompleted) is retained but currently dead code — those hooks are disabled in HOOKS_CONFIG / hooks.json because beforeShellExecution fires pre-approval and Cursor expects a JSON response we don't provide. """ import json import os import socket import sys SOCKET_PATH = os.path.expanduser("~/.cursor-flasher/flasher.sock") _SHELL_EVENT_MAP = { "beforeShellExecution": "shellApproved", "afterShellExecution": "shellCompleted", } def main() -> None: try: data = json.load(sys.stdin) except (json.JSONDecodeError, ValueError): return workspace_roots = data.get("workspace_roots") or [] workspace = workspace_roots[0] if workspace_roots else "" event = data.get("hook_event_name", "") mapped_event = _SHELL_EVENT_MAP.get(event) if mapped_event: msg = json.dumps({"workspace": workspace, "event": mapped_event, "tool": "Shell"}) else: tool = data.get("tool_name", "") msg = json.dumps({"workspace": workspace, "event": event, "tool": tool}) try: s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) s.settimeout(1) s.connect(SOCKET_PATH) s.sendall(msg.encode()) s.close() except (ConnectionRefusedError, FileNotFoundError, OSError): pass if __name__ == "__main__": main()