From 38226fea2c8f9d77a41fb6191369dcf4cc4e53e6 Mon Sep 17 00:00:00 2001 From: Alan Wizemann Date: Fri, 24 Apr 2026 02:54:22 +0200 Subject: [PATCH] fix(nous): force PYTHONUNBUFFERED=1 so device-code output surfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sign-in sheet was stuck on the "Contacting Nous Portal…" spinner even though hermes was running correctly. Root cause: Python block-buffers stdout when it's a pipe instead of a TTY, and `hermes auth add nous` enters a 15-minute polling loop after printing the device-code block without ever calling `input()` — so nothing flushes the buffer. Our readability handler never receives the URL + user_code lines. PKCE doesn't hit this because hermes calls `input("Authorization code: ")`, which flushes stdout before blocking. Device-code has no equivalent trigger. Setting PYTHONUNBUFFERED=1 in the subprocess environment forces line-buffered stdout for the duration of the flow — the device-code block surfaces immediately, our regex extracts the URL and code, and the sheet transitions into the waitingForApproval state as intended. Local-only fix; remote SSH contexts get the remote's login env untouched (the user's remote shell config owns buffering behavior there). Co-Authored-By: Claude Opus 4.7 (1M context) --- scarf/scarf/Core/Services/NousAuthFlow.swift | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scarf/scarf/Core/Services/NousAuthFlow.swift b/scarf/scarf/Core/Services/NousAuthFlow.swift index 640bd60..770bab3 100644 --- a/scarf/scarf/Core/Services/NousAuthFlow.swift +++ b/scarf/scarf/Core/Services/NousAuthFlow.swift @@ -68,7 +68,22 @@ final class NousAuthFlow { if !context.isRemote { // Only enrich env locally — remote ssh gets the remote login env // naturally, and exporting our local keys into it would be wrong. - proc.environment = HermesFileService.enrichedEnvironment() + var env = HermesFileService.enrichedEnvironment() + // Python block-buffers stdout when it's a pipe (not a TTY). The + // device-code flow prints the verification URL + user code, then + // enters a ~15-minute polling loop that never hits `input()` — + // so nothing flushes and our readability handler never sees the + // output. Users see the sheet spinning forever while hermes is + // actually waiting for approval. + // + // PKCE doesn't have this problem because `input("Authorization + // code: ")` flushes stdout before blocking, which is why + // OAuthFlowController works without this setting. + // + // PYTHONUNBUFFERED forces line-buffered stdout for the whole + // subprocess — tiny perf cost, huge UX win for device-code. + env["PYTHONUNBUFFERED"] = "1" + proc.environment = env } let outPipe = Pipe()