38

I tried to integrate MSYS2 shell into Visual studio Code integrated terminal. Here's my user settings:

{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
    "terminal.integrated.shellArgs.windows": ["--login", "-i"]
}

However, I ran into a problem where --login changes the current working directory to Windows home. I want the current directory to be at the root of my workspace.

My further attempt was I tried add a flag -c 'cd ${workspaceRoot}'. However, the bash would crashed on start. I could properly get to current directory by removing --login, but without login mode, all other shell command (ls, cd, etc) are not available.

How do I properly integrate MSYS2 shell into my vscode?

pbeta
  • 774
  • 1
  • 7
  • 13
  • 1
    For everybody checking out the answers: since Apr 2021, the setting used to be `terminal.integrated.shell.windows` is pointing to [`terminal.integrated.profiles.windows`](https://code.visualstudio.com/docs/editor/integrated-terminal). – Abel Cheung May 07 '21 at 16:27

11 Answers11

38

To inhibit the working directory change from your current directory, set the CHERE_INVOKING environment variable to a non-empty value:

    "terminal.integrated.env.windows": {
        "CHERE_INVOKING": "1"
    },

In MSYS login scripts, setting the CHERE_INVOKING variable serves only to prevent a shell from doing a cd "${HOME}", and nothing else.

If you require a MinGW toolchain, set the MSYSTEM environment variable to select a toolchain. Recognized values are MSYS (default), MINGW32 or MINGW64.

    "terminal.integrated.env.windows": {
        "MSYSTEM": "MINGW64",
    },

In full, the VS Code settings might look like so:

{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
    "terminal.integrated.shellArgs.windows": [
        "--login",
    ],
    "terminal.integrated.env.windows": {
        "CHERE_INVOKING": "1",
        "MSYSTEM": "MINGW64",
    },
}

To provide some context on the very cryptic nomenclature of CHERE_INVOKING: chere is apparently a Cygwin command for installing and managing a "Command Prompt Here" folder context menu item. Although MSYS2 inherits the environment variable from Cygwin, it doesn't actually inherit the command itself.

Jānis Rūcis
  • 481
  • 1
  • 4
  • 4
38

Answers here are from the old method which is now (July 2021) deprecated in VSCode the new suggested way, add this to settings.json:

"terminal.integrated.profiles.windows": {
    "PowerShell": {
      "source": "PowerShell",
      "icon": "terminal-powershell"
    },
    "Command Prompt": {
      "path": [
        "${env:windir}\\Sysnative\\cmd.exe",
        "${env:windir}\\System32\\cmd.exe"
      ],
      "args": [],
      "icon": "terminal-cmd"
    },
    "Git Bash": {
      "source": "Git Bash"
    },
    "MSYS2": {
      "path": "C:\\msys64\\usr\\bin\\bash.exe",
      "args": [
        "--login",
        "-i"
      ],
      "env": {
        "MSYSTEM": "MINGW64",
        "CHERE_INVOKING": "1"
      }
    }
  },

reference: integrated-terminal#_configuring-profiles

Ali80
  • 6,333
  • 2
  • 43
  • 33
  • 2
    To add on to this, the text that you should add to the settings.json file is the "MSYS2" text and downward. – BSplitter Jun 07 '22 at 06:44
24

#Original but not working 100% (accepted as the answer) This will start the MSYS2 bash shell properly so your .bash_login gets executed:

"terminal.integrated.shell.windows": "C:\\msys64\\msys2_shell.cmd",
"terminal.integrated.shellArgs.windows": ["-defterm", "-mingw64", "-no-start", "-here"]

#Edit The original answer seemed to work at the time, but when I tried to start using tasks in VSCode it was clearly not working. Trying to run a task that simply called make all caused the following error:

/usr/bin/bash: /d: No such file or directory
The terminal process terminated with exit code: 127

From the other answers, using "terminal.integrated.shellArgs.windows": ["--login", "-i"] got the almost the correct environment (MSYS instead of MINGW64) but started in the wrong directory, and "terminal.integrated.shellArgs.windows": ["-lic", "cd $OLDPWD; exec bash"] started in the correct directory with the correct environment but could not run tasks.

I came up with this solution that so far seems to work fine.
In VSCode settings:

"terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
"terminal.integrated.env.windows":
{
    "MSYSTEM": "MINGW64",
    //"MSYS2_PATH_TYPE": "inherit",
    "MSVSCODE": "1"
},

In .bashrc:

if [ ! -z "$MSVSCODE" ]; then
    unset MSVSCODE
    source /etc/profile
    cd "${OLDPWD}" # this has to be in quotes to handle file paths with spaces
fi
AntPalmer
  • 51
  • 6
cola
  • 326
  • 2
  • 5
8

This works for me:

{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
    "terminal.integrated.shellArgs.windows": ["--login", "-i"],
    "terminal.integrated.env.windows":
    {
        "MSYSTEM": "MINGW64",
        "CHERE_INVOKING":"1"
    }
}
1

When calling the shell to execute task, vs code add /d /c arguments to the shell executable as it would for cmd.exe (see cmd /? in cli). Of course MSYS2 bash don't interpret /d /c as valid params, that s why it answers /d: No such file or directory as it try to interpret /d as a command. I ve just began to dig in VSCode and I have the feeling some config parameter is missing in user configuration to tell vscode the good way to call msys2_shell.cmd (ie with -c arg) for task execution (no pb for integrated/interactive shell as no arg is passed when bash is invoked). Anyway, to overcome the problem it is possible to edit msys2_shell.cmd to trap \d \c and call bash with -c:

@echo off
setlocal

rem usefull get what VSCode pass 
rem echo "given params %1 %2 %3 %4 %5 %6 %7 %8 %9"

set "WD=%__CD__%"
if NOT EXIST "%WD%msys-2.0.dll" set "WD=%~dp0usr\bin\"

rem To activate windows native symlinks uncomment next line
rem set MSYS=winsymlinks:nativestrict

rem Set debugging program for errors
rem set MSYS=error_start:%WD%../../mingw64/bin/qtcreator.exe^|-debug^|^<process-id^>

rem To export full current PATH from environment into MSYS2 use '-use-full-path' parameter
rem or uncomment next line
rem set MSYS2_PATH_TYPE=inherit

:checkparams
rem Help option
if "x%~1" == "x-help" (
  call :printhelp "%~nx0"
  exit /b %ERRORLEVEL%
)
if "x%~1" == "x--help" (
  call :printhelp "%~nx0"
  exit /b %ERRORLEVEL%
)
if "x%~1" == "x-?" (
  call :printhelp "%~nx0"
  exit /b %ERRORLEVEL%
)
if "x%~1" == "x/?" (
  call :printhelp "%~nx0"
  exit /b %ERRORLEVEL%
)
rem Shell types
if "x%~1" == "x-msys" shift& set MSYSTEM=MSYS& goto :checkparams
if "x%~1" == "x-msys2" shift& set MSYSTEM=MSYS& goto :checkparams
if "x%~1" == "x-mingw32" shift& set MSYSTEM=MINGW32& goto :checkparams
if "x%~1" == "x-mingw64" shift& set MSYSTEM=MINGW64& goto :checkparams
if "x%~1" == "x-mingw" shift& (if exist "%WD%..\..\mingw64" (set MSYSTEM=MINGW64) else (set MSYSTEM=MINGW32))& goto :checkparams
rem Console types
if "x%~1" == "x-mintty" shift& set MSYSCON=mintty.exe& goto :checkparams
if "x%~1" == "x-conemu" shift& set MSYSCON=conemu& goto :checkparams
if "x%~1" == "x-defterm" shift& set MSYSCON=defterm& goto :checkparams
rem Other parameters
if "x%~1" == "x-full-path" shift& set MSYS2_PATH_TYPE=inherit& goto :checkparams
if "x%~1" == "x-use-full-path" shift& set MSYS2_PATH_TYPE=inherit& goto :checkparams
if "x%~1" == "x-here" shift& set CHERE_INVOKING=enabled_from_arguments& goto :checkparams
if "x%~1" == "x-where" (
  if "x%~2" == "x" (
    echo Working directory is not specified for -where parameter. 1>&2
    exit /b 2
  )
  cd /d "%~2" || (
    echo Cannot set specified working diretory "%~2". 1>&2
    exit /b 2
  )
  set CHERE_INVOKING=enabled_from_arguments
)& shift& shift& goto :checkparams
if "x%~1" == "x-no-start" shift& set MSYS2_NOSTART=yes& goto :checkparams

rem VS CODE  CMD.EXE argument PATCH
if "x%~1" == "x/d" (
    if "x%~2" == "x/c" (
        rem we got a vs code task issued
        echo "VSCODE_TASK detected"
        shift& shift
        set VSCODE_TASK=yes 
        goto :checkparams
    )
)& shift& goto :checkparams


rem Setup proper title
if "%MSYSTEM%" == "MINGW32" (
  set "CONTITLE=MinGW x32"
) else if "%MSYSTEM%" == "MINGW64" (
  set "CONTITLE=MinGW x64"
) else (
  set "CONTITLE=MSYS2 MSYS"
)

if "x%MSYSCON%" == "xmintty.exe" goto startmintty
if "x%MSYSCON%" == "xconemu" goto startconemu
if "x%MSYSCON%" == "xdefterm" goto startsh

if NOT EXIST "%WD%mintty.exe" goto startsh
set MSYSCON=mintty.exe
:startmintty
if not defined MSYS2_NOSTART (
  start "%CONTITLE%" "%WD%mintty" -i /msys2.ico -t "%CONTITLE%" /usr/bin/bash --login %1 %2 %3 %4 %5 %6 %7 %8 %9
) else (
  "%WD%mintty" -i /msys2.ico -t "%CONTITLE%" /usr/bin/bash --login %1 %2 %3 %4 %5 %6 %7 %8 %9
)
exit /b %ERRORLEVEL%

:startconemu
call :conemudetect || (
  echo ConEmu not found. Exiting. 1>&2
  exit /b 1
)
if not defined MSYS2_NOSTART (
  start "%CONTITLE%" "%ComEmuCommand%" /Here /Icon "%WD%..\..\msys2.ico" /cmd "%WD%bash" --login %1 %2 %3 %4 %5 %6 %7 %8 %9
) else (

  "%ComEmuCommand%" /Here /Icon "%WD%..\..\msys2.ico" /cmd "%WD%bash" --login %1 %2 %3 %4 %5 %6 %7 %8 %9
)
exit /b %ERRORLEVEL%

:startsh
set MSYSCON=
if not defined MSYS2_NOSTART (
  start "%CONTITLE%" "%WD%bash" --login %1 %2 %3 %4 %5 %6 %7 %8 %9
) else (
  rem integrated shell called (interactive)
  if not defined VSCODE_TASK (
    "%WD%bash" --login %1 %2 %3 %4 %5 %6 %7 %8 %9
  ) else (
    rem Call bash with -c arg (execute the command in argument and quit)
    rem echo  "start  %WD%bash" --login -c "%1 %2 %3 %4 %5 %6 %7 %8 %9"
    "%WD%bash" --login -c "%1 %2 %3 %4 %5 %6 %7 %8 %9"
  )
)
exit /b %ERRORLEVEL%

:EOF
exit /b 0

:conemudetect
set ComEmuCommand=
if defined ConEmuDir (
  if exist "%ConEmuDir%\ConEmu64.exe" (
    set "ComEmuCommand=%ConEmuDir%\ConEmu64.exe"
    set MSYSCON=conemu64.exe
  ) else if exist "%ConEmuDir%\ConEmu.exe" (
    set "ComEmuCommand=%ConEmuDir%\ConEmu.exe"
    set MSYSCON=conemu.exe
  )
)
if not defined ComEmuCommand (
  ConEmu64.exe /Exit 2>nul && (
    set ComEmuCommand=ConEmu64.exe
    set MSYSCON=conemu64.exe
  ) || (
    ConEmu.exe /Exit 2>nul && (
      set ComEmuCommand=ConEmu.exe
      set MSYSCON=conemu.exe
    )
  )
)
if not defined ComEmuCommand (
  FOR /F "tokens=*" %%A IN ('reg.exe QUERY "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\ConEmu64.exe" /ve 2^>nul ^| find "REG_SZ"') DO (
    set "ComEmuCommand=%%A"
  )
  if defined ComEmuCommand (
    call set "ComEmuCommand=%%ComEmuCommand:*REG_SZ    =%%"
    set MSYSCON=conemu64.exe
  ) else (
    FOR /F "tokens=*" %%A IN ('reg.exe QUERY "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\ConEmu.exe" /ve 2^>nul ^| find "REG_SZ"') DO (
      set "ComEmuCommand=%%A"
    )
    if defined ComEmuCommand (
      call set "ComEmuCommand=%%ComEmuCommand:*REG_SZ    =%%"
      set MSYSCON=conemu.exe
    )
  )
)
if not defined ComEmuCommand exit /b 2
exit /b 0

:printhelp
echo Usage:
echo     %~1 [options] [bash parameters]
echo.
echo Options:
echo     -mingw32 ^| -mingw64 ^| -msys[2]   Set shell type
echo     -defterm ^| -mintty ^| -conemu     Set terminal type
echo     -here                            Use current directory as working
echo                                      directory
echo     -where DIRECTORY                 Use specified DIRECTORY as working
echo                                      directory
echo     -[use-]full-path                 Use full currnent PATH variable
echo                                      instead of triming to minimal
echo     -no-start                        Do not use "start" command and
echo                                      return bash resulting errorcode as
echo                                      this batch file resulting errorcode
echo     -help ^| --help ^| -? ^| /?         Display this help and exit
echo.
echo Any parameter that cannot be treated as valid option and all
echo following parameters are passed as bash command parameters.
echo.
exit /b 0
Dje53
  • 11
  • 3
1

The accepted answer works for me but with zsh shell ("terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\zsh.exe"), things are much slower than with bash. I don't know why but using ConEmu's cygwin/msys terminal connector greatly helped:

"terminal.integrated.shell.windows": "C:\\conemu\\ConEmu\\conemu-msys2-64.exe",
"terminal.integrated.env.windows": {
    "CHERE_INVOKING": "1",
    "MSYSTEM": "MINGW64",
    "MSYS2_PATH_TYPE": "inherit",
},
"terminal.integrated.shellArgs.windows": [
    "/usr/bin/zsh",
    "-l",
    "-i",
],
Borek Bernard
  • 50,745
  • 59
  • 165
  • 240
1

This works for me with Visual Studio Code version shown below

"terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
"terminal.integrated.shellArgs.windows": ["--login", "-i"],
"terminal.integrated.env.windows":
{
    "MSYSTEM": "MINGW64",
    "CHERE_INVOKING":"1",
    "PATH" : "/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/c/Windows/System32:/c/Windows:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0/"         
},

VS Code version

Sy Tran
  • 11
  • 1
0

I got this to work

{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\bash.exe",
    "terminal.integrated.shellArgs.windows": ["-lic", "cd $OLDPWD; exec bash"],
}
user2241515
  • 121
  • 2
  • 8
0
{
    "terminal.integrated.shell.windows": "C:\\msys64\\usr\\bin\\sh.exe",
    "terminal.integrated.shellArgs.windows": ["--login", "-i"]
}

Worked for me.

n370
  • 3,296
  • 3
  • 15
  • 20
0

Press F1 + write settings.json then, at the end of the {} add the next lines:

"terminal.integrated.shell.windows": "C:\\msys32\\msys2_shell.cmd",
"terminal.integrated.shellArgs.windows": ["-defterm", "-mingw32", "-no-start", "-here"],

It would looks like this: (Obviously, the settings.json could be different to the next example)

"telemetry.enableTelemetry": true,
"code-runner.saveFileBeforeRun": true,
"code-runner.saveAllFilesBeforeRun": true,
"code-runner.runInTerminal": true,
"liveshare.audio.startCallOnShare": true,
"window.zoomLevel": 1,
"explorer.confirmDelete": false,
"C_Cpp.updateChannel": "Insiders",

"terminal.integrated.shell.windows": "C:\\msys32\\msys2_shell.cmd",
"terminal.integrated.shellArgs.windows": ["-defterm", "-mingw32", "-no-start", "-here"]

Keep in mind that you have to add a comma , before to paste the suggested lines.

  • Note that while this answer can successfully launch a basic msys2/mingw shell from within vscode integrated terminal, it may not work when python venv activation is required. For me launching `bash.exe` directly is required for python projects using venv. – Abel Cheung May 07 '21 at 15:48
0

This question is more than a year old, but I was still having it. Just thought I'd share my solution, since it's not on here.

The accepted answer works, and allows tasks to work too, but when I try getting the vscode-cpptools debugger to launch GDB, GDB will always crash with the following error unless I remove --login:

ERROR: Unable to start debugging. Unexpected GDB output from command "-exec-run". During startup program exited with code 0xc0000135

To fix this, there were two options, the first was to add "source": "Git Bash" to the terminal profile, but this requires you to have git for windows installed.

The second option was simpler, and added the path variables without using --login:

"terminal.integrated.profiles.windows":
{
    "MINGW64":
    {
        "path": "C:/msys64/usr/bin/bash.exe",
        "env":
        {
            "CHERE_INVOKING": "1",
            "MSYSTEM": "MINGW64",
            // THE FOLLOWING IS A HACK TO PLACE THE MSYS PATHS BEFORE THE WINDOWS ONES
            "PATH": "/usr/bin;/mingw64/bin;${env:PATH}"
        },
        "color": "terminal.ansiMagenta"
    }
},
"terminal.integrated.defaultProfile.windows": "MINGW64",

Hope this helps.