oh-my-bash icon indicating copy to clipboard operation
oh-my-bash copied to clipboard

cd not working in shells created by cursor

Open gurelkaynak opened this issue 3 months ago • 7 comments

Hi,

I started having an issue with the cd command when cursor agent creates shells and tries to cd to a directory. I get this error:

environment: line 5945: _omb_cd_dirstack[0]: unbound variable

Image

My bash syntax experience is minimal so I tried asking LLM agents. After trying different models, finally GPT-5 high reasoning model fixed it for me by modifying the directories.sh file with this command:

perl -0777 -pe 's/\$\{_omb_cd_dirstack\[0\]\}/\$\{_omb_cd_dirstack[0]-\}/g'

This is the description of the fix from GPT-5:

Oh My Bash aliases cd to _omb_directories_cd, which references _omb_cd_dirstack[0] without guarding for nounset, causing the unbound variable error in non-interactive shells.

I looked for issues/PRs related to this ("cd" or "unbound") but could not find any.

I will create a PR for this soon.

gurelkaynak avatar Sep 30 '25 07:09 gurelkaynak

In the first place, _omb_cd_dirstack is ensured to be non-empty, so there shouldn't be any need for a guard for accessing _omb_cd_dirstack[0]. Do you have an idea why _omb_cd_dirstack[0] becomes unset?

akinomyoga avatar Oct 18 '25 04:10 akinomyoga

I have no idea. I have tried to debug with an LLM. Here's the result:

The Root Cause

The issue is that Oh My Bash is being loaded in a context where the return statement doesn't actually exit the script. This could be because: The script is being sourced in a subshell where return doesn't work The script is being loaded through a different mechanism that bypasses the interactive check There's a custom loading mechanism that's overriding the interactive check The fact that we see ++ return in the trace but the script continues executing confirms that the return statement is not working as intended in this context. This explains why: Oh My Bash is loading despite being in a non-interactive shell The _omb_cd_dirstack variable gets defined but then becomes unset The interactive check is present but not working as expected The return statement in the interactive check is failing to actually return from the script, allowing Oh My Bash to continue loading in non-interactive shells.

Cursor starts a non interactive shell with only hBc flags but the check at the beginning of oh-my-bash.sh does not work properly and the script continues to be executed. I still don't know what happens down the road that unsets _omb_cd_dirstack. This is the code that checks the non-interactive shell:

# Bail out early if non-interactive
#
# Note: We cannot produce any error messages here because, in some systems,
# /etc/gdm3/Xsession sources ~/.profile and checks stderr.  If there is any
# stderr ourputs, it refuses to start the session.
case $- in
  *i*) ;;
    *) return;;
esac

In my case, this does not work properly and in the end I get that error. My environment:

Windows 11 with WSL2 Ubuntu Cursor IDE connected to WSL2. BASH_VERSION: 5.0.17(1)-release Shell flags: hBCHc

gurelkaynak avatar Oct 20 '25 07:10 gurelkaynak

Hmm, this seems like an issue with the unusual use of the shell by the Cursor AI Agent. I'm still unsure why _omb_cd_dirstack is unset with the described setup, but one possibility could be that the Cursor AI Agent records aliases and functions and imports them into the non-interactive Bash process used to execute commands, while it doesn't import shell variables. Shouldn't this be fixed at the Cursor-AI-Agent side?

akinomyoga avatar Oct 20 '25 08:10 akinomyoga

I'll create a ticket on their side too. But I think both systems should be forgiving/stable enough to make things work when something is not right in a separate context. In this case I still believe the PR makes sense since it solves my issue on this side.

This is my opinion so it's up to you folks to accept it or not. Thanks for the input.

gurelkaynak avatar Oct 20 '25 09:10 gurelkaynak

I'm not sure exactly why the problem happens, but if variables would be lost in general with Cursor, it's impossible to work around it in general. In the present case, we could suppress the error message by using ${var-}, and there doesn't seem to be any visible breakage other than that, but many more parts may be broken more terribly under the cover.

In this case I still believe the PR makes sense since it solves my issue on this side.

Even if the problem isn't caused by Cursor, I actually doubt the validity of the PR. It just hides the error message, yet it doesn't solve the original problem that the error message tried to inform us of.

akinomyoga avatar Oct 20 '25 10:10 akinomyoga

I have no real experience with the omb development and bash scripts in general so I have no strong opinions. I'll be happy to pair and debug or follow some instructions you give me to find out more. Until then, I will try to get a hold of cursor people :)

gurelkaynak avatar Oct 20 '25 12:10 gurelkaynak

The fact that we see ++ return in the trace but the script continues executing confirms that the return statement is not working as intended in this context.

I guess this implies that you've gotten the result of set -x (set -o xtrace) while executing the command. Could you provide the content of the trace?

akinomyoga avatar Oct 20 '25 12:10 akinomyoga