Skip to content

[Bug]: Quitting the desktop app still stops SSH-launched servers and kills running turns #27183

Closed as not planned

Description

@harshit97

Splitting this out of #15608, as Theo asked on Oct 21 ("desktop quit still stops the managed remote server"). It's the same lifecycle as #10934, whose triage ended with "Needs a maintainer stamp on that quit-vs-disconnect contract before implementation." That decision never happened.

What I'm asking for: quit (and window close) only closes the port forward. Disconnect, turning the environment off, and Remove stay the ways to stop a server T3 launched. The fix is then small (see "Where I'd start").

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/desktop

Steps to reproduce

  1. Add an SSH environment for a Linux box and let T3 launch the server (Settings → Environments → Add environment → SSH).
  2. Start a turn there that runs for more than a few seconds.
  3. Cmd+Q the desktop app.
  4. Check ~/.t3/ssh-launch/<id>/server.log on the box, or reopen the app and open the thread.

Expected behavior

The remote server keeps running and the turn finishes. Quit closes the port forward, nothing more.

The docs agree: the only documented way to stop a launched server is removing the connection. The #10934 triage said stopping on quit "is stricter than the documented 'remove connection' rule and is what broke long-running remote work."

Actual behavior

About 5 seconds after Cmd+Q, every SSH environment's server shuts down and its running turns are cancelled.

My repro: a Codex turn ran for ~20s, I hit Cmd+Q, and the remote server logged its shutdown 5.8s later with terminalizedRuns: 1. My other two environments went down within a second of it. Reopening the app 3 minutes later restarted all three and posted "Continue where you left off." to the thread. Recovery works, but the agent was dead the whole time, and so was everything else on that server (I also use it from a browser on another machine).

I run agents on a remote box so they keep going when I walk away from the laptop:

To me those all mean "done with the laptop for now." I found out one of them was destructive by losing a turn.

The workaround suggested on #10951, t3 service install, needs systemd or launchd. My box is a container without systemd. Someone else on #10951 said this made remote connections "next to unusable" and that they'd probably switch to Claude Code Desktop for the time being.

Where I'd start

From main at dd14848153:

Impact

Major degradation or frequent failure

Version or commit

Desktop T3 Code (Beta) 0.1.5, remote runtime 0.1.5. Same code on main at dd14848153.

Environment

macOS 26.7.1, three SSH environments on Debian 12 (x86_64), Codex CLI 0.166.0.

Logs

# times relative to Cmd+Q
T+0.0s    desktop    desktop.lifecycle.startWaitingForShutdown
T+4.9s    host C     V2 orchestration shutdown reconciliation completed   terminalizedRuns: 0
T+5.2s    host B     V2 orchestration shutdown reconciliation completed   terminalizedRuns: 0
T+5.8s    host A     V2 orchestration shutdown reconciliation completed   terminalizedRuns: 1
T+5.8s    host A     provider-runtime.continue queued; run 1 cancelled (turn started ~19s before quit)

# after reopening the app
T+189.6s  host A, B  Listening on http://127.0.0.1:3773
T+189.8s  host C     Listening on http://127.0.0.1:3773
T+190.2s  host A     provider-runtime.continue ran, run 2 started

Workaround

Start the server on the box yourself before the desktop connects. The desktop adopts it as "external" and never stops it:

nohup env T3CODE_NO_BROWSER=1 ~/.t3/runtime/versions/0.1.5/t3 serve --host 127.0.0.1 --port 3773 --base-dir ~/.t3 >> ~/.t3/manual-serve.log 2>&1 < /dev/null &

The catch: desktop updates no longer update it, and nothing restarts it after a reboot.

Related: #10934 and #15608 (same bug, closed), #10951 (closed fix), #14268 (forward leak on update, a different path), #26948 (a separate launcher bug I filed).

Activity

  1. juliusmarminge commented on Nov 12, 2026

    @juliusmarminge
    Member

    I tried to reproduce this on the current build and could not.

    Commit ed54f30 (origin/main). Ran the real desktop app on Linux: T3CODE_DEV_SEED=0 headless-desktop vp run dev:desktop, with ssh on PATH wrapping a private ssh config that points at an isolated local sshd (127.0.0.1:2299, remote HOME in a scratch dir) and T3CODE_DEV_REMOTE_T3_SERVER_ENTRY_PATH set to the checkout's apps/server/src/bin.ts. In Settings → Connections → Add environment → SSH I entered the host alias and clicked Add environment; the desktop launched a managed remote server (ssh-launch//managed = managed, PID 38690, listening on 127.0.0.1:3774). Then I closed the window, which quits the app on Linux, the platform path the reporter says is also affected. The desktop logged before-quit received and Electron exited, but the remote server was still alive 60 s later. sshd logged no new session after quit, so no stop command was sent, and the remote server.log shows no shutdown. Relaunching reused PID 38690; a second clean relaunch-then-quit gave the same result (server alive at T+60 s, no stop attempt). On this build Electron exits before the SSH manager layer is released: DesktopApp.ts marks shutdown complete in the program scope and the lifecycle calls app.quit, so the tunnel finalizer's stopRemoteServer never runs. The reporter's macOS packaged 0.1.5 build reached it about 5 s after Cmd+Q; I had no macOS or packaged build to confirm that timing. At package level the behaviour is real: extending the 'waits for %s shutdown before reconnecting the same target' test in packages/ssh/src/tunnel.test.ts to assert stops === 1 and remoteRunning after the manager layer is released fails on main for both rows (stops is 2), because the entry finalizer stops the remote server on manager teardown.

    Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions