app-server remote mode: no way to shut down a remote TUI gracefully from the server side (always exits non-zero on server-initiated close)
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- rust
- Domain
- cli, networking
Research direction
Start in codex-rs/app-server-client/src/remote.rs around line 409, where server WebSocket close messages are mapped to a disconnect error, and inspect how the close code is handled. Reproduce the behavior with the app-server and remote TUI commands from the issue, then verify that a server-side normal close (code 1000) ends the TUI with exit code 0 rather than 1.
Written by the indexing model from the issue text.
Description
Motivation
We run codex app-server (WebSocket listen) under a supervisor, with human-facing codex --remote ws://… TUIs attached to it. Each TUI console window is wrapped so that exit code 0 closes the window and non-zero keeps it open for diagnosis (startup failures stay readable).
When the supervisor intentionally stops the app-server stack, the remote TUI can only observe its socket closing, and it always exits non-zero — indistinguishable from a crash or a startup failure. As far as we can tell there is no way for the server side to end a remote TUI session cleanly.
Current behavior (codex-cli 0.146.0; same on current main)
- A server-initiated WebSocket close is treated as an error regardless of close code:
codex-rs/app-server-client/src/remote.rsmapsMessage::Close(frame)unconditionally toAppServerEvent::Disconnected/ErrorKind::ConnectionAborted; the close code is never inspected (onlyframe.reasonis used for the message text). - Verified empirically with 0.146.0: closing the connection from the server side with close code 1000 (reason "driver stopping"), or with no code at all, makes the TUI exit 1 in both cases. Exit 0 happens only for client-initiated shutdown (quit / Ctrl+C).
Request
Either of these would solve it:
- Treat a normal closure (WebSocket close code 1000) as a graceful end of session: the remote TUI shuts down and exits 0; or
- Add a server→client notification (e.g.
shutdown) that instructs the client to terminate cleanly.
Why it matters
Wrapper tooling around the TUI relies on the exit code to distinguish "intended shutdown" (safe to auto-close the console window) from "abnormal disconnect / startup failure" (keep the window for diagnosis). With the current behavior, every server-side stop leaves a stale error window behind, and its exit code (1) collides with genuine startup failures, so the two cases cannot be told apart.
Repro sketch
codex app-server --listen ws://127.0.0.1:7461 --ws-auth capability-token --ws-token-file <f>- Attach a TUI through a trivial pass-through WS forwarder listening on 7462:
codex --remote ws://127.0.0.1:7462 --remote-auth-token-env TOKEN_ENV - From the forwarder, close the downstream socket with close code 1000 → the TUI exits 1 (same as with no close code).
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- Avg merge
- 1m
- Merged PRs (30d)
- 1k
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openai/codex
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
bug CLI windows-os
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
macOS sandbox blocks hw.optional.arm64 sysctl, causing Flutter to misdetect Apple Silicon as x64 Openbug CLI sandbox
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug CLI TUI
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
CLI config enhancement skills
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
kwakseongjae/auto-hwp#319 ·
-
area:cli bug filter-quality good first issue priority:medium
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 1/5 Under an hour Newbie friendliness 72/100
bevyengine/bevy#25861 ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
A-linter
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
oxc-project/oxc#26863 ·