🛠️ Guide: Fix Cursor Agent Terminal Hangs Caused by .zshrc

:hammer_and_wrench: Guide: Fix Cursor Agent Terminal Hangs Caused by .zshrc

:pushpin: Problem

When using Zsh with custom configs like Oh My Zsh, you might notice:

  • Cursor Agent terminal hangs indefinitely after running a command
  • You must click “Move to background” or “Skip” every time
  • Meanwhile, Cursor’s interactive terminal (Ctrl+ `) works fine

This is caused by your .zshrc loading interactive or slow components (e.g., themes, plugins), which interfere with Cursor Agent’s ability to detect command completion.


:test_tube: Step 1 — Confirm the issue

Run this inside Cursor’s Agent terminal (e.g., via a “Run terminal command” block):

zsh -i -c 'pwd'

If it hangs or never completes (despite printing output), the issue is confirmed.


:brain: Step 2 — Identify the difference

Run this in both terminals:

env > ~/env_from_this_terminal.txt

Compare them:

diff ~/env_from_interactive.txt ~/env_from_agent.txt

In our testing, the Agent shell had:

PAGER=head -n 10000 | cat
COMPOSER_NO_INTERACTION=1

These do not exist in the interactive terminal.


:white_check_mark: Step 3 — Patch your .zshrc

To skip loading the rest of your config inside Cursor Agent shell only, add this to the top of your ~/.zshrc:

if [[ "$PAGER" == "head -n 10000 | cat" || "$COMPOSER_NO_INTERACTION" == "1" ]]; then
  return
fi

:magnifying_glass_tilted_left: What this does:

  • :white_check_mark: Skips .zshrc only inside Agent
  • :white_check_mark: Keeps full Oh My Zsh behavior in:
    • Cursor’s Ctrl+ ` interactive terminal
    • iTerm / Terminal
    • VSCode terminal

No command overrides, no flags, no breaking changes.


:soap: Optional: Comment block

You can include this for clarity in .zshrc:

if [[ "$TERM_PROGRAM" == "vscode" || "$TERM_PROGRAM" == "cursor" ]]; then
  return
fi

:white_check_mark: Confirmed working on:

  • macOS 26.x / Zsh 5.9+
  • Oh My Zsh
  • Cursor v1.1.3+
  • Apple Silicon (M1/M2)
11 Likes

Thanks for sharing!

1 Like

This resolved my issue for now (MacOS):

:soap: Optional: Comment block

You can include this for clarity in .zshrc:

if [[ "$TERM_PROGRAM" == "vscode" || "$TERM_PROGRAM" == "cursor" ]]; then
  return
fi
2 Likes

Epic, thanks so much for the fix!

1 Like

I observe the issue on bash on Ubuntu. Is there an analogous fix, or is this specific to zsh?

thank you!!!

1 Like

Hey! I’m primarily on macOS using Zsh, so I haven’t tested this on Bash/Ubuntu directly — but the root cause is likely the same:

The Cursor Agent terminal injects unique environment variables to indicate it’s running in “Agent mode”, and if your shell config (like .bashrc) runs interactive-only logic (e.g., prompts, aliases, plugins), it can prevent the Agent from detecting command completion.


To adapt the fix for Bash, you can try the following:

  1. Run these two commands inside Cursor:

    • Inside the interactive terminal (Ctrl+ `):
      env > ~/env_interactive.txt
      
    • Inside the Agent terminal (e.g. “run terminal command”):
      env > ~/env_agent.txt
      
  2. Then compare:

    diff ~/env_interactive.txt ~/env_agent.txt
    
  3. If you find any env var that only exists in the Agent terminal, you can use it at the top of your .bashrc to short-circuit:

    if [ "$SOME_ENV_FLAG" = "1" ]; then
        return
    fi
    

This will prevent Bash from loading the rest of .bashrc in the Agent shell — keeping it clean and non-interactive.


Let me know if you find a reliable flag! Would be happy to update the solution to support Bash officially.

1 Like

VS code terminal running commands doesn’t have this issue, i have p10k theme on , and in vs code it works completely fine and doesn’t get stuck, unlike cursor its gets stuck

You’re absolutely right — the issue doesn’t happen in the VS Code integrated terminal, even with full themes like p10k, because that terminal is interactive and behaves like a normal user shell.

However, the Cursor Agent doesn’t use an interactive terminal. It spawns a headless shell in the background to execute commands — and this non-interactive behavior is exactly where the problem comes in.

Tools like Oh My Zsh, p10k, or custom .bashrc/.zshrc configs are designed for interactive shells. When they run in a background, non-interactive context (like the Agent), they can interfere with the process output or hang waiting for terminal input, which causes the Agent to “freeze” or never detect completion.

That’s why the fix we propose only bypasses config inside the Agent terminal, but keeps everything fully enabled in VS Code, iTerm, or Cursor’s Ctrl + ` terminal.

Let me know if you want to verify whether your config loads in non-interactive shells — happy to walk you through it.

1 Like

Thank you for this fix; however, I think the cursor team should look into this. I personally like an interactive shell, because I can see the entire output clearly, especially since I’m learning mostly and don’t want just to run the command. At least they should give u the option

1 Like

Totally fair — and I 100% agree this should be addressed at the core level by the Cursor team.

Our workaround just keeps the Agent functional for now, but long-term, this really should be a built-in option.

Appreciate you sharing your perspective :raising_hands:

The AI agent should get a new ability to send inputs to the shell and interpret interactive outputs, like scrolling the content with the less pager with hjkl :neutral_face:

Haha yep — interpreting interactive outputs like less, vim, or even top would be next-level :exploding_head:

Right now, the Agent operates in a non-interactive shell and doesn’t have input control after launch — so it can’t respond to --More-- prompts or scrollable output yet.

But you’re spot on: long-term, giving the Agent actual terminal input/output control would unlock much richer workflows. Definitely hope the team explores this kind of interactivity someday :eyes:

it does not work in my fish shell env

# if test "$PAGER" = "head -n 10000 | cat"; or test "$COMPOSER_NO_INTERACTION" = "1"
#   return
# end

Thanks for testing this in fish — you’re almost there!

Your syntax looks valid for Fish shell, but the environment variables used by Cursor Agent might not match exactly in your setup — especially if you’re on Linux or Windows/WSL. It’s worth confirming whether variables like PAGER or COMPOSER_NO_INTERACTION are actually being set inside the Agent terminal.


:white_check_mark: Recommended steps:

  1. Compare the environment variables between:
    • Cursor interactive terminal (Ctrl+`)
    • Cursor Agent terminal (e.g. “Run this terminal command: env > ~/env_fish_agent_terminal.txt”)

Run this in each one:

  • Cursor interactive terminal (Ctrl+`):

  • env > ~/env_fish_ctrl_terminal.txt
    
  • Cursor Agent terminal:

  • env > ~/env_fish_agent_terminal.txt
    

Then compare:

diff ~/env_fish_ctrl_terminal.txt ~/env_fish_agent_terminal.txt

  1. Look for a unique variable , like:
  • PAGER = head -n 10000 | cat
  • COMPOSER_NO_INTERACTION = 1
  • Or anything specific to Agent (e.g. PIP_NO_INPUT = 1, etc.)

  1. Apply the condition at the top of your ~/.config/fish/config.fish:
if test "$PAGER" = "head -n 10000 | cat"; or test "$COMPOSER_NO_INTERACTION" = "1"
  return
end

:white_check_mark: This will skip the rest of your config only inside the Cursor Agent terminal, but will still fully load your Fish shell config in your interactive terminals.


Let me know if you find a different variable — happy to update the solution for other fish users too!

1 Like

I had the same issue with oh-my-zsh + antigen, and your hack helped. But then I found the source $ZSH/oh-my-zsh.sh at the end of the file after the antigen apply. So, in my case, the problem was caused by double omz initialization. Removing the source $ZSH/oh-my-zsh.sh fixed the issue with the Cursor terminal without the guard clause.

1 Like