Managing VSCode Extensions

The last several years Microsoft’s Visual Studio Code (VSCode) is my favorite text editor. Thanks to the amazing “LaTeX Workshop” plugin, I started using it as a LaTeX editor to write my research papers, and eventually I moved most of my everyday routines there. Currently, I use it for Python and Rust (I’ve just started) development, web development. Even this post I write in this editor due to its great support of markdown language.

The opportunity to use one editor for so many different tasks is made possible by its great plugin subsystem and all those people, who have been spending hours and hours (thank you!!!) to develop wonderful extensions. With the lapse of time, your Extensions side bar tab will be populated with tens of different extensions, which are quite difficult to remember all. In this post, I will explain how to manage extensions, in particular, how to list all installed extensions, download them for offline use, and install them.

The code snippets are also available in the GitHub repository.

Update 27/09/2020: You can share and synchronize your extensions, settings and keybindings, using Settings Sync feature. However, the approach described in this post still can be used if you need to deploy VSCode with the extensions on a machine that does not have Internet connection.
Table of Contents

Prerequisites

I assume that you run a Linux operating system with VSCode installed. I tested the code snippets in the Kubuntu 18.04 operating system, however, most probably the code should work in majority Linux distributions with the Bash shell.

VSCode provides several useful commands in order to work with extensions.

$ code --list-extensions
$ code --install-extension {extension id}
$ code --uninstall-extension {extension id}
$ code --disable-extensions

The first command is used to list all the installed extensions. Obviously, the second and the third commands are used to install and uninstall an extension correspondingly. The forth command is used to launch VSCode with all extensions disabled. This is useful if you experience a bug, and you want to test if it is caused by an extension. In what follows, we will rely mostly on the first two commands.

Listing Installed Extensions

I recommend to dump the list of installed extensions from time to time. This will help you to restore them quickly in case of fresh installation. For instance, currently on my system I have more than 50 plugins installed. Of course, it is quite difficult to remember the list of all installed applications, and definitely it will take me a lot of time to restore them all if something happens with my installation.

As it was mentioned in the beginning of the post, you can list VSCode extensions using code --list-extensions command. Besides just listing the installed plugins, I also recommend to dump the list into a file using the following command:

$ code --list-extensions > extensions.txt

You can re-run this command from time to time to have the updated list of the installed extensions. The code snippets below rely on this file to install extensions.

Installing Listed Extensions

Once you have a file with the extensions list, you can install them in batch mode using the following script. Of course, before running this script you need to have VSCode installed in your system.

#!/usr/bin/env bash

REGEX='^([_0-9a-zA-Z\-]+)\.([_0-9a-zA-Z\-]+)'

if [[ -z "$1" ]]; then
    list_file=`realpath "extensions.txt"`
else
    list_file=`realpath "$1"`
fi
if [ -f $list_file ]; then
    echo "File $list_file exists."
else
    echo "File $list_file does not exist."
    return
fi

while read extension_line; do
    echo "$extension_line"
    if [[ $extension_line =~ $REGEX ]]
    then
        echo "Installing $extension_line"
        code --install-extension "$extension_line"
    else
        echo "Something wrong!"
    fi
done < $list_file

Basically, this script obtains the path to a file with a list of extensions as an argument. Then, it iterates over the lines and checks the name of the extension match a predefined format. If it matches, it tries to install the extensions using code --install-extension command. You can run this script in the following way (if you run them from the cloned GitHub repository).

$ source install_exts_online.sh <path_to_exts_file>

If the path to a file with a list of extensions <path_to_exts_file> is not provided, the script will try to find extensions.txt in the current working directory by default.

Managing Extensions Offline

Of course, the script from the previous section you can run only if your machine is connected to the Internet. In this case, the extensions are downloaded and installed. However, sometimes you want to use the same list of extensions on the machines that are not connected to the global network. For instance, now it is common to have isolated internal networks of hosts not connected to the Internet due to the security reasons. Still, even on the machines in such networks you would like to use the same set of familiar tools. In such a case, you can download all the extensions from the Internet, copy them to the isolated host, and install them. The VSCode plugins have a predefined extension .vsix.

Downloading Extensions

In order to get an extensions from the Internet, the script relies on curl. So I assume that you have this utility installed in your system.

To download extensions, you can use the following script:

#!/usr/bin/env bash

REGEX='^([_0-9a-zA-Z\-]+)\.([_0-9a-zA-Z\-]+)'

if [[ -z "$1" ]]; then
    list_file=`realpath "extensions.txt"`
else
    list_file=`realpath "$1"`
fi
if [ -f $list_file ]; then
    echo "File $list_file exists."
else
    echo "File $list_file does not exist."
    return
fi

[[ -z "$2" ]] && output_dir="$(pwd)/plugins" || output_dir="$2"
mkdir -p ${output_dir}

while read extension_line; do
    echo "$extension_line"
    if [[ $extension_line =~ $REGEX ]]
    then
        publisher=${BASH_REMATCH[1]}
        extension=${BASH_REMATCH[2]}
        version="latest"
        echo "Downloading: $publisher.$extension"
        url="https://${publisher}.gallery.vsassets.io/_apis/public/gallery/publisher/${publisher}/extension/${extension}/${version}/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage"
        output="${output_dir}/${publisher}.${extension}.vsix"
        curl -o "${output}" ${url}
    else
        echo "Something wrong!"
    fi
done < $list_file

The script downloads the list of extensions listed in the file provided as the first argument into the directory, the path to which provided as the second argument. You can run the script in the following way:

$ source download_vsix.sh <path_to_exts_file> <path_to_output_dir>

If the path to a file with a list of extensions <path_to_exts_file> is not provided, the script will try to find extensions.txt in the current working directory by default. Similarly, if the path to output dir <path_to_output_dir> is not there, the script will create plugins/ subdirectory in the current working directory and will store extensions there.

Installing Extensions from VSIX Files

Once the extensions are downloaded, you can install them from VSCode. If you want to install one extension, it is better to use the functionality built in the editor. In order to install an extension, open VSCode and go to the Extensions view (Ctrl+Shift+X). In the upper right corner of the view, click on “…” and select menu item “Install from VSIX…” (see Figure 1). After that just select the extension from the directory.

Install from VSIX
Install from VSIX

If you want to install all extensions from a directory with the extensions, you can use the following script:

#!/usr/bin/env bash

VSIX_FILES="*.vsix"

if [[ -z "$1" ]]; then
    vsix_dir="$(pwd)/plugins"
else
    vsix_dir=`realpath "$1"`
fi
if [[ ! -d $vsix_dir ]]; then
    echo "$vsix_dir is not a directory! Exiting!"
    return
fi

for i in $vsix_dir/$VSIX_FILES; do
    [ -f "$i" ] || break
    echo "Installing $i"
    code --install-extension $i
done

This script looks for .vsix files in the provided directory and install them one by one. By default, the script tries to look for the files in the plugins subdirectory of the current working directory. You can run this script using the following call:

$ source install_vsix_offline.sh <path_to_dir_with_vsixs>

It is also possible to copy all your installed extensions with the configurations. In order to do this, you should copy the whole $HOME/.vscode/extensions directory. In this directory, VSCode stores already installed and configured extensions, and you can simply side-load them to another machine. However, be careful some extensions may store some private data in their configuration.

Conclusion

These scripts were developed in order to get VSCode with all my extensions to be installed on a host in the air-gapped network. You can find them all in this GitHub repository.

Related