enable:
"terminal.integrated.shellIntegration.enabled": true
and
cat /Users/lqiao/.config/fish/conf.d/cursor.fish
string match -q "$TERM_PROGRAM" "vscode"
and . (cursor --locate-shell-integration-path fish)
Now both local macOS and remote macOS, fish shell, after run terminal in cursor chat, the LLM will detect the finish status and reply/summarize to me.
run `ls -l; env|grep -iE 'COMPOSER_NO_INTERACTION|PAGER|VSCODE_INJECTION'` in terminal, then put the original env list to me.
total 8
...
PAGER=head -n 10000 | cat
COMPOSER_NO_INTERACTION=1
I guess maybe zsh user can try to use (replace official code to cursor to test, or other shell user to test according to official doc.
Finally I found Kiro did it with right way: in config.fish string match -q "$TERM_PROGRAM" "kiro" and . (kiro --locate-shell-integration-path fish)
cat ~/.config/fish/conf.d/vsc-term-shell-integration.fish
# string match -q "$TERM_PROGRAM" "vscode" and . (cursor --locate-shell-integration-path fish)
# string match -q "$TERM_PROGRAM" "kiro" and . (kiro --locate-shell-integration-path fish)
# List of IDE commands to check for
set -l ide_cmds "cursor" "kiro" "windsurf" "cascade"
# Corresponding TERM_PROGRAM patterns for each command (space-separated)
set -l term_program_env_names "vscode" "cursor" "kiro" "windsurf" "cascade"
for i in (seq (count $ide_cmds))
set -l cmd $ide_cmds[$i]
if command -v $cmd >/dev/null
# Get the patterns for the current command and split them
set -l term_name (string split ' ' $term_program_env_names[$i])
# Check if TERM_PROGRAM matches any of the patterns for the command
string match -q -- "$TERM_PROGRAM" $term_name
and . ($cmd --locate-shell-integration-path fish)
and break
end
end
Iâve tried to add the fix to ~/.zprofile as well now and it has not helped. I am not sure what you mean when you say nothing overrides $PAGER further down the config, which config are you referring to?
Please be aware that if you do this, all of your custom environment from .zshrc wonât be loaded after the return. So no aliases, custom environment exports etc.
This goes more to opinion territory, but itâs much better to have your Cursor agent have as close to the same environment as you have in your interactive shell, and these days most people just dump all of their shell setup into the .zshrc file rather than splitting it out (see below pedantic approach). This means you donât need to waste time asking Cursor to figure out why youâre on a different asdf version or a tool or anything like that.
Alternative solution for the most common issue (interactive OMZ update prompt):
If you have Oh My ZSH set up then youâre likely getting the terminal hanging on the update prompt for that. What happens is that you .zshrc fully loads, and then the âPlease update OMZâ prompt runs at the end.
Alternatively, any other interactive prompting in your .zshrc could do this too.
Since OMZ is so rarely updated with anything you care about, just disable it with this anywhere in you .zshrc:
DISABLE_UPDATE_PROMPT=true
Note that the update prompt runs in the same environment, after .zshrc was sourced, so you donât even need to export it.
You can update it by hand whenever you want with omz update.
More comprehensive, pedantic solution:
Technically, following z-shell semantics, .zshrc shouldnât be sourced by Cursor because itâs intended for interactive shells, whereas Cursor is trying to use the shell in a non-interactive manner.
There are multiple initialization files you can use:
.zshenv: Move any common environment setup here for all shells, login or otherwise. This is sourced for all shells.
.zprofile: Move your userâs login setup here. E.g. any $PATH adjustments. This is sourced for all login shells and Cursor should source it.
.zshrc: Add the early return logic here from the above answer. âRCâ = âRun Commandsâ â this file should be sourced only by interactive shells. Cursor should not source it but it does, so you need to force it not to load.
.zshlogin: Listed for the pedantic sake of completion, this gets sourced after the login process is complete, so if you care about specific timing, itâs an option. Typically, just use .zprofile though.
.zshlogout: Listed for the pedantic sake of completion, this gets sourced when you exit a login shell. I guess you could put a cleanup task here.