Output to vscode.Pseudoterminal stops after some time (5 minutes, even up to an hour)

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

I’m using the Extension API vscode.Pseudoterminal for displaying output from my extensions. It has worked fine for years, but recently started to misbehave such that: Output first is arriving just fine in the terminal, but after some different amount of time (most often within an hour) output stops arriving .

Also , my extensions keep track of when the terminal is closed using Pseudoterminal.close(). When a terminal has stopped displaying output, this handler also stops receiving calls. (onDidCloseTerminal seems to keep working.)

In VS Code, Version: 1.128.0-insider, I can’t reproduce the issue.

Steps to Reproduce

  1. Have an extension open a pseudo terminal
  2. Start a heartbeat output to the terminal, say every minute

An easy way to do this is to install the Joyride extension, issue the command Joyride: Run Clojure Code…, and paste this:

(require '["vscode" :as vscode])

(let [!seq (atom 0)
      !interval (atom nil)
      emitter (vscode/EventEmitter.)
      fire! (fn []
              (let [n @!seq]
                (swap! !seq inc)
                (.fire emitter (str "beat " n "  " (.toISOString (js/Date.)) "\r\n"))))
      pty #js {:onDidWrite (.-event emitter)
               :open (fn [_]
                       (fire!)
                       (when-not @!interval
                         (reset! !interval (js/setInterval fire! 60000))))
               :close (fn []
                        (when-let [id @!interval]
                          (js/clearInterval id)
                          (reset! !interval nil))
                        (vscode/window.showInformationMessage
                         "PTY heartbeat: Pseudoterminal.close()"))
               :handleInput (fn [_] nil)}
      term (vscode/window.createTerminal #js {:name "PTY heartbeat" :pty pty})]
  (.show term true)
  (.onDidCloseTerminal vscode/window
                       (fn [t]
                         (when (identical? t term)
                           (vscode/window.showInformationMessage
                            "PTY heartbeat: onDidCloseTerminal"))))
  :started)

(You can also ask the agent to run the code for you.)

Expected Behavior

We expect the pseudo terminal to keep displaying the heartbeats, indefinitely. And when the terminal is closed/killed, we expect two info message boxes, saying it was closed.

Instead, it stops displaying heartbeats after a while. And after it has stopped like this, closing/kiling it will only show the message box fromonDidCloseTerminal.

Operating System

MacOS

Version Information

Version: 3.17.8
VS Code Extension API: 1.128.0
Commit: 2fdd31c9f33f7fbe501f2d57772dc5bf64b63620
Date: 2026-08-20T02:18:12.724Z
Layout: IDE
Build Type: Stable
Release Track: Default
Electron: 40.10.3
Chromium: 144.0.7559.236
Node.js: 24.15.0
V8: 14.4.258.32-electron.0
xterm.js: 6.1.0-beta.291
OS: Darwin arm64 25.5.0

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey @PEZ, thanks for the report and the ready-to-run repro, and apologies for the slow reply.

We think we’ve tracked down what’s going on. The pseudoterminal’s connection to the renderer is getting torn down when Cursor recycles one of its internal helper processes, which happens when a window has been unfocused and idle for around 30 minutes (and occasionally when one of those processes restarts on its own). After that point, output and the close() callback stop being delivered, even though the terminal stays open. This is Cursor-specific, which is why you couldn’t reproduce it in VS Code.

In the meantime, two things help: keeping the window focused while you need the output, and closing and re-creating the terminal after it has gone quiet (a fresh terminal works again until the next time it happens). Handling onDidCloseTerminal as you already do is the right fallback for cleanup.

One thing that would confirm we’re looking at the same trigger: does the stall line up with the window having been in the background for 30 minutes or more? And when it has stalled, does typing into the terminal still reach your handleInput?

Thanks for looking in to this! :folded_hands:

I haven’t noticed a correlation with the window in the background or not. Also, sometimes it stops working after only a few minutes, sometimes (or one time, rather) runs for up to five hours.

I haven’t reproed the issue in development yet. But it should be fairly easy to add that input handler test to the Joyride code above. I seem to recall from my previous checks that I don’t see an echo of the characters I type in the pseudoterminal when it has stopped outputting, but that could be that it has stopped outputting rather than that the handler isn’t hit…