Where does the bug appear (feature/product)?
Cursor CLI
Describe the Bug
cli on windows freezes after hitting ESC or q from the /mdp list menu
Steps to Reproduce
Reproduction
/mcp list
- Run
agentto start interactive mode - Type
/mcp list - The MCP server list renders correctly (navigation with arrow keys works)
- Press Esc, q, or Ctrl+C to close the pager
- Result: Agent is frozen. No keyboard input is accepted. Must kill the terminal.
/skills
- Run
agentto start interactive mode - Type
/skills, select a skill, let it run - When the skill finishes and the agent should prompt for input
- Result: Agent is frozen.
Expected Behavior
Expected: Pager/overlay closes and the agent prompt resumes accepting input.
Operating System
Windows 10/11
Version Information
Environment
- Agent version:
[email protected](latest as of 2026-03-05) - Node.js: v24.5.0 (bundled)
- OS: Windows 10 22631
- Terminal: Windows Terminal
- Shell: PowerShell 5.1 and PowerShell 7.5.4 (same behavior in both)
Additional Information
used claude opus 4.6 high thinking to diagnose this, here what it said:
Root Cause Analysis
Reverse-engineered from the minified bundle (434.index.js).
The deferred transition wrapper (ln) in src/run-agent.tsx
All overlay onClose handlers route through ln():
ln = useCallback((callback) => {
const { promise, resolve } = Promise.withResolvers();
tn(true); // Step 1: set transition flag (disables ALL UI rendering)
setTimeout(() => {
callback(); // Step 2a: execute state change (hide overlay)
clearScreen(stdout); // Step 2b: write \x1b[H\x1b[2J\x1b[3J
setTimeout(() => {
tn(false); // Step 3: clear transition flag (should re-enable UI)
resolve();
}, 10);
}, 10);
return promise;
}, [stdout]);
Why it freezes
The main prompt/chat UI only renders when ALL of these flags are false:
!en && !_n && !Yn && !ro && !Vn && !to && "chat" === viewMode
en is the transition flag controlled by tn(). During the deferred transition:
tn(true)setsen = true– all UI stops rendering, all InkuseInputhandlers deactivate- The overlay’s
useInputhooks deregister from stdin (component unmounts) - After 10ms+10ms,
tn(false)setsen = false– Ink should re-render and reactivate the prompt’suseInput
On Windows, step 3 fails: Ink does not re-attach the stdin data listener after the
deferred unmount/remount cycle. The UI may re-render visually, but keyboard input is
silently dropped because no handler is listening on stdin.
Confirmed by patching
Tested three patches to isolate the root cause:
-
Screen clear no-op (replace
\x1b[H\x1b[2J\x1b[3Jwithvoid 0): Still freezes.
Rules out the escape sequence as the cause. -
Bypass
ln()for MCP pager only (replaceonClose:()=>{ln((()=>{Zn(!1)}))}with
onClose:()=>{Zn(!1)}): MCP pager no longer freezes. Confirmsln()is the bug.
But/skillsstill freezes because it also callsln()viaJn(). -
Make
ln()synchronous (removetn(true)/setTimeout/tn(false), call callback
and screen clear immediately): Fixes ALL overlays. This is the working patch.
Working patch (applied to minified 434.index.js)
Replace the deferred ln implementation with a synchronous version:
// Before (broken on Windows):
ln = useCallback((e) => __awaiter(function*() {
const { promise, resolve } = Promise.withResolvers();
tn(true);
setTimeout(() => __awaiter(function*() {
yield e();
clearScreen(stdout);
setTimeout(() => { tn(false); resolve(); }, 10);
}), 10);
return promise;
}), [stdout]);
// After (synchronous, works on Windows):
ln = useCallback((e) => { e(); clearScreen(stdout); return Promise.resolve(); }, [stdout]);
Source Files (from source map references in the bundle)
src/run-agent.tsx– deferred transition wrapper (ln) and main render treesrc/components/mcp-servers-pager.tsx– MCP pager with threeuseInputhandlerssrc/components/alt-screen.tsx– screen clear functionsrc/components/items-pager.tsx– skills/rules/commands pager (usesJnwhich callsln)
Workaround
For /mcp list specifically: use agent mcp list (non-interactive CLI mode).
For the general fix: patch ln() to be synchronous as described above.
Does this stop you from using Cursor
Sometimes - I can sometimes use Cursor