From de7339fe016764aa6ec79a7ab21fc08c1c98eee4 Mon Sep 17 00:00:00 2001 From: Callum McIntyre Date: Thu, 19 Mar 2026 12:02:45 +0000 Subject: [PATCH] Remove heartbeat from exec-based Claude execution Exec sessions stay alive as long as we're connected and for up to an hour after disconnect, so the 20s stderr heartbeat that was needed to keep service-based sprites alive is no longer necessary. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- Wisp/ViewModels/ChatViewModel.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Wisp/ViewModels/ChatViewModel.swift b/Wisp/ViewModels/ChatViewModel.swift index b440859f..0ca800a5 100644 --- a/Wisp/ViewModels/ChatViewModel.swift +++ b/Wisp/ViewModels/ChatViewModel.swift @@ -776,12 +776,7 @@ final class ChatViewModel { } claudeCmd += " '\(escapedPrompt)'" - // Wrap claude with a heartbeat so the sprite stays alive while Claude - // is waiting for an API response and Wisp is detached. The heartbeat - // writes a byte to stderr every 20s — enough to count as output without - // interfering with the NDJSON stdout stream. The trap ensures cleanup. - let wrappedClaudeCmd = "{ (while true; do sleep 20; printf . >&2; done) & HBEAT=$!; trap \"kill $HBEAT 2>/dev/null\" EXIT; \(claudeCmd); kill $HBEAT 2>/dev/null; }" - commandParts.append(wrappedClaudeCmd) + commandParts.append(claudeCmd) let fullCommand = commandParts.joined(separator: " && ") receivedSystemEvent = false