VS Code Make Offline Installer (Air-gapped Remote-SSH)
Prepare an offline, reproducible bundle that lets:
- •Desktop clients (Windows/macOS/Linux) install VS Code and extensions without internet, and
- •A headless Linux server run the matching VS Code Server, so Remote-SSH connects without downloading anything,
- •With extensions installed on the correct side (local UI vs remote extension host), pinned to known-good versions.
This skill assumes Microsoft VS Code + Remote-SSH (not Coder "code-server").
What to ask the user
- •Target release:
- •Either:
- •Explicit:
CHANNEL(stableorinsider), andCOMMIT(required), plus optionalVERSION, or - •Mirror local host:
TARGET_RELEASE=local-installed(agent discoversCHANNEL,VERSION,COMMIT, and local extensions)
- •Explicit:
- •Either:
- •Client targets:
- •OS + arch list (examples:
win32-x64-user,darwin-universal,linux-deb-x64) - •If unspecified, assume the client runs in the same environment as the host running this workflow.
- •If the host is headless, still assume the same OS family + arch as the host; assume the user will add a desktop environment themselves if needed.
- •OS + arch list (examples:
- •Server targets:
- •Linux arch list (
x64,arm64) - •You do not need to pre-decide the server user account; the install script supports
--user <username>and defaults to the executing user.
- •Linux arch list (
- •Extensions:
- •
extensions_local: extension IDs + pinned versions - •
extensions_remote: extension IDs + pinned versions - •Download policy (recommended): try Open VSX first, then Marketplace, else skip the extension
- •Required:
extensions_localmust includems-vscode-remote.remote-ssh
- •
- •Assumptions for this skill:
- •Clients have SSH access to servers (Remote-SSH is the connectivity path).
- •
taris available on the Linux server. - •Disable VS Code + extension auto-updates via the included post-install script.
Key invariants (don't skip)
- •VS Code "version" is not enough: Remote-SSH must match the client
COMMIT(build hash). - •Remote-SSH extension is mandatory on the client: air-gapped remote development over SSH requires
ms-vscode-remote.remote-sshto be installed locally from a.vsix. - •Remote-SSH offline requires cache placement on the remote server:
Remote-SSH boots a VS Code Server on the remote host. If the server for this exact
COMMITis missing, it normally downloads and extracts it during the first connection. In an air-gapped environment that download fails, so you must pre-place the tarballs/marker files and extracted server under~/.vscode-server/for the target user (the providedscripts/server/install-vscode-server-cache.shdoes this).- •
~/.vscode-server/vscode-cli-<COMMIT>.tar.gz.done - •
~/.vscode-server/vscode-server.tar.gz - •
~/.vscode-server/cli/servers/Stable-<COMMIT>/server/extracted contents
- •
- •Extensions have two installs:
- •Local UI side:
code --install-extension <file.vsix> - •Remote side:
~/.vscode-server/.../bin/code-server --install-extension <file.vsix>
- •Local UI side:
Outputs (recommended kit layout)
Create a single folder you can copy via USB/NAS:
vscode-airgap-kit/
README.md # installation instructions for the selected client/server platforms (generated)
manifest/ # metadata + inventories (what this kit contains)
vscode.json # commit/channel + downloaded artifacts + sha256
vscode.local.json # optional: discovery export from a host (channel/version/commit)
extensions.local.txt # local-side extension id@version pins
extensions.remote.txt # remote-side extension id@version pins
clients/ # VS Code desktop installers/archives per OS
windows/ # e.g., VSCodeUserSetup-*.exe
macos/ # e.g., VSCode-*.zip
linux/ # e.g., .deb/.rpm/.tar.gz
server/ # VS Code Server + CLI artifacts for air-gapped Remote-SSH
linux-x64/ # vscode-server-linux-x64-<COMMIT>.tar.gz
linux-arm64/ # vscode-server-linux-arm64-<COMMIT>.tar.gz
cli/ # vscode-cli-alpine-<arch>-<COMMIT>.tar.gz
extensions/ # offline extension bundles (.vsix)
local/ # install on the client (UI side): `code --install-extension`
remote/ # install on the server (extension host): `code-server --install-extension`
scripts/ # helper install/config scripts to run in each environment
wan/ # run on WAN-connected prep host
client/ # run on air-gapped desktop client
server/ # copy+run on air-gapped headless Linux server
Manifest example: references/vscode-airgap-manifest.example.json
Workflow
Script groups (3 parts)
This skill ships scripts in 3 groups:
- •WAN prep host (internet-connected):
- •
scripts/wan/discover-local-vscode.ps1— detect installed VS Codechannel/version/commitand export the local extension inventory. - •
scripts/wan/download-vscode-artifacts.ps1— download commit-pinned VS Code client installers/archives and the matching server+CLI tarballs into the kit, plus SHA256s. - •
scripts/wan/download-vsix-bundle.ps1— download pinned extension.vsixfiles for offline install (Open VSX first, Marketplace fallback) and write a report. - •
scripts/wan/write-kit-readme.ps1— writeREADME.mdinto the kit output directory with installation instructions for the selected client/server platforms (stagesscripts/client/+scripts/server/into the kit by default; disable via-NoStageScripts).
- •Air-gapped client (desktop):
- •Install VS Code:
- •Windows:
scripts/client/install-vscode-client.ps1— launch the offline installer (interactive by default;-Silentbest-effort). - •Linux (Ubuntu Desktop):
scripts/client/install-vscode-client.sh— install the offline.debviadpkg(recommended client artifact:linux-deb-<arch>).
- •Windows:
- •Install local extensions (client/UI side):
- •PowerShell:
scripts/client/install-vscode-client-extensions.ps1 - •Bash:
scripts/client/install-vscode-client-extensions.sh
- •PowerShell:
- •Configure VS Code (disable auto-updates + set
remote.SSH.localServerDownload):- •PowerShell:
scripts/client/configure-vscode-client.ps1 - •Bash:
scripts/client/configure-vscode-client.sh
- •PowerShell:
- •Cleanup packages (optional):
- •PowerShell:
scripts/client/cleanup-vscode-client.ps1 - •Bash:
scripts/client/cleanup-vscode-client.sh
- •PowerShell:
- •Air-gapped headless Linux server:
- •Install server cache + extract:
scripts/server/install-vscode-server-cache.sh— pre-place the server/CLI cache files and extract the server for the targetCOMMIT. - •Configure server state:
scripts/server/configure-vscode-server.sh— createdata/Machine/settings.json(optional override) and touch the.readymarker. - •Install remote extensions:
scripts/server/install-vscode-server-extensions.sh— install all.vsixin a folder into the remote extension host viacode-server. - •Cleanup old versions/cache (optional):
scripts/server/cleanup-vscode-server.sh— remove cache tarballs and/or old extracted servers once you’ve verified Remote-SSH works.
Installation, configuration, and cleanup are intentionally split because they have different purposes and options.
When preparing vscode-airgap-kit/, copy the relevant script folders from this skill into vscode-airgap-kit/scripts/ so they travel with the offline packages.
Windows note (agent vs user):
- •When the AI agent runs a
.ps1, use one-off execution policy bypass, e.g.pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File <script.ps1> ...(do not ask the user to change global ExecutionPolicy). - •For user-facing deliverables, keep a same-basename
.batlauncher next to each.ps1so end users can run it without dealing with ExecutionPolicy/permission issues.
0) Discovery option: mirror the host's currently installed VS Code release
If the user says to target the release currently used by the host, discover it first (do not guess).
Windows (PowerShell):
- •Run
scripts/wan/discover-local-vscode.ps1to exportVERSION,COMMIT, and the local extension list:- •Agent:
pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\wan\\discover-local-vscode.ps1 -OutDir .\\manifest - •User:
scripts\\wan\\discover-local-vscode.bat -OutDir .\\manifest - •Outputs:
- •
.\\manifest\\vscode.local.json - •
.\\manifest\\extensions.local.txt
- •
- •Ensure
ms-vscode-remote.remote-sshis installed locally before exporting if the offline client must use Remote-SSH.
- •Agent:
macOS (Terminal):
- •Stable:
- •
/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code --version
- •
- •Insiders:
- •
/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code-insiders --version
- •
- •Local extensions:
- •
code --list-extensions --show-versions > extensions.local.txt
- •
Linux (Terminal):
- •Version+commit:
- •
code --version(orcode-insiders --version)
- •
- •Local extensions:
- •
code --list-extensions --show-versions > extensions.local.txt
- •
Derive CHANNEL from which binary is used (code = stable, code-insiders = insider). Keep COMMIT as the compatibility key for server downloads.
If the user does not specify client targets, assume the client target matches the host OS family + arch (even if the host is currently headless).
1) Pick VERSION and COMMIT (match everything to COMMIT)
On any machine that can install VS Code with internet, install the exact VS Code build you intend to deploy, then record:
code --version
Keep:
- •Line 1:
VERSION(example:1.106.2) - •Line 2:
COMMIT(example:1e3c50d64110be466c0b4a45222e81d2c9352888)
If you must "standardize" across multiple client OSes, standardize on COMMIT (it is the real compatibility key for the server).
2) Download VS Code clients (Windows/macOS/Linux)
Download from the Microsoft update endpoint (commit-pinned):
https://update.code.visualstudio.com/commit:<COMMIT>/<PLATFORM>/<CHANNEL>
Common PLATFORM values:
- •Windows:
win32-x64-user,win32-arm64-user - •macOS:
darwin-universal(recommended),darwin-arm64 - •Linux:
- •Archives:
linux-x64,linux-arm64 - •Debian/Ubuntu:
linux-deb-x64,linux-deb-arm64 - •RHEL/Fedora:
linux-rpm-x64,linux-rpm-arm64
- •Archives:
Save the downloaded files under clients/<os>/ and record SHA256 hashes in manifest/vscode.json.
Optional helper (WAN prep) to download commit-pinned artifacts and write manifest/vscode.json:
pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\wan\\download-vscode-artifacts.ps1 `
-Commit "<COMMIT>" -Channel stable -OutDir .\\vscode-airgap-kit `
-ClientPlatforms @("win32-x64-user") `
-ServerArch @("x64","arm64")
3) Download VS Code Server + VS Code CLI (Linux)
Download the server tarballs (commit-pinned):
https://update.code.visualstudio.com/commit:<COMMIT>/server-linux-x64/<CHANNEL> https://update.code.visualstudio.com/commit:<COMMIT>/server-linux-arm64/<CHANNEL>
Download the CLI tarballs (commit-pinned):
https://update.code.visualstudio.com/commit:<COMMIT>/cli-alpine-x64/<CHANNEL> https://update.code.visualstudio.com/commit:<COMMIT>/cli-alpine-arm64/<CHANNEL>
Put them under:
- •
server/linux-x64/andserver/linux-arm64/ - •
server/cli/
4) Freeze and download extensions as .vsix (local + remote)
Pin versions first, then download .vsix files.
Required client extension for SSH remote development:
- •
ms-vscode-remote.remote-ssh(do not skip)
Recommended "pinning" flow (do this on an online staging environment):
- •Install VS Code client (
COMMIT) on a desktop. - •Connect to a similar Linux server once (online) and install/configure extensions until it works.
- •Export the exact extension versions:
- •Local:
code --list-extensions --show-versions > extensions.local.txt - •Remote (over SSH): run the server's
code-serverbinary:- •
~/.vscode-server/cli/servers/Stable-<COMMIT>/server/bin/code-server --list-extensions --show-versions - •Save output as
extensions.remote.txt
- •
- •Local:
Downloading .vsix (preferred order):
- •
- •Open VSX (https://open-vsx.org/) (preferred when available):
- •
ovsx get publisher.extension@<version> -o <file>.vsix
- •
- •Marketplace fallback:
- •Use the Marketplace "vspackage" endpoint (as implemented by
scripts/wan/download-vsix-bundle.ps1):- •
https://marketplace.visualstudio.com/_apis/public/gallery/publishers/<publisher>/vsextensions/<name>/<version>/vspackage
- •
- •
- •If neither source has the extension, skip it and record it in your manifest/logs.
- •If you expected it to exist but the links/endpoints look broken (404/redirect loops), try a quick web search for the extension ID + version + “vsix” and update the download URL/source notes you store in the manifest.
Optional helper (Windows-friendly) to download pinned VSIX in bulk:
pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\wan\\download-vsix-bundle.ps1 -InputList .\\manifest\\extensions.local.txt -OutDir .\\extensions\\local pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\wan\\download-vsix-bundle.ps1 -InputList .\\manifest\\extensions.remote.txt -OutDir .\\extensions\\remote -RequiredIds @()
Place downloaded .vsix files into:
- •
extensions/local/ - •
extensions/remote/
Validate every .vsix is a ZIP (fast corruption check):
- •
unzip -t file.vsix(Linux/macOS) or - •
python -c "import zipfile; zipfile.ZipFile('file.vsix').testzip()"(any)
Generate an install README in the kit output directory (recommended):
# Agent pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\wan\\write-kit-readme.ps1 -KitDir .\\vscode-airgap-kit # User (double-click friendly) scripts\\wan\\write-kit-readme.bat -KitDir .\\vscode-airgap-kit
5) README content: install VS Code on air-gapped clients (desktop)
Agent note: you typically cannot run client-side steps on an air-gapped desktop. Instead, generate a
README.mdin the kit output dir that contains these instructions (usescripts/wan/write-kit-readme.ps1).
On each client OS:
- •Install VS Code from the offline installer/archive.
- •Disable update checks + extension auto-updates (required for air-gapped stability):
- •Run the post-install config script:
- •
pwsh -NoProfile -File scripts\\client\\configure-vscode-client.ps1 -Channel auto - •
bash scripts/client/configure-vscode-client.sh --channel auto
- •
- •Run the post-install config script:
- •Install local extensions:
- •
code --install-extension /path/to/extensions/local/<x>.vsix --force
- •
Recommended split scripts on the air-gapped client:
Windows (PowerShell):
# 1) Install VS Code (best-effort automation; Windows supported) pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\client\\install-vscode-client.ps1 -InstallerPath .\\clients\\windows\\VSCodeUserSetup-x64-*.exe # 2) Configure VS Code settings (disable updates, set Remote-SSH behavior) pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\client\\configure-vscode-client.ps1 -Channel auto # 3) Install local extensions from VSIX (includes required Remote-SSH) pwsh -NoLogo -NoProfile -ExecutionPolicy Bypass -File scripts\\client\\install-vscode-client-extensions.ps1 -ExtensionsDir .\\extensions\\local -Channel auto
Linux (Ubuntu Desktop) / macOS (Bash):
# 1) Install VS Code from an offline package (Ubuntu: .deb) bash scripts/client/install-vscode-client.sh --installer-path ./clients/linux/*.deb # 2) Configure VS Code settings (disable updates, set Remote-SSH behavior) bash scripts/client/configure-vscode-client.sh --channel stable # 3) Install local extensions from VSIX (includes required Remote-SSH) bash scripts/client/install-vscode-client-extensions.sh --extensions-dir ./extensions/local --channel stable
Remote-SSH settings guidance:
- •Fully air-gapped (server already has cache files): set
"remote.SSH.localServerDownload": "off" - •Client online but server offline (rare): set
"remote.SSH.localServerDownload": "always"
6) README content: install VS Code Server on headless Linux (air-gapped)
Agent note: you typically cannot run server-side steps on the air-gapped host. Instead, generate a
README.mdin the kit output dir that contains these instructions (usescripts/wan/write-kit-readme.ps1).
Prefer the cache-based method so Remote-SSH never attempts downloads.
Copy the scripts/server/ folder to the headless server and run the scripts there.
Recommended split scripts on the server:
# 1) Install (place cache files + extract server) sudo bash scripts/server/install-vscode-server-cache.sh \ --commit "<COMMIT>" --user "<USERNAME>" \ --server-tar "/path/to/vscode-server-linux-x64-<COMMIT>.tar.gz" \ --cli-tar "/path/to/vscode-cli-alpine-x64-<COMMIT>.tar.gz" # 2) Configure (create settings.json, touch .ready) sudo bash scripts/server/configure-vscode-server.sh --commit "<COMMIT>" --user "<USERNAME>" # Optional: provide a prebuilt settings.json # sudo bash scripts/server/configure-vscode-server.sh --commit "<COMMIT>" --user "<USERNAME>" --settings-file "/path/to/settings.json" # 3) Install remote-side extensions (safe to re-run for updates) sudo bash scripts/server/install-vscode-server-extensions.sh \ --commit "<COMMIT>" --user "<USERNAME>" \ --extensions-dir "/path/to/extensions/remote"
Notes:
- •If
--useris omitted, it installs for the executing user. - •If
--useris different from the executing user, run the script as root/admin (or viasudo) so it can write into that user's home and fix ownership.
Option B: manual placement (must match filenames exactly):
- •Copy CLI tarball to
~/.vscode-server/vscode-cli-<COMMIT>.tar.gz - •Duplicate it to
~/.vscode-server/vscode-cli-<COMMIT>.tar.gz.done - •Copy server tarball to
~/.vscode-server/vscode-server.tar.gz - •Extract server to
~/.vscode-server/cli/servers/Stable-<COMMIT>/server/(strip top-level folder)
7) Verify end-to-end (no downloads)
On the server:
- •
test -f ~/.vscode-server/vscode-cli-<COMMIT>.tar.gz.done - •
test -f ~/.vscode-server/vscode-server.tar.gz - •
test -x ~/.vscode-server/cli/servers/Stable-<COMMIT>/server/bin/code-server - •
~/.vscode-server/cli/servers/Stable-<COMMIT>/server/bin/code-server --list-extensions --extensions-dir ~/.vscode-server/extensions
From a desktop client:
- •Connect via "Remote-SSH: Connect to Host..."
- •Watch the Remote-SSH output: it should report it found an existing installation and should not attempt downloads.
Common failure modes
- •Client/server mismatch:
COMMITdiffers -> client tries to download a different server build. - •Wrong filenames:
vscode-server-linux-x64-<COMMIT>.tar.gzis not detected unless it is copied/renamed to~/.vscode-server/vscode-server.tar.gz. - •Wrong architecture: x64 server tarball on arm64 host (or vice versa).
- •Extensions not visible remotely: installed only on the client; install them via server
code-servertoo (or install "from VSIX" while connected to the remote window).
Updating (client and server)
When you need to update VS Code (new COMMIT) and/or extension versions:
- •
On the WAN prep host:
- •Re-run
scripts/wan/download-vscode-artifacts.ps1for the new commit and overwrite the kit (or produce a new kit folder). - •Re-run
scripts/wan/download-vsix-bundle.ps1for updated pinned extension lists.
- •Re-run
- •
On the air-gapped client:
- •Re-run
scripts/client/install-vscode-client.ps1(Windows) orscripts/client/install-vscode-client.sh(Linux) with the new installer/package. - •Re-run
scripts/client/configure-vscode-client.ps1orscripts/client/configure-vscode-client.sh(idempotent). - •Re-run
scripts/client/install-vscode-client-extensions.ps1orscripts/client/install-vscode-client-extensions.shwith updated VSIX (forces install).
- •Re-run
- •
On the headless server:
- •Run
scripts/server/install-vscode-server-cache.sh --commit <NEW_COMMIT> ...(keeps old extracted servers unless you later clean up). - •Run
scripts/server/configure-vscode-server.sh --commit <NEW_COMMIT> ... - •Run
scripts/server/install-vscode-server-extensions.sh --commit <NEW_COMMIT> ...(forces extension installs). - •Optionally remove old commits/cache with
scripts/server/cleanup-vscode-server.shafter verification.
- •Run