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

10

53

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?

Ferwerda answered 11/8, 2017 at 12:23 Comment(0)
H
24

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
Heymann answered 19/11, 2021 at 2:22 Comment(2)
Also as the other answer says, it's likely you want source ~/.bashrc in your terminal_startup.sh file.Eclampsia
And if you don't chmod u+x terminal_startup.sh it'll just silently skip the terminal_startup.sh script rather than erroring (there's probably a log with a message)Demount
G
34

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
Glaze answered 27/2, 2020 at 17:6 Comment(8)
Surely there has to be more to this answer? If you just set shellArgs.linux to a script, won't the shell just execute the script and exit?Brookins
After a little bit of digging found a better solution: --init-file. Updated the answer. Also that may be helpful serverfault.com/questions/368054/…Glaze
Well, the man page says Execute commands from file instead of the standard personal initialization file ~/.bashrc if the shell is interactiveBrookins
@Hubro, you're right. That took me a while. But I think I've made it. Updated the answer.Glaze
Note that to add ["--init-file", "your_init_script.sh"] in the settings ui (not the json) you need to add --init-file and your_init_script.sh as two separate items.Schlessinger
This is a very thorough answer. Kudos to you!Carpentaria
terminal.integrated.shellArgs is now deprecated - see @Robert's answer below for a modern solution.Matrix
What I needed to see was the .bashrc file name. And with it, I could make the updates I needed.Twicetold
B
34

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.

Brookins answered 27/2, 2020 at 17:12 Comment(6)
Really interesting! Thanks for sharing @BrookinsAgni
It looks nicer than my answer. But wouldn't it require editing .bashrc of every team member? And so require extra work, extra documentation, and can even introduce conflicts, if ZSH_INIT_COMMAND (or any name for that matter) already in use in someone's .bashrc.Glaze
@Glaze Yes, but that's fine. The only part of this that is shared with the team is the dev session setup script. Everything else is local to my PC. My team members can choose to source the script manually, or they can replicate my setup if they want.Brookins
This is so elegant! Thanks man!Diplomacy
This is the only answer that works with zsh (which has no --init-file equivalent) AND doesn't initiate a sub-shell. Very nice solution, other than the downside mentioned by x00 in the earlier comment.Detour
@Detour this seems to work for me: "args": [ "-c", "source ${workspaceFolder}/.vscode/terminal/zsh-init.sh; zsh" ]Yeasty
H
24

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
Heymann answered 19/11, 2021 at 2:22 Comment(2)
Also as the other answer says, it's likely you want source ~/.bashrc in your terminal_startup.sh file.Eclampsia
And if you don't chmod u+x terminal_startup.sh it'll just silently skip the terminal_startup.sh script rather than erroring (there's probably a log with a message)Demount
W
20

You can do the following:

"terminal.integrated.shellArgs.windows": ["start-ssh-agent.cmd"]

Modified from: https://code.visualstudio.com/docs/editor/integrated-terminal#_shell-arguments

Whimwham answered 11/8, 2017 at 13:0 Comment(2)
use /K command to process command as an immediate command in terminal such as set CLASSPATH, ["/K", "C:\\cmder\\vendor\\init.bat"]Wallpaper
This solution is now deprecated. The actual solution in current VSCode versions is to use Automation Profiles, like mentioned in this thread by Robert in https://mcmap.net/q/337551/-vscode-how-to-run-a-command-after-each-terminal-openNekton
I
4

I use the following for powershell on Windows:

{
    "terminal.integrated.shellArgs.windows": [
        "-NoExit",
        "-Command", "conda activate ./env"
    ]
}
Integrated answered 9/4, 2020 at 11:44 Comment(1)
No longer works; key is now "terminal.integrated.profiles.windows; see stackoverflow.com/a/71512662.Trunk
W
3

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

Waterborne answered 16/12, 2019 at 23:5 Comment(0)
O
3

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"
}
Overtop answered 17/3, 2022 at 12:54 Comment(0)
T
1

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

Tussore answered 25/2, 2020 at 15:42 Comment(0)
A
1

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

Armyworm answered 12/11, 2020 at 4:27 Comment(0)
F
1

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",
}

Fibrovascular answered 7/9, 2022 at 19:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.