Starting a VSCode Devcontainer via Shortcut

on 2026-10-16 automatically translated

How can you open a VSCode project directly in a Devcontainer (within WSL), without first opening the project and then using 'Reopen in Devcontainer'? Sure, you can use 'Open Recent', but there you only see the most recent projects and still have to wait for the initial loading of the 'empty' VSCode.

code.exe has a --remote parameter. The syntax for a devcontainer is:

code.exe --remote dev-container+<hex json blob><linux path in devcontainer> <linux path in devcontainer>

The JSON blob is called the 'authority' and has the following contents:

{
  "hostPath": "\\\\wsl.localhost\\<WSL Name>\\<path in WSL with backslashes>",
  "localDocker": false,
  "configFile": {
    "$mid": 1,
    "path": "/<linux path in WSL>/.devcontainer/devcontainer.json",
    "scheme": "vscode-fileHost"
  }
}

You can generate the blob with the script below, for example:

python open_devcontainer.py Ubuntu-26.04 /home/me/my/workspace

or start VSCode directly with --exec.

MSYS_NO_PATHCONV=1 python open_devcontainer.py Ubuntu-22.04 /home/me/my/workspace --exec

I always use git bash / msys / mingw, and there it is important that the 'linux' path is not automatically converted to a Windows path. That's why the MSYS_NO_PATHCONV=1 environment variable is used. --show displays the JSON blob in plain text. This lets you check whether the path is correct.

open_devcontainer.py

#!/usr/bin/env python3
"""Generate the VS Code dev-container remote authority for a folder in WSL.

Usage: open_devcontainer.py <wsl-distro> <path-in-wsl> [--exe PATH] [--exec] [--show]
Example: open_devcontainer.py Ubuntu-22.04 /home/dseemer/clones/lzb_ocie2_sim
"""
import argparse
import json
import os
import posixpath
import subprocess


def build_authority(distro: str, wsl_path: str, show=False) -> tuple[str, str]:
  wsl_path = posixpath.normpath(wsl_path)
  host_path = "\\\\wsl.localhost\\" + distro + wsl_path.replace("/", "\\")
  payload = {
    "hostPath": host_path,
    "localDocker": False,
    "configFile": {
      "$mid": 1,
      "path": posixpath.join(wsl_path, ".devcontainer/devcontainer.json"),
      "scheme": "vscode-fileHost",
    },
  }
  if show:
    print(json.dumps(payload, indent=2))
  # Compact separators: key order and formatting must match VS Code's output.
  hex_id = json.dumps(payload, separators=(",", ":")).encode("utf-8").hex()
  container_folder = "/workspaces/" + posixpath.basename(wsl_path)
  return "dev-container+" + hex_id, container_folder


def main() -> None:
  parser = argparse.ArgumentParser()
  parser.add_argument("distro")
  parser.add_argument("path")
  parser.add_argument("--show", action="store_true")
  parser.add_argument("--exe", default=r"C:\Program Files\Microsoft VS Code\Code.exe")
  parser.add_argument("--exec", action="store_true", help="start VS Code instead of only printing the command")
  args = parser.parse_args()

  authority, folder = build_authority(args.distro, args.path, args.show)

  if not args.show:
    print(f'--remote {authority}{folder} {folder}')

  if args.exec:
    # env = dict(os.environ, MSYS_NO_PATHCONV="1")
    subprocess.Popen([args.exe, "--remote", authority + folder, folder])


if __name__ == "__main__":
  main()