Autocomplete “no match” menu intercepts Enter for ! shell commands
What version of Codex CLI is running?
Codex CLI 0.145.0
What subscription do you have?
Chat GPT pro
Which model were you using?
gpt 5.6 Sol
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64
What terminal emulator and version are you using (if applicable)?
Windows Powershell
Codex doctor report
{
"schemaVersion": 1,
"generatedAt": "1784769061s since unix epoch",
"overallStatus": "ok",
"codexVersion": "0.145.0",
"checks": {
"app_server.status": {
"id": "app_server.status",
"category": "app-server",
"status": "ok",
"summary": "background server is not running",
"details": {
"control socket": "C:\\Users\\HyuN\\.codex\\app-server-control\\app-server-control.sock",
"daemon state dir": "C:\\Users\\HyuN\\.codex\\app-server-daemon",
"mode": "ephemeral",
"pid file": "C:\\Users\\HyuN\\.codex\\app-server-daemon\\app-server.pid (missing)",
"settings": "C:\\Users\\HyuN\\.codex\\app-server-daemon\\settings.json (missing)",
"status": "not running",
"update-loop pid file": "C:\\Users\\HyuN\\.codex\\app-server-daemon\\app-server-updater.pid (missing)"
},
"remediation": null,
"durationMs": 0
},
"auth.credentials": {
"id": "auth.credentials",
"category": "auth",
"status": "ok",
"summary": "auth is configured",
"details": {
"auth file": "C:\\Users\\HyuN\\.codex\\auth.json",
"auth storage mode": "File",
"stored API key": "false",
"stored ChatGPT tokens": "true",
"stored agent identity": "false",
"stored auth mode": "chatgpt"
},
"remediation": null,
"durationMs": 0
},
"config.load": {
"id": "config.load",
"category": "config",
"status": "ok",
"summary": "config loaded",
"details": {
"CODEX_HOME": "C:\\Users\\HyuN\\.codex",
"config.toml": "C:\\Users\\HyuN\\.codex\\config.toml",
"config.toml parse": "ok",
"cwd": "D:\\codex\\snake",
"enabled feature flags": "<redacted>",
"feature flag overrides": "none",
"feature flags enabled": "36",
"log dir": "C:\\Users\\HyuN\\.codex\\log",
"mcp servers": "0",
"model": "<default>",
"model provider": "openai",
"sqlite home": "C:\\Users\\HyuN\\.codex"
},
"remediation": null,
"durationMs": 0
},
"git.environment": {
"id": "git.environment",
"category": "git",
"status": "ok",
"summary": "git version 2.53.0.windows.2",
"details": {
".git entry": "directory",
"PATH git #1": "C:\\Program Files\\Git\\cmd\\git.exe",
"PATH git entries": "1",
"git build options": "git version 2.53.0.windows.2; cpu: x86_64; built from commit: e9edee0b34751bf4d7d1feda0e2535bff64d4e77; sizeof-long: 4; sizeof-size_t: 8; shell-path: D:/git-sdk-64/usr/bin/sh; rust: disabled; feature: fsmonitor--daemon; gettext: enabled; libcurl: 8.18.0; OpenSSL: OpenSSL 3.5.5 27 Jan 2026; zlib: 1.3.1; SHA-1: SHA1_DC; SHA-256: SHA256_BLK; default-ref-format: files; default-hash: sha1",
"git exec path": "C:/Program Files/Git/mingw64/libexec/git-core",
"git version": "git version 2.53.0.windows.2",
"repo detected": "true",
"repo root": "D:\\codex\\snake",
"selected git": "C:\\Program Files\\Git\\cmd\\git.exe"
},
"remediation": null,
"durationMs": 66
},
"installation": {
"id": "installation",
"category": "install",
"status": "ok",
"summary": "installation looks consistent",
"details": {
"PATH codex #1": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\codex",
"PATH codex #2": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\codex.cmd",
"PATH codex entries": "2",
"current executable": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\bin\\codex.exe",
"install context": "npm (package C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc, bin C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\bin, resources C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\codex-resources, path C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\codex-path)",
"managed by bun": "false",
"managed by npm": "true",
"managed by pnpm": "false",
"managed package root": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex",
"npm update target": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex"
},
"remediation": null,
"durationMs": 217
},
"mcp.config": {
"id": "mcp.config",
"category": "mcp",
"status": "ok",
"summary": "no MCP servers configured",
"details": {},
"remediation": null,
"durationMs": 0
},
"network.env": {
"id": "network.env",
"category": "network",
"status": "ok",
"summary": "network-related environment looks readable",
"details": {
"proxy env vars present": "HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy"
},
"remediation": null,
"durationMs": 0
},
"network.provider_reachability": {
"id": "network.provider_reachability",
"category": "reachability",
"status": "ok",
"summary": "active provider endpoints are reachable over HTTP",
"details": {
"ChatGPT base URL": "https://chatgpt.com/backend-api/ reachable (HTTP 403)",
"reachability mode": "ChatGPT auth"
},
"remediation": null,
"durationMs": 748
},
"network.websocket_reachability": {
"id": "network.websocket_reachability",
"category": "websocket",
"status": "ok",
"summary": "Responses WebSocket handshake succeeded",
"details": {
"DNS": "1 IPv4, 1 IPv6, first IPv6",
"auth mode": "chatgpt",
"connect timeout": "15000 ms",
"endpoint": "wss://chatgpt.com/backend-api/<redacted>",
"handshake result": "HTTP 101 Switching Protocols",
"model provider": "openai",
"models etag present": "true",
"provider name": "OpenAI",
"proxy env vars present": "HTTP_PROXY, HTTPS_PROXY, http_proxy, https_proxy",
"reasoning header": "false",
"server model present": "false",
"supports websockets": "true",
"wire API": "responses"
},
"remediation": null,
"durationMs": 1879
},
"runtime.provenance": {
"id": "runtime.provenance",
"category": "runtime",
"status": "ok",
"summary": "running npm on windows-x86_64",
"details": {
"commit": "unknown",
"current executable": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\bin\\codex.exe",
"install method": "npm (package C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc, bin C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\bin, resources C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\codex-resources, path C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\codex-path)",
"platform": "windows-x86_64",
"version": "0.145.0"
},
"remediation": null,
"durationMs": 0
},
"runtime.search": {
"id": "runtime.search",
"category": "search",
"status": "ok",
"summary": "search is OK (bundled)",
"details": {
"search command": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex\\node_modules\\@openai\\codex-win32-x64\\vendor\\x86_64-pc-windows-msvc\\codex-path\\rg.exe",
"search command readiness": "file exists",
"search provider": "bundled"
},
"remediation": null,
"durationMs": 0
},
"sandbox.helpers": {
"id": "sandbox.helpers",
"category": "sandbox",
"status": "ok",
"summary": "sandbox configuration is readable",
"details": {
"approval policy": "OnRequest",
"codex-linux-sandbox helper": "none",
"execve wrapper helper": "none",
"filesystem sandbox": "restricted",
"network sandbox": "restricted"
},
"remediation": null,
"durationMs": 0
},
"state.paths": {
"id": "state.paths",
"category": "state",
"status": "ok",
"summary": "state paths and databases are inspectable",
"details": {
"CODEX_HOME": "C:\\Users\\HyuN\\.codex (dir)",
"active rollout files": "19 files, 15312689 total bytes, 805931 average bytes",
"archived rollout files": "0 files, 0 total bytes, 0 average bytes",
"goals DB": "C:\\Users\\HyuN\\.codex\\goals_1.sqlite (file)",
"goals DB integrity": "ok",
"log DB": "C:\\Users\\HyuN\\.codex\\logs_2.sqlite (file)",
"log DB integrity": "ok",
"log dir": "C:\\Users\\HyuN\\.codex\\log (missing)",
"memories DB": "C:\\Users\\HyuN\\.codex\\memories_1.sqlite (file)",
"memories DB integrity": "ok",
"sqlite home": "C:\\Users\\HyuN\\.codex (dir)",
"state DB": "C:\\Users\\HyuN\\.codex\\state_5.sqlite (file)",
"state DB integrity": "ok",
"thread history DB": "C:\\Users\\HyuN\\.codex\\thread_history_1.sqlite (missing)",
"thread history DB integrity": "skipped (missing)"
},
"remediation": null,
"durationMs": 122
},
"state.rollout_db_parity": {
"id": "state.rollout_db_parity",
"category": "threads",
"status": "ok",
"summary": "rollout files and state DB thread inventory agree",
"details": {
"default model provider": "openai",
"rollout DB active files": "19",
"rollout DB active rows": "19",
"rollout DB archive mismatches": "0",
"rollout DB archived files": "0",
"rollout DB archived rows": "0",
"rollout DB duplicate DB paths": "0",
"rollout DB duplicate rollout thread ids": "0",
"rollout DB malformed file names": "0",
"rollout DB missing active rows": "0",
"rollout DB missing archived rows": "0",
"rollout DB model providers": "openai=19",
"rollout DB rows": "19",
"rollout DB scan cap reached": "false",
"rollout DB scan errors": "0",
"rollout DB sources": "cli=16, subagent:review=2, vscode=1",
"rollout DB stale rows": "0"
},
"remediation": null,
"durationMs": 53
},
"system.environment": {
"id": "system.environment",
"category": "system",
"status": "ok",
"summary": "OS language zh-CN",
"details": {
"EDITOR": "not set",
"VISUAL": "not set",
"os": "Windows 10.0.26200 (Windows 11 CoreCountrySpecific) [64-bit]",
"os language": "zh-CN",
"os type": "Windows",
"os version": "10.0.26200"
},
"remediation": null,
"durationMs": 0
},
"terminal.env": {
"id": "terminal.env",
"category": "terminal",
"status": "ok",
"summary": "terminal metadata was detected",
"details": {
"WT_SESSION": "present",
"color output": "disabled (stdout is not a terminal)",
"console input code page": "936",
"console output code page": "936",
"stderr console mode": "unavailable",
"stderr is terminal": "false",
"stdin is terminal": "false",
"stdout console mode": "unavailable",
"stdout is terminal": "false",
"terminal": "Windows Terminal",
"terminal size": "120x30"
},
"remediation": null,
"durationMs": 0
},
"terminal.title": {
"id": "terminal.title",
"category": "title",
"status": "ok",
"summary": "terminal title default",
"details": {
"terminal title activity": "true",
"terminal title items": "activity, project-name",
"terminal title project source": "git repo root",
"terminal title project value": "snake",
"terminal title source": "default"
},
"remediation": null,
"durationMs": 0
},
"updates.status": {
"id": "updates.status",
"category": "updates",
"status": "ok",
"summary": "update configuration is locally consistent",
"details": {
"cached latest version": "0.145.0",
"check for update on startup": "true",
"last checked at": "2026-07-22T07:31:02.891754500Z",
"latest version": "0.145.0",
"latest version status": "current version is not older",
"npm update target": "C:\\Users\\HyuN\\AppData\\Roaming\\npm\\node_modules\\@openai\\codex",
"update action": "npm install -g @openai/codex",
"version cache": "C:\\Users\\HyuN\\.codex\\version.json"
},
"remediation": null,
"durationMs": 1903
}
}
}
What issue are you seeing?
In Codex CLI on Windows, entering a shell command such as:
!echo $env:HTTP_PROXY
opens the autocomplete menu and displays “no match”. While this menu is open,
pressing Enter does nothing—the command is not executed.
It appears that the autocomplete menu intercepts Enter as a candidate-selection
action even though there are no candidates. Moving the cursor back near the
leading “!” changes the menu state, after which Enter executes the command
normally.
What steps can reproduce the bug?
Uploaded thread: 019f8aae-062e-7a52-9378-cf0d9f25275c
What is the expected behavior?
When a prompt starts with “!”, Codex CLI should recognize it as a shell command.
If the autocomplete menu has no matching candidates, it should close or stop
capturing keyboard input.
Pressing Enter should submit and execute the shell command without requiring the
cursor to be moved back near the leading “!” character.
Additional information
_No response_
2 Comments
Analysis (community)
Thanks for the clear repro - the symptoms line up tightly with the composer's skill-popup key handling.
0.145.0, Windows, Windows Terminal. Analysis against currentmain(codex-rs/tui, static read only; not a live Windows re-run on my side).!echo $env:HTTP_PROXY-> "no matches" menu -> Enter does nothing; moving the cursor near the leading!clears the menu and Enter works) matches the control flow below. Happy to correct anything if maintainers see a different popup path (e.g. mentions v2).$env:…, plain Enter neither inserts nor submits; the draft stays put.!shell draft (same contract as file / unified-mention popups when nothing is selected).Root-cause hypothesis
Two cooperating pieces, both in
codex-rs/tui:$env:…is treated as a completable$skill querycompletion_target::dollar_query_kind(codex-rs/tui/src/bottom_pane/chat_composer/completion_target.rs) classifies a name asShellVariableonly when it is all non-lowercase andis_common_env_var(codex-rs/tui/src/mention_codec.rs:PATH/HOME/USER/ … only).$env:HTTP_PROXY, the name segment includes lowercaseenv(and:is allowed in the name scan), so it falls through toDollarQueryKind::Completablerather than shell syntax.ChatComposer::current_mention_target+sync_mention_popupopenActivePopup::Skill. Empty filter render iscodex-rs/tui/src/bottom_pane/skill_popup.rs->render_rows_single_line(..., "no matches").home:searchcompletable (completion_target_tests.rs::dollar_query_classifies_shell_and_skill_syntax), so a blunt "no colons" rule would be wrong.ChatComposer::handle_key_event->ActivePopup::Skill->handle_key_event_with_skill_popup, then alwayssync_popups().handle_key_event_with_skill_popupoptionally insertsselected_mention(), setsactive = None, and returns(InputResult::None, true)- no call tohandle_key_event_without_popup.sync_popups()immediately reopensActivePopup::Skillbecause the$…token is still active -> Enter appears to do nothing.$token (e.g. toward!/ start of the shell draft) clears the target, so Enter can submit - matches the report.Contrast (intended contract already elsewhere):
handle_key_event_with_file_popup: no selection + Enter ->active = Nonethenreturn self.handle_key_event_without_popup(key_event); Tab stays close-only.handle_key_event_with_mentions_v2_popup: Enter setssubmit_without_popup = selected.is_none()and, after close,return self.handle_key_event_without_popup(key_event).enter_submits_when_file_popup_has_no_selectionandenter_submits_when_unified_mention_popup_has_no_selectionincodex-rs/tui/src/bottom_pane/chat_composer.rs. There is no skill-popup counterpart.Slash-command popups are already gated with
!self.draft.is_bash_modeinsync_popups; the legacy$skill path is not, which is why!shell drafts still surface skill autocomplete.High-level fix outline (not a PR)
Primary (small, preferred): In
handle_key_event_with_skill_popup, on plain Enter whenselected_mention()isNone, setactive = Noneandreturn self.handle_key_event_without_popup(key_event)- same contract as File / MentionV2 - so!shell drafts (and ordinary prompts with an empty skill menu) submit. Keep Tab as close-only without submit if that remains existing Tab semantics for this popup.Optional secondary (separate change, needs product alignment):
dollar_query_kindthat PowerShell-style$env:/$Env:prefixes are non-completable shell syntax (narrow prefix rule), without breaking intentional skill names that use:(e.g.home:search).$skill popups whiledraft.is_bash_mode(parallel to slash-popup bash gating).Non-goals / risks: Do not change File / MentionV2 fallthrough, slash-popup bash gating, or
RunUserShellCommandsubmission itself. Enter fallthrough looks low-risk and aligns with existing tests. Classification changes must not hide real skills; bash-mode popup suppression is a product call more than a pure bugfix.Test ideas
Fail-first unit tests next to the existing file/mention_v2 cases in
codex-rs/tui/src/bottom_pane/chat_composer.rs:enter_submits_when_skill_popup_has_no_selection-set_skill_mentionswith unrelated skills, insert$env:HTTP_PROXYor$zzzz-no-skill,sync_popupsassertsActivePopup::Skill, Enter ->InputResult::Submittedwith unchanged draft text.enter_submits_bang_shell_command_when_skill_popup_empty- same idea with a leading!/ bash-mode draft matching the reporter command.dollar_query_kind("env:HTTP_PROXY")is not completable and that token does not open a skill popup; keephome:searchcompletable.Questions for maintainers
$skill completion be disabled entirely inis_bash_mode(like slash commands), or only fixed at the Enter fallthrough layer?$env:/$Env:shell-syntax exception acceptable given skill names may use:?KeyModifiers != NONE) worth treating as a secondary path, or is the plainNONEpath sufficient given the reporter's "no matches" + cursor-move behavior?mentions_enabled-> Skill popup)? Was mentions v2 in play (would prefer@paths, not$skill)?Happy to refine this analysis with more pointers or adjust the outline if any of the above is off. If the team later wants an invited PR along an agreed approach, I'd be glad to help - no rush either way.
Building on the root-cause analysis above (which already traced the skill-popup Enter close-without-submit and the File/MentionV2 fallthrough), here is the commit archaeology pinning the divergence and current line pins. Traced against
mainas of5dd992a(2026-07-24).What #23363 changed, precisely - and what it did not.
git log -S "submit_without_popup" -- codex-rs/tui/src/bottom_pane/chat_composer.rsreturns a single commit:6c1215dac/ #23363 (2026-05-28, "TUI: Unified mentions tweaks + polish mentions rendering"). #23363 introduced thesubmit_without_popupfallthrough inhandle_key_event_with_mentions_v2_popupso Enter with no selection submits the draft instead of just closing the popup. The file popup already had Enter-fallthrough before #23363: the parent6c1215dac^still haslet Some(sel) = popup.selected_match() else { ... self.handle_key_event_without_popup(key_event) }(then atchat_composer.rs:1820-1823). #23363 did not change the skill popup's Enter/no-selection handling (it added only a doc comment tohandle_key_event_with_skill_popup).Reframing - #23363 did not introduce the inconsistency; it elevated MentionV2. The skill popup handler has always closed-on-Enter-without-submitting. It was introduced in
9a50a0440/ #7506 ("Support listing and selecting skills via $ or /skills") and later moved/renamed via #14717 / #15922 / #16104. The file popup has had Enter-fallthrough for longer than #23363. So the skill popup was already inconsistent with the file popup before #23363; #23363 added the same fallthrough to MentionV2, leaving the skill popup as the remaining incomplete port among the File/Skill/MentionV2 token-completion siblings. (The slash/command popup also falls through on Enter with no selection, so this "outlier" scope is File/Skill/MentionV2.) The bug is latent until mentions/skills are enabled soActivePopup::Skillopens.Line pins (as of
5dd992a), still unfixed.handle_key_event_with_skill_popupis atchat_composer.rs:2063; itsTab|Enterarm (:~2113-2126) on no selection doesclose_popup = true; (InputResult::None, true)and never callshandle_key_event_without_popup. The file popup's contract to mirror is atchat_composer.rs:2040-2046(self.popups.active = ActivePopup::None; return if key_event.code == KeyCode::Enter { self.handle_key_event_without_popup(key_event) } else { (InputResult::None, true) }). The no-selection branch of the skill popup'sTab|Enterarm is the one-region fix target.Not fixed on
main. The only commit touchingchat_composer.rssince the issue date (2026-07-23) is5b40227/ #35012 "Expose remote skill icon URLs through app server" (icon-URL plumbing, not Enter handling).skill_popup.rs's most recent commit is #33232 (2026-07-15, "Disambiguate skill mentions from shell parameters" - before the report, and unrelated to Enter handling).