VSCode: How to run a command after each terminal open?

Viewed 29254

On Windows I have to run the command start-ssh-agent.cmd on each new terminal session I open. My development environment is VSCode, and I open a dozen new terminals each day. After each terminal open, I have to manually run this command.

Is there is a way to run this command on the terminal each time I open one ?

enter image description here

This may take the form of a VSCode extension, VSCode configuration (settings) or a Windows environment configuration.

Any idea?

10 Answers

On Linux systems you should use:

"terminal.integrated.shellArgs.linux"

On Windows and OSX:

terminal.integrated.shellArgs.windows

and

terminal.integrated.shellArgs.osx

respectively.

If you want to apply shellArgs setting on a per-workspace basis - you can, despite the fact that documentation says:

The first time you open a workspace which defines any of these settings, VS Code will warn you and subsequently always ignore the values after that

At least version 1.42 of VSCode asks you something like:

"This workspace wants to set shellArgs, do you want to allow it?"

See issue 19758


On Linux, if you are using bash (default for shell in VSCode), there are some subtleties:

  1. "terminal.integrated.shellArgs.linux": ["your_init_script.sh"]
    
    will execute the script and close terminal right away. To prevent this you'll have to end the script with $SHELL command.
    #!/bin/bash
    echo "init"
    export PATH=$PATH:/xxx/yyy/zzz # or do whatever you want
    $SHELL
    
    But that way you end up in a subshell. Sometimes it's unacceptable (Read 1) (Read 2).
  2. "terminal.integrated.shellArgs.linux": ["--init-file", "your_init_script.sh"]
    
    will leave you in the initial shell, but will not execute the .bashrc init file. So you may want to source ~/.bashrc inside your_init_script.sh
    #!/bin/bash
    source ~/.bashrc
    echo "init"
    export PATH=$PATH:/xxx/yyy/zzz # or do whatever you want
    
  3. And if you already have some_init_script.sh in a repository, and for some reason don't feel like adding source ~/.bashrc into it, you can use this:
    "terminal.integrated.shellArgs.linux": ["--init-file", "your_init_script.sh"]
    
    your_init_script.sh:
    #!/bin/bash
    source ~/.bashrc
    source some_init_script.sh
    
    some_init_script.sh:
    #!/bin/bash
    echo "init"
    export PATH=$PATH:/xxx/yyy/zzz # or do whatever you want
    

    Outside of VSCode you can do without creating extra file. Like this
    bash --init-file <(echo "source ~/.bashrc; source some_init_script.sh")
    
    But I could not pass this string into terminal.integrated.shellArgs.linux - it needs to be split into array somehow. And none of the combinations I've tried worked.

Also, you can open terminal at a specific folder:

terminal.integrated.cwd

Change env:

"terminal.integrated.env.linux"
"terminal.integrated.env.windows"
"terminal.integrated.env.osx"

And even change terminal to your liking with

terminal.integrated.shell.linux
terminal.integrated.shell.windows
terminal.integrated.shell.osx

Or

terminal.external.linuxExec
terminal.external.osxExec
terminal.external.windowsExec

I actually found a pretty neat Linux solution for this. It should also work on Windows if you use a shell like Bash. I'm not sure if it's possible using vanilla CMD.

Add something like this to your .bashrc or .zshrc:

#
# Allow parent to initialize shell
#
# This is awesome for opening terminals in VSCode.
#
if [[ -n $ZSH_INIT_COMMAND ]]; then
    echo "Running: $ZSH_INIT_COMMAND"
    eval "$ZSH_INIT_COMMAND"
fi

Now, in your VSCode workspace setting, you can set an environment variable like this:

"terminal.integrated.env.linux": {
    "ZSH_INIT_COMMAND": "source dev-environment-setup.sh"
}

Now the script "dev-environment-setup.sh" will be automatically sourced in all new VSCode terminal windows.

The other answer are great but a little outdated. You will get a warning in VSCode. Here is what I'm doing in my XXX.code-workspace file on linux:

    "terminal.integrated.profiles.linux": {
      "BashWithStartup": {
        "path": "bash",
        "args": [
          "--init-file",
          "./terminal_startup.sh"
        ]
      }
    },
    "terminal.integrated.defaultProfile.linux": "BashWithStartup"

Be sure to make sure your terminal_startup.sh script is executable:

chmod u+x terminal_startup.sh

For anyone using the wonderful cmder, you'll need something akin to the following in your settings.json

{
    "terminal.integrated.shell.windows": "cmd.exe",
    "terminal.integrated.env.windows": {
        "CMDER_ROOT": "C:\\path\\to\\cmder"
    },
    "terminal.integrated.shellArgs.windows": [
        "/k",
        "%CMDER_ROOT%\\vendor\\bin\\vscode_init.cmd"
    ],
}

And then you can add any aliases into the user_aliases.cmd file that should already exist in %CMDER_ROOT%\\config\\user_aliases.cmd

I use the following for powershell on Windows:

{
    "terminal.integrated.shellArgs.windows": [
        "-NoExit",
        "-Command", "conda activate ./env"
    ]
}

After much trial and error, the following worked for me on OSX:

"terminal.integrated.shellArgs.osx": [
    "-l",
    "-c",
    "source script.sh; bash"
],

For context, I'm using this with a jupyter notebook to set environment variables that cannot simply be defined using terminal.integrated.env.osx

After the April 2021 update the configuration structure has been changed. Check the documentation.
There's a distinction even between terminal instances. To run a file on Windows:

PowerShell

{
  "terminal.integrated.profiles.windows": {
    "My PowerShell": {
      "path": "pwsh.exe",
      "args": ["-noexit", "-file", "${env:APPDATA}PowerShellmy-init-script.ps1"]
    }
  },
  "terminal.integrated.defaultProfile.windows": "My PowerShell"
}

Command Prompt

{
  "terminal.integrated.profiles.windows": {
    "cmder": {
      "path": "C:\\WINDOWS\\System32\\cmd.exe",
      "args": ["/K", "C:\\cmder\\vendor\\bin\\vscode_init.cmd"]
    }
  },
  "terminal.integrated.defaultProfile.windows": "cmder"
}

If you use PowerShell you can add a PowerShell Script to your your profile in which you can execute what you want. Each development environment has 4 Profiles, stored in $Profile:

  • AllUsersAllHosts
  • AllUsersCurrentHost
  • CurrentUserAllHosts
  • CurrentUserCurrentHost

Eg create a profile in VSCode with

code $profile.CurrentUserAllHosts

Some more details

I did this for accessing x64 Native Tools Command Prompt for 2022:


{
    "terminal.integrated.profiles.windows": {
        "PowerShell": {
            "source": "PowerShell",
            "icon": "terminal-powershell"
        },
        "x64 Native": {
            "path": [
                "${env:windir}\\System32\\cmd.exe"
            ],
            "args": [
                "/K",
                "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat",
            ],
            "icon": "terminal-cmd"
        },
    },
    "terminal.integrated.defaultProfile.windows": "x64 Native",
}

Related