Skip to main content

Fixing Cursor Agent Terminal Hangs: zsh, bash, fish Shell Solutions

Cursor Terminal Hang Fix

One of the most common issues when using Cursor's Agent mode is terminal hangs. The agent terminal loads your shell configuration (.zshrc, .bashrc, .bash_profile, .config/fish/config.fish), and if these files contain interactive plugins like Oh My Zsh, Powerlevel10k, or custom prompts, the agent gets stuck waiting for user input. This guide provides proven fixes for all major shells.

Understanding the Problem​

What Happens​

  1. Cursor Agent opens a new terminal
  2. The terminal loads your shell configuration file
  3. Interactive plugins (Oh My Zsh, p10k, etc.) initialize
  4. Some plugins wait for user interaction
  5. The agent terminal hangs indefinitely

Common Culprits​

ShellConfig FileCommon Hanging Plugins
zsh.zshrcOh My Zsh, p10k, zsh-autosuggestions
bash.bashrc, .bash_profilebash-it, custom PS1 with git status
fish~/.config/fish/config.fishOh My Fish, fisher, custom prompts

The cleanest solution is to detect when Cursor is running and skip interactive configuration.

For zsh (.zshrc)​

Add this at the very top of your .zshrc:

# Skip interactive configuration for non-interactive shells
if [[ -n "$CURSOR_AGENT" ]] || [[ "$TERM_PROGRAM" == "cursor" ]] || [[ -n "$COMPOSER_NO_INTERACTION" ]]; then
# Minimal prompt for Cursor Agent
PS1="$ "
return
fi

# Your existing interactive configuration below...
# export ZSH="$HOME/.oh-my-zsh"
# source $ZSH/oh-my-zsh.sh
# etc.

For bash (.bashrc)​

Add this at the very top of your .bashrc:

# Skip interactive configuration for Cursor Agent
if [[ -n "$CURSOR_AGENT" ]] || [[ "$TERM_PROGRAM" == "cursor" ]] || [[ -n "$COMPOSER_NO_INTERACTION" ]]; then
PS1="$ "
return
fi

# Your existing configuration below...

For bash (.bash_profile)​

Same approach for .bash_profile:

# Detect Cursor Agent environment
if [[ -n "$CURSOR_AGENT" ]] || [[ "$TERM_PROGRAM" == "cursor" ]]; then
PS1="$ "
return
fi

For fish (config.fish)​

Add at the top of ~/.config/fish/config.fish:

# Skip interactive configuration for Cursor Agent
if test -n "$CURSOR_AGENT"; or test "$TERM_PROGRAM" = "cursor"; or test -n "$COMPOSER_NO_INTERACTION"
function fish_prompt
echo '$ '
end
return
end

# Your existing configuration below...

Solution 2: Non-Interactive Shell Detection​

Use POSIX-standard non-interactive shell detection:

Universal Approach (Works for bash, zsh)​

# At the top of .bashrc or .zshrc
case $- in
*i*) ;;
*)
# Non-interactive shell (Cursor Agent)
PS1="$ "
return
;;
esac

# Alternative one-liner
[[ $- != *i* ]] && PS1="$ " && return

Solution 3: Minimal Agent Shell​

Create a dedicated configuration for Cursor Agent:

Step 1: Create Agent Shell Config​

# Create ~/.cursor-shell-rc
# This is a minimal RC file for Cursor Agent

# Basic PATH
export PATH="/usr/local/bin:/usr/bin:/bin:$HOME/.local/bin"

# Aliases that work without plugins
alias ll='ls -la'
alias ..='cd ..'

# Minimal prompt
PS1="\w $ "

Step 2: Point Cursor to Minimal Config​

In Cursor Settings or .cursor/agent-config.json:

{
"terminal": {
"shell": "/bin/zsh",
"shellArgs": ["--rcs", "~/.cursor-shell-rc"]
}
}

Or set environment variable in Cursor:

{
"terminal.integrated.env.linux": {
"ZDOTDIR": "~/.cursor-zsh"
},
"terminal.integrated.env.osx": {
"ZDOTDIR": "~/.cursor-zsh"
}
}

Step 3: Create ~/.cursor-zsh Directory​

mkdir -p ~/.cursor-zsh
cat > ~/.cursor-zsh/.zshrc << 'EOF'
# Minimal zsh config for Cursor Agent
export PATH="/usr/local/bin:/usr/bin:/bin:$HOME/.local/bin"
PS1="%1~ $ "
EOF

Solution 4: Plugin-Specific Fixes​

Oh My Zsh​

# In .zshrc - wrap Oh My Zsh loading
if [[ -z "$CURSOR_AGENT" ]] && [[ -z "$COMPOSER_NO_INTERACTION" ]]; then
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="powerlevel10k/powerlevel10k"
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
source $ZSH/oh-my-zsh.sh
else
# Minimal config for Cursor
PS1="$ "
fi

Powerlevel10k (p10k)​

# In .zshrc
if [[ -z "$CURSOR_AGENT" ]] && [[ -z "$COMPOSER_NO_INTERACTION" ]]; then
# Enable Powerlevel10k instant prompt
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

# Load p10k configuration
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
else
# Skip p10k for Cursor Agent
PS1="$ "
fi

zsh-autosuggestions​

# Only load in interactive shells
if [[ -o interactive ]] && [[ -z "$CURSOR_AGENT" ]]; then
source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
fi

bash-it​

# In .bashrc
if [[ -n "$PS1" ]] && [[ -z "$CURSOR_AGENT" ]]; then
export BASH_IT="$HOME/.bash_it"
source "$BASH_IT/bash_it.sh"
else
PS1="\w\$ "
fi

Oh My Fish​

# In config.fish
if test -n "$CURSOR_AGENT"
# Skip OMF for Cursor Agent
function fish_prompt
echo (prompt_pwd) '> '
end
else
# Load Oh My Fish
if test -f $HOME/.local/share/omf/pkg/omf/functions/omf.fish
source $HOME/.local/share/omf/pkg/omf/functions/omf.fish
end
end

Solution 5: Timeout-Based Detection​

Add a timeout to detect hanging prompts:

# In .zshrc or .bashrc
# If the shell takes too long to initialize, show a warning

__cursor_shell_timeout() {
local start_time=$(date +%s)

# Your normal config here

local end_time=$(date +%s)
local elapsed=$((end_time - start_time))

if [[ $elapsed -gt 3 ]] && [[ -n "$CURSOR_AGENT" ]]; then
echo "WARNING: Shell took ${elapsed}s to initialize. Consider optimizing your config."
fi
}

__cursor_shell_timeout

Solution 6: Cursor-Specific Environment Variables​

Set these in Cursor's terminal settings:

In Cursor Settings (settings.json)​

{
"terminal.integrated.env.linux": {
"CURSOR_AGENT": "1",
"COMPOSER_NO_INTERACTION": "1",
"PAGER": "cat",
"GIT_PAGER": "cat"
},
"terminal.integrated.env.osx": {
"CURSOR_AGENT": "1",
"COMPOSER_NO_INTERACTION": "1",
"PAGER": "cat",
"GIT_PAGER": "cat"
},
"terminal.integrated.env.windows": {
"CURSOR_AGENT": "1",
"COMPOSER_NO_INTERACTION": "1",
"PAGER": "cat",
"GIT_PAGER": "cat"
}
}

Testing Your Fix​

Method 1: Simulate Agent Terminal​

# Open a terminal with Cursor Agent environment
CURSOR_AGENT=1 COMPOSER_NO_INTERACTION=1 zsh -l

# If it loads quickly without prompts, your fix works

Method 2: Time Your Shell Startup​

# Time zsh startup
time zsh -i -c exit

# Time bash startup
time bash -i -c exit

# Should be under 1 second for Agent environments

Method 3: Use Cursor's Built-in Terminal​

  1. Open Cursor
  2. Open integrated terminal (Ctrl + `)
  3. Check if it loads without delay
  4. Run a simple command: echo $CURSOR_AGENT

Debugging Shell Startup​

Enable Debug Mode​

# For zsh - trace startup
zsh -xv 2>&1 | head -50

# For bash - trace startup
bash -x -l 2>&1 | head -50

Profile Shell Startup​

# For zsh
zsh -xv 2>&1 | ts '[%H:%M:%.S]' | head -100

# Check which lines take the longest

Quick Reference: Fix by Shell​

zsh Fix Summary​

# Add to TOP of ~/.zshrc
if [[ -n "$CURSOR_AGENT" ]] || [[ "$TERM_PROGRAM" == "cursor" ]]; then
PS1="$ "
return
fi

# Then your normal config

bash Fix Summary​

# Add to TOP of ~/.bashrc
if [[ -n "$CURSOR_AGENT" ]] || [[ "$TERM_PROGRAM" == "cursor" ]]; then
PS1="$ "
return
fi

# Then your normal config

fish Fix Summary​

# Add to TOP of ~/.config/fish/config.fish
if test -n "$CURSOR_AGENT"; or test "$TERM_PROGRAM" = "cursor"
function fish_prompt
echo '$ '
end
return
end

# Then your normal config

Common Mistakes​

MistakeWhy It FailsFix
Detection at bottom of configInteractive plugins already loadedMove detection to TOP
Using $TERM instead of $TERM_PROGRAM$TERM is xterm-256colorUse $TERM_PROGRAM or $CURSOR_AGENT
Forgetting return or exitConfig continues loadingAlways return after minimal setup
Only checking one variableCursor may set different varsCheck multiple variables