Skip to content

Instantly share code, notes, and snippets.

@matteosecli
Last active July 7, 2026 23:56
Show Gist options
  • Select an option

  • Save matteosecli/2a6f34cd151527ff28aaa516274a3a61 to your computer and use it in GitHub Desktop.

Select an option

Save matteosecli/2a6f34cd151527ff28aaa516274a3a61 to your computer and use it in GitHub Desktop.
Download the latest VS Code Server (official distribution)
#!/bin/sh
# Note: consider using bash with "set -euo pipefail"
set -eu
# Decide whether to install the SSH remote server (-ssh),
# the web one (-web), or both (if no argument is given).
INSTALL_SSH=1
INSTALL_WEB=1
if [ "$#" -gt 0 ]; then
INSTALL_SSH=0
INSTALL_WEB=0
for arg in "$@"; do
case "$arg" in
-ssh) INSTALL_SSH=1 ;;
-web) INSTALL_WEB=1 ;;
-h|-help|--help)
printf 'Usage: %s [-ssh] [-web]\n' "$0" >&2
exit 0
;;
*)
printf 'error: unknown option: %s\n' "$arg" >&2
printf 'Usage: %s [-ssh] [-web]\n' "$0" >&2
exit 1
;;
esac
done
fi
# If OSTYPE is not set (e.g. in sh), try to set it.
if [ -z "${OSTYPE:-}" ]; then
OSTYPE="$(uname -s | tr '[:upper:]' '[:lower:]')"
fi
case "$OSTYPE" in
linux*) CODE_OS="linux"; CODE_CLI_OS="alpine" ;;
darwin*) CODE_OS="darwin"; CODE_CLI_OS="darwin" ;;
*) echo >&2 "error: OS ($OSTYPE) is not supported"; exit 1 ;;
esac
ARCH="$(uname -m)"
case "$ARCH" in
amd64|x86_64) CODE_ARCH="x64" ;;
arm64|aarch64|armv8) CODE_ARCH="arm64" ;;
armv6|armv7) CODE_ARCH="armhf" ;;
*) echo >&2 "error: architecture ($ARCH) is not supported"; exit 1 ;;
esac
if [ "${CODE_CLI_OS}" = "darwin" ] && [ "${CODE_ARCH}" = "x64" ]; then
CODE_PLATFORM="${CODE_CLI_OS}"
CODE_CLI_PLATFORM="${CODE_CLI_OS}"
else
CODE_PLATFORM="${CODE_OS}-${CODE_ARCH}"
CODE_CLI_PLATFORM="${CODE_CLI_OS}-${CODE_ARCH}"
fi
TMP_FILES=""
cleanup() {
rm -f ${TMP_FILES}
}
trap cleanup EXIT
# Note: bsdtar seems to have trouble preserving permissions when extracting from a pipe
downloadArchiveToDir() {
FILE_URL=$1
DEST_DIR=$2
EXTRA_ARGS=${3:-}
mkdir -p ${DEST_DIR}
VSC_TMP_FILE=$(mktemp -t vsc_dl.XXXXXX)
TMP_FILES="${TMP_FILES} ${VSC_TMP_FILE}"
curl -sSL "${FILE_URL}" -o ${VSC_TMP_FILE}
tar -xpf ${VSC_TMP_FILE} -C ${DEST_DIR} ${EXTRA_ARGS}
}
# Note: there are other ways to get the COMMIT_ID, but it's useful to have the full CLI anyway.
# Alternatives:
# - COMMIT_ID=$(curl -sL "https://update.code.visualstudio.com/api/latest/linux-x64/stable" | grep -oEi '"version":\s*"[a-f0-9]{40}"' | cut -d'"' -f4)
# - COMMIT_ID=$(curl -sL "https://update.code.visualstudio.com/api/latest/linux-x64/stable" | jq -r .version)
# - COMMIT_ID=$(curl -sIL "https://update.code.visualstudio.com/latest/server-linux-x64-web/stable" | grep -i location | grep -oE '[a-f0-9]{40}')
# And then, once we have the COMMIT_ID needed to create the correct output directory, we can just e.g.:
# - downloadArchiveToDir "https://update.code.visualstudio.com/latest/server-linux-x64-web/stable" "${CODE_SERVER_WEB_DIR}" "--strip-components 1"
echo "Downloading VS Code CLI..."
CODE_CLI_DIR=${HOME}/.vscode-cli/bin
CODE_CLI=${CODE_CLI_DIR}/code
downloadArchiveToDir "https://code.visualstudio.com/sha/download?build=stable&os=cli-${CODE_CLI_PLATFORM}" "${CODE_CLI_DIR}"
COMMIT_ID=$(${CODE_CLI} --version | grep -oE '[a-f0-9]{40}')
if [ "${INSTALL_SSH}" -eq 1 ]; then
echo "Downloading VS Code Server..."
CODE_SERVER_DIR=${HOME}/.vscode-server/bin/${COMMIT_ID}
downloadArchiveToDir "https://update.code.visualstudio.com/commit:${COMMIT_ID}/server-${CODE_PLATFORM}/stable" "${CODE_SERVER_DIR}" "--strip-components 1"
fi
if [ "${INSTALL_WEB}" -eq 1 ]; then
echo "Downloading VS Code Server Web..."
CODE_SERVER_WEB_DIR=${HOME}/.vscode/cli/serve-web/${COMMIT_ID}
downloadArchiveToDir "https://update.code.visualstudio.com/commit:${COMMIT_ID}/server-${CODE_PLATFORM}-web/stable" "${CODE_SERVER_WEB_DIR}" "--strip-components 1"
fi
echo "Done!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment