CLI: Esc can dismiss `/side` instead of submitting queued steering, losing side-chat context
What version of Codex CLI is running?
codex-cli 0.130.0
What subscription do you have?
Pro
Which model were you using?
Any
What platform is your computer?
Darwin 24.6.0 arm64 arm
What terminal emulator and version are you using (if applicable)?
Any terminal tested/observed, including Ghostty and VS Code terminal.
Codex doctor report
N/A
What issue are you seeing?
In the CLI, Esc has conflicting meanings while a /side conversation is focused.
If the main thread is working, I can open /side, start work in the side conversation, then submit a queued steering/follow-up prompt while the side conversation is still working. The UI shows the normal queued-message hint saying the message will be submitted after the next tool call, and that pressing Esc will submit it immediately.
However, because the active UI is a /side conversation, pressing Esc returns to the main thread / dismisses the side chat instead of submitting the queued steering prompt. Since /side conversations are ephemeral and currently not stored in session logs, this can lose the side-chat context and the queued prompt. See #20262 for the related persistence issue: https://github.com/openai/codex/issues/20262
There is also a race/bounce problem. If the side-chat work completes just before the user presses Esc, the user's intent is still "submit the queued steer immediately," but the actual action becomes "close the side chat." That makes the same visible user action switch from submitting work to discarding the side conversation based on timing the user cannot reliably perceive.
This is different from cases where Esc is not received by the terminal. Esc is received, but the /side "return to parent" handler appears to win over, or race with, the queued-message "submit immediately" action.
What steps can reproduce the bug?
- Start a Codex CLI session.
- Submit a prompt in the main thread that keeps the main thread working long enough to interact with the UI.
- Run
/sidewhile the main thread is still working. - In the side conversation, submit a prompt that starts work in the side conversation.
- While the side conversation is working, type a steering/follow-up message so the UI shows the queued-message prompt:
Messages to be submitted after next tool call (press esc to interrupt and send immediately)
- Press Esc.
- Observe that Esc can return from/dismiss the side chat instead of submitting the queued side-chat message immediately.
- If the side-chat work completes just before Esc is processed, observe the bounce/race: the same Esc keypress closes
/sideeven though the user pressed it in response to the "submit immediately" hint.
What is the expected behavior?
Esc should not silently choose the lossy /side dismissal behavior when the UI is advertising Esc as "submit immediately" for a queued message.
A reasonable behavior would be:
- If a queued message/steering prompt is pending in the focused side conversation, Esc should submit that queued prompt immediately to the focused side conversation.
- Returning from
/sideshould only happen when there is no pending queued prompt, or should require a separate action such as a second Esc. - If the queued prompt is no longer actionable because the turn completed just before Esc was handled, the CLI should avoid treating that same Esc as an implicit request to close/discard the side chat.
- If leaving
/sidewould discard non-persisted side-chat state, the CLI should avoid data loss: preserve the side chat, make it recoverable, or confirm before discarding unsaved side-chat content.
Additional information
Related but not duplicate issues:
- #20262 asks to store
/sidechats in session logs. This bug is higher severity while/sideremains ephemeral, because an accidental Esc can lose the side-chat context. - #17095 reports Esc not submitting queued messages generally in one terminal. This issue is different: Esc is handled, but it is handled as
/sidedismissal. - #13892 reports queued follow-up / pending steer state confusion in the TUI.
- #21168 is a closed CLI
/side+ Esc issue, but it covered the working timer resetting, not queued-message submission or side-chat data loss. - #21583 covers similar side-chat loss/routing concerns in Desktop, not the CLI
/sideEsc keybinding collision.
7 Comments
This is by design. Side conversations are not intended for substantive work. They're intended for simple side questions. They are limited in what they can do; for example, many slash commands are not available.
I'll change this from a bug report to an enhancement request and keep it open to see if we get similar feedback from other codex users.
I don't mind how this is classified. Bug / Feature. From my perspective the problem here is there's a prompt at the bottom of the screen that says Esc will do one thing (submit a message immediately), but which actually does something else (closes the side chat) which lost actual important work and means that now I can't trust that the UI will do what it says it will do.
This is not a hypothetical situation. I was in the middle of something substantive on an intentional side conversation. Regardless of whether /side is intended to be used this way, the problem of that framing is that it assumes that we will always only know when substantive work happens up front.
Obv. your call on how this works, but perhaps consider disabling the Esc to submit immediately message or something like that to avoid this from being a data loss event.
As a general rule though, I have a strong opinion that all chats with codex should result in a session log, so I'd push back on /side being generally ephemeral being an answer to this from that perspective see https://github.com/openai/codex/issues/20262
Right now, I'm fine with this not being worked on, I know that this bug/feature works this way, so I'd avoid this path as a sharp edge.
/sideis not meant to be used for something substantive. It's meant for quick lightweight questions. If you need to do something substantive and want persistence, there are other tools you can use like/fork.I've encountered a variant of this behaviour that I also find disruptive: I can't interrupt the agent to correct a prompt in a
/sidechat by pressingesc.It seems that
ctrl-candctrl-dboth close the/sidechat, analogously to closing a sub-shell. So perhaps theescbinding could simply be removed in favour of advertising one of those other two bindings?I think the “intended use” framing is doing too much work here.
I understand the argument that
/sideis meant for lightweight questions rather than substantive work, and I’m not trying to litigate whether this is a bug or an enhancement. But “not intended for substantive work” does not fully answer the product problem.A feature can be “not intended for substantive work” and still be badly designed if it invites substantive work and then makes losing it easy.
That is the distinction I think matters here: misuse is different from foreseeable use.
/sideis a chat interface, opened inside the current session, with access to the current context, capable of producing useful work. It is very foreseeable that users will occasionally do something meaningful there, even if that was not the original design intent.“Intended use” defines the happy path, but good product design also accounts for foreseeable use. If a product makes a behavior natural, productive, and only weakly marked as unsafe, then failures in that behavior are not simply user error. They are affordance failures, expectation failures, or data-loss safety failures.
The sharper issue here is that the UI advertises one meaning for Esc, but the focused mode can interpret Esc as something else. In this case, the queued-message hint says Esc will submit the message immediately, but in
/sidethe same key can instead dismiss the side conversation. Because/sideis ephemeral and not stored in the session log, that turns a keybinding ambiguity into a data-loss path.That is not just “the user used
/sidefor the wrong thing.” The product showed a prompt, the user followed the prompt, and the result could be losing work.I think a better product principle is:
Products are responsible not only for intended workflows, but also for foreseeable misuse created by their own affordances.
In this case, any of these would reduce the sharp edge:
/sidechats in the session log/sideis focusedI don’t think this requires making
/sidea full replacement for/fork. It just means the product should not make an ephemeral workspace look and behave like a normal chat, allow valuable work to happen there, and then silently discard it through an ambiguous or timing-sensitive keypress.Put another way: when a product creates an attractive footgun, the injury is not explained away by saying the user pulled the trigger wrong.
We received similar feedback from several other users. This will be addressed in the next release.
I was unconsciously trying to go back to the conversation by pressing Esc, but I was immediately ejected without any notice, which dropped my mood to the bottom. Honestly, if you really want to do it in a semantic conflict, at least give a secondary pop-up window. If the design of the library is not elegant enough, it would be better to pop up a secondary confirmation window on the first press of Esc and then use Y/N to close. I don't think it's necessary to keep the content of side, but the unannounced exit and loss of conversation due to semantic conflict is completely unacceptable. You should understand the importance of this.