Skip to content

Instantly share code, notes, and snippets.

@joeblackwaslike
Last active December 2, 2025 09:02
Show Gist options
  • Select an option

  • Save joeblackwaslike/2767cc00b6aa45a15f5369f7189260a0 to your computer and use it in GitHub Desktop.

Select an option

Save joeblackwaslike/2767cc00b6aa45a15f5369f7189260a0 to your computer and use it in GitHub Desktop.
Automatically install vscode extensions listed in external file

VSCode Extension Installer

Usage

Remote (no download necessary)

curl -fsSL "https://gist.githubusercontent.com/joeblackwaslike/2767cc00b6aa45a15f5369f7189260a0/raw/24e8b0e627d9520d40480000d548f9cdc3e96ed8/install-vscode-exts.sh" | bash -s -- --helper code-insiders
#!/usr/bin/env bash
# ============================================================================
# Maintainer: Joe Black
# Contact: https://github.com/joeblackwaslike
#
# Copyright (c) 2025 Joe Black
#
# License: MIT
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# In short: Do what you want, just credit Joe Black. For questions, suggestions,
# or contributions, reach out via GitHub.
# ============================================================================
# Function to display usage/help message
show_usage() {
local script_name
script_name="$(basename "$0")"
echo "Usage: $script_name [--input-file <file>] [--helper <helper>]"
echo -e "\n--input-file <file|https-url>: Path or https URL to a file containing one VS Code extension ID per line (default: https://gist.githubusercontent.com/joeblackwaslike/2767cc00b6aa45a15f5369f7189260a0/raw/f6d50ca759f5ac0d5182c2701bb6f9586917f76c/vscode-exts.txt)."
echo -e "\n--helper <helper>: CLI helper command to use for installing extensions (default: code)."
echo -e "\nThis script installs the latest extension from the microsoft marketplace for each extension ID listed in the input file."
}
# Function to display error and usage, then exit
error_and_usage() {
echo "Error: $1"
show_usage
exit 1
}
# Default values for CLI flags
input_file="https://gist.githubusercontent.com/joeblackwaslike/2767cc00b6aa45a15f5369f7189260a0/raw/f6d50ca759f5ac0d5182c2701bb6f9586917f76c/vscode-exts.txt"
helper="code"
# Temp directory for remote downloads. Empty means no temp dir used.
temp_dir=""
# Parse arguments
if [[ "$1" == "--help" ]]; then
show_usage
exit 0
fi
# Parse CLI flags
while [[ $# -gt 0 ]]; do
case "$1" in
--input-file)
input_file="$2"
shift 2
;;
--helper)
helper="$2"
shift 2
;;
*)
error_and_usage "Unknown argument: $1"
;;
esac
done
# If input_file is an https URL, download it to a temp directory and use that file
# We clean up the temp directory on exit (success or failure).
if [[ "$input_file" =~ ^https:// ]]; then
# Ensure curl exists. We use curl for simple, reliable downloads.
if ! command -v curl >/dev/null 2>&1; then
error_and_usage "curl is required to fetch remote input files over https"
fi
# Create a temp directory. We store the fetched file here.
temp_dir="$(mktemp -d -t vscode-exts.XXXXXXXX)" || error_and_usage "Failed to create temporary directory"
# Define cleanup function and register EXIT trap right after we create temp_dir
cleanup() {
# Only remove if we actually created it
if [[ -n "$temp_dir" && -d "$temp_dir" ]]; then
rm -rf "$temp_dir"
fi
}
trap cleanup EXIT
# Destination path for the downloaded list
remote_list="$temp_dir/vscode-exts.txt"
# Fetch the URL. -f fails on HTTP errors. -s silent. -S shows errors. -L follows redirects.
if ! curl -fSsL "$input_file" -o "$remote_list"; then
error_and_usage "Failed to download input file from URL: $input_file"
fi
# Point input_file to the downloaded local file
input_file="$remote_list"
fi
# Check if input file exists
if [[ ! -f "$input_file" ]]; then
error_and_usage "File '$input_file' not found!"
fi
# Read file line by line and process each extension ID
while IFS= read -r extensionId; do
# Skip empty lines and lines starting with # (comments)
if [[ -z "$extensionId" || "$extensionId" =~ ^# ]]; then
continue
fi
# Validate extensionId format (should be publisher.name)
if ! [[ "$extensionId" =~ ^[^.]+\.[^.]+$ ]]; then
echo "Warning: Skipping invalid extension ID: $extensionId"
continue
else
echo "Installing extension from marketplace: $extensionId"
$helper --install-extension "$extensionId"
fi
done < "$input_file"
# Codeium.codeium
# GitHub.copilot
# GitHub.copilot-chat
alefragnani.Bookmarks
alefragnani.project-manager
Amerey.markdown-math-snippets
antfu.vite
Anthropic.claude-code
bierner.markdown-checkbox
bierner.markdown-emoji
bierner.markdown-footnotes
bierner.markdown-mermaid
bierner.markdown-preview-github-styles
bierner.markdown-yaml-preamble
bradlc.vscode-tailwindcss
burkeholland.simple-react-snippets
charliermarsh.ruff
christian-kohler.npm-intellisense
ConradLudgate.rust-playground
DavidAnson.vscode-markdownlint
dbaeumer.vscode-eslint
donjayamanne.githistory
eamodio.gitlens
EditorConfig.EditorConfig
esbenp.prettier-vscode
fill-labs.dependi
frhtylcn.pythonsnippets
gel.edgedb
GitHub.github-vscode-theme
github.vscode-github-actions
GitHub.vscode-pull-request-github
golang.go
Gruntfuggly.todo-tree
Jacano.vscode-pnpm
jannchie.ruff-ignore-explainer
JScearcy.rust-doc-viewer
kaih2o.python-resource-monitor
KevinRose.vsc-python-indent
leighlondon.eml
lextudio.restructuredtext
linear.linear-connect
LyonSyonII.rust-syntax
matt-meyers.vscode-dbml
mechatroner.rainbow-csv
MeshIntelligentTechnologiesInc.pieces-vscode
mhutchie.git-graph
ms-azuretools.vscode-containers
ms-python.debugpy
ms-toolsai.jupyter
ms-vscode-remote.remote-containers
ms-vscode-remote.remote-ssh
ms-vscode.cpptools
ms-vscode.cpptools-extension-pack
ms-vscode.makefile-tools
ms-vscode.remote-server
ms-vscode.vscode-speech
ms-vscode.vscode-typescript-next
mtxr.sqltools
mtxr.sqltools-driver-mysql
mtxr.sqltools-driver-pg
nortakales.flipper-zero-syntax-highlighting
redhat.vscode-xml
redhat.vscode-yaml
Redis.redis-for-vscode
reduckted.vscode-gitweblinks
remcohaszing.schemastore
rust-lang.rust-analyzer
samuelcolvin.jinjahtml
SanjulaGanepola.github-local-actions
Supabase.vscode-supabase-extension
tamasfe.even-better-toml
timonwong.shellcheck
tomoki1207.pdf
trond-snekvik.simple-rst
vitest.explorer
vsls-contrib.gistfs
wilsonsio.color-vision
zhouronghui.propertylist
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment