Code change:
Parent issue Update: Activate the fish shell integration by following these instructions: We're keeping this open until automatic injection is looked into.
Deferring to focus on polishing how shell integration works in general
Final implementation details aside, fish's event handing will make at least some of this dead easy: Some will be more difficult, at least to deploy auto-magically, because fish's are the output of shell functions, not the contents of variables: So to transparently preserve the user's original prompt, like the bash script does, would require modifying a shell function on-the-fly, not just a variable. Yikes. That said, I put the above code, plus the following, in my own config— —and I had all of VS Code's working perfectly with VS Code v1.70.0 + fish 3.5.1. It's only a proof of concept, but hopefully this saves somebody a few web searches down the line, at least. :)
very handy info thanks! The bash script handles both PS1 and PRONPT_COMMAND, might be able to wrap the function automatically in a similar way?
Well, fish doesn't have either: if you want something to run right before the prompt displays, you put it in a function with . There is, alas, no event handler that runs after displaying the prompt but before accepting input (which is where you'd want ). There are also no events specific to the right-side prompt only. FWIW, there's also no equivalent in fish—"instead it leaves the lines indented to show that the commandline isn’t complete yet"—but the lack of and sequences in the above didn't seem to have any noticeable impact on VS Code's ability to parse the terminal in my testing.
ah I see, I think this stuff should still work though. We actually don't currently use some of these positions and the 633 E sequence kind of removes the need for them all together. So if there are limitations like this we can just take note for the future, like when finalizing the sequences this month. The limitations imposed on us by the Windows backend are much more frustrating to deal with than this sounds If you want to put a PR out with just the script as a starting point (just the script) we could then give it a try and see if we can get it in as an experimental thing. I guess just manually installing until it's considered stable, plus the automatic injection was a handful for the other shells. You could also move the 633 A to just after 633 D, I'd expect that to work fine.
I've been wanting to do this since last month, and comment finally motivated me to put up a fish plugin here: The trick I have seen in is that they wait for a event and then initialize the code, at which time the prompt function should be ready however they are defined.
FYI those sequences may change as they are yet to be finalized ().
Now that has reminded me fish can do e.g. (which I just... totally blanked on yesterday ), I think I could put together an experimental PR for this—one that could be easily tweaked if/when the escape sequences are finalized.
Also thanks to a PR from the fish history file is now loaded so pulls from it when fish is active !
that would be fantastic
Thanks everyone! The script should be available in tomorrow's Insiders, see for manual install instructions (replace with ) I'll keep this issue open until we no longer consider it experimental.
The new function does not work properly in my case. My fish configuration uses a right prompt and shows the exit code of the command (green check mark). The exit code is always shown as good, even if the executed program returns a non-0 code. The right prompt is also misaligned. It is one line below where it is supposed to be. ! The status code issue seems to be caused by executing first, because this will overwrite and . The misaligned right prompt seems to relate to some newline shenanigans fish does. It removes the last newline from the prompt, but since is after the prompt it doesn't work any longer. I found these related links: , I change the above snippet to this it seems to work better for me.
thanks for the report! Do you want to submit a PR or should I try out the fix?
I am not interested in progressing this further or submitting a PR.
no worries, thanks for reporting
Isn't this already done? Or is this about automatic integration?
I was keeping it open until the kinks were worked out, plus automatic injection would be great if it's possible. Not sure anyone has looked into it yet.
should we change the title of this issue or create a new one to capture automatic injection?
i think the right way to add automatic injection would be to append a directory to that contains the integration script in a subdirectory (see )
we wouldn't be able to stick it in XDGDATADIRS though in case a user has a file there already. Changing XDGDATADIRS also seems dangerous and I think this would only work on Linux
it sounds like you may be confused as to what XDGDATADIRS is so i whipped up a pr for this, with links to the relevant spec and fish docs. alternatively i'm confused as to what you might mean. XDGDATADIRS is a set of directories to search for data files, ordered by preference. we'd be adding a directory to the end of it so what a user may already have there is irrelevant, and our directory would be part of the vscode distribution so the user really shouldn't have any files in there. aside from that user things go in XDGDATAHOME, XDGDATADIRS is for system components. i'm not sure what danger you see there. we're adding another directory to find data files in; we're not preventing any other data files from being found. this is documented universal fish behavior on any system it supports. i linked the literal default fish configuration above that demonstrates this. also back when i last used a mac most tools did support the xdg base directories, including fish (and nix, which makes rather heavy use of XDGDATADIRS). the only ones that didn't still don't on linux (like electron ).
oh it's a list of dirs, I thought this was setting a single dir. And you're right we don't need to worry about Windows here. Thanks, will check out the PR soon
Since the issue is now closed, is the problem reported here something you would still want to fix? It doesn't seem to be fixed on main so far.
thanks for the reminder, I forked it off to
To verify: Make sure fish is installed on your system (macOS or Linux) Launch a fish shell and verify the shell integration decorations should up to the left of the terminal
yep, works for me!
Unfortunately this does not work in a newly-installed fish shell via homebrew on macOS. https://user- Pty host logs:
what's your ? Also what is the output of ?
works for me with this info: !
did you manually install shell integration? This issue is about automatic injection, the update in the original issue was to help users manually activate it before this was done.
Yes I did
and disabled automatic injection (set ) as you see in the screenshot. it also works for me in a subshell, so I know that i'm testing / verifying manual injection
it also works for me with automatic injection
is 3.6.0, and the shell integration path is
Looking at the code it doesn't look like we actually copy a file to :
hm, the path does appear to exist <img width="1045" alt="image" src="https://user-"Manually executing it with results in an exit code of 1 and no output, however
yeah I think what happened was I already had the injection config in my fish file when I tested automatic injection - likely from testing manual injection at one pt
Argh, I had removed the manual integration but still have other FinalTerm-compatible shell integration and probably thought this was working because of that On 26. Jan 2023, at 18:19, Megan Rogge yeah I think what happened was I already had the injection config in my fish file when I tested automatic injection - likely from testing manual injection at one pt —Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID:
To verify make sure you don't manually activate shell integration in your , then check with and without and make sure shell integration works and doesn't work respectively.
When I open a terminal in the fish shell and run some commands, then run "Run recent command", the commands in the fish terminal don't show up, I assume that means it's not working for me
works for me: <img width="741" alt="Screenshot 2023-05-30 at 2 43 13 pm" src=""Do you see the grey/blue/red dot?
No, I guess shell integration is not enabled in the fish profile, I'm not sure how to troubleshoot that.
Is there supposed to be automatic integration in stable VSCode now? It doesn't seem to be working for me, but manual integration still does. Open and make sure it contains the manual integration code:
he's trying to test the newly fixed automatic injection in Insiders
can you run ? Also enabling trace logs and getting the pty host log when launching would be helpful (be mindful of any sensitive environment variables)
Here's my pty host log which includes
this isn't working for me after I removed my !
what do you mean by removed your XDGDATADIRS? weird, it's there so it should be run afaik. any idea what could be going wrong here wrt the XDGDATADIR auto activation?
I think I had manually enabled fish shell integration which is why it was working. In order to undo that, to test automatic injection, I removed that directory. Then it didn't work
IE my expectation was after undoing manual injection, it would work automatically. That wasn't the case.
I had misunderstood how this injection works because it is different from that of and . Deleting my in the comment above was the reason I saw it not working. I now see it working. !
since it's working for and I we'll close this and include it in the release notes. It would be good to get to the bottom of your issue, we can track that in another issue? We can have a call to investigate when you're free if that works.
Sure, call any time
Not really, sorry. Maybe the snap packaging interferes somehow? From your shell session, are and present?
We investigated, it ended up being the fish version being too old. After the update it worked great! Thanks for all the help
This isn't working for me in 1.79.0 (non-insider), as far as I can see the fish config is there but XDGDATADIRS isn't getting set. And looking at the code I found -- what happened?
we had to disable it because it was printing an error when starting up for someone on the team: For some reason was undefined at the time, it got set later, after our applied.
Looking at again I believe this would happen when something we need, like , is configured in either or in a file with a basename that's sorted before the one we expose. The file is intentionally read last so people can override vendor configuration, so since we need to run after user configuration maybe providing vendor configuration is just not the way to go here… sorry Maybe instead we could invoke fish with ? That would ensure the integration happens after any configuration but before* interactive input. If I have the spoons and noone beats me to it I'll try to whip up a PR for that next week.
One way to make sure something runs after the user's but before interactive input is to put the necessary code in a self-erasing function tied to the , e.g.: This can be placed in the appropriate vendor-config directory as simply (e.g.) with no need to worry about sorting order. The function will be defined during startup, executed just before printing the first prompt, then immediately undefined so it doesn't run twice.
I tried something like that thanks to your suggestion. It's not working atm and not sure why... lmk if you see what could be wrong here
I think you also need to add to this function:
Removing verification-needed as this was covered by a test plan item.

Related discussion:
text: <ins> # --------------------------------------------------------------------------------------------- #   Copyright (c) Microsoft Corporation. All rights reserved. #   Licensed under the MIT License. See License.txt in the project root for license information. # --------------------------------------------------------------------------------------------- # # Visual Studio Code terminal integration for fish # # Manual installation: # #   (1) Add the following to the end of `$__fish_config_dir/config.fish`: # #         string match -q "$TERM_PROGRAM" "vscode" #         and . (code --locate-shell-integration-path fish) # #   (2) Restart fish. # Don't run in scripts, other terminals, or more than once per session. status is-interactive and string match --quiet "$TERM_PROGRAM" "vscode" and ! set --query VSCODE_SHELL_INTEGRATION or exit set --global VSCODE_SHELL_INTEGRATION 1 # Apply any explicit path prefix (see #99878) if status --is-login; and set -q VSCODE_PATH_PREFIX fish_add_path -p $VSCODE_PATH_PREFIX end set -e VSCODE_PATH_PREFIX # Apply EnvironmentVariableCollections if needed if test -n "$VSCODE_ENV_REPLACE" set ITEMS (string split : $VSCODE_ENV_REPLACE) for B in $ITEMS set split (string split = $B) set -gx "$split[1]" (echo -e "$split[2]") end set -e VSCODE_ENV_REPLACE end if test -n "$VSCODE_ENV_PREPEND" set ITEMS (string split : $VSCODE_ENV_PREPEND) for B in $ITEMS set split (string split = $B) set -gx "$split[1]" (echo -e "$split[2]")"$$split[1]" # avoid -p as it adds a space end set -e VSCODE_ENV_PREPEND end if test -n "$VSCODE_ENV_APPEND" set ITEMS (string split : $VSCODE_ENV_APPEND) for B in $ITEMS set split (string split = $B) set -gx "$split[1]" "$$split[1]"(echo -e "$split[2]") # avoid -a as it adds a space end set -e VSCODE_ENV_APPEND end # Handle the shell integration nonce if set -q VSCODE_NONCE set -l __vsc_nonce $VSCODE_NONCE set -e VSCODE_NONCE end # Helper function function __vsc_esc -d "Emit escape sequences for VS Code shell integration" builtin printf "e]633;%sa" (string join ";" $argv) end # Sent right before executing an interactive command. # Marks the beginning of command output. function __vsc_cmd_executed --on-event fish_preexec __vsc_esc C __vsc_esc E (__vsc_escape_value "$argv") $__vsc_nonce # Creates a marker to indicate a command was run. set --global _vsc_has_cmd end # Escape a value for use in the 'P' ("Property") or 'E' ("Command Line") sequences. # Backslashes are doubled and non-alphanumeric characters are hex encoded. function __vsc_escape_value # Escape backslashes and semi-colons echo $argv  | string replace --all '' ''  | string replace --all ';' 'x3b'  ; end # Sent right after an interactive command has finished executing. # Marks the end of command output. function __vsc_cmd_finished --on-event fish_postexec __vsc_esc D $status end # Sent when a command line is cleared or reset, but no command was run. # Marks the cleared line with neither success nor failure. function __vsc_cmd_clear --on-event fish_cancel __vsc_esc D end # Sent whenever a new fish prompt is about to be displayed. # Updates the current working directory. function __vsc_update_cwd --on-event fish_prompt __vsc_esc P Cwd=(__vsc_escape_value "$PWD") # If a command marker exists, remove it. # Otherwise, the commandline is empty and no command was run. if set --query _vsc_has_cmd set --erase _vsc_has_cmd else __vsc_cmd_clear end end # Sent at the start of the prompt. # Marks the beginning of the prompt (and, implicitly, a new line). function __vsc_fish_prompt_start __vsc_esc A end # Sent at the end of the prompt. # Marks the beginning of the user's command input. function __vsc_fish_cmd_start __vsc_esc B end function __vsc_fish_has_mode_prompt -d "Returns true if fish_mode_prompt is defined and not empty" functions fish_mode_prompt | string match -rvq '^ *(#|function |end$|$)' end # Preserve the user's existing prompt, to wrap in our escape sequences. functions --copy fish_prompt __vsc_fish_prompt # Preserve and wrap fish_mode_prompt (which appears to the left of the regular # prompt), but only if it's not defined as an empty function (which is the # officially documented way to disable that feature). if __vsc_fish_has_mode_prompt functions --copy fish_mode_prompt __vsc_fish_mode_prompt function fish_mode_prompt __vsc_fish_prompt_start __vsc_fish_mode_prompt end function fish_prompt __vsc_fish_prompt __vsc_fish_cmd_start end else # No fish_mode_prompt, so put everything in fish_prompt. function fish_prompt __vsc_fish_prompt_start __vsc_fish_prompt __vsc_fish_cmd_start end end </ins>