Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 72 additions & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ RUN curl -Lo /usr/local/bin/kubectl https://dl.k8s.io/release/v${VERSION_KUBECTL


RUN apt update \
&& apt install tmux dnsutils telnet iputils-ping jq certbot nethogs nload vim -y \
&& apt install tmux dnsutils telnet iputils-ping jq certbot nethogs nload vim socat -y \
&& apt clean -y
RUN curl -Lo /usr/local/bin/kind https://kind.sigs.k8s.io/dl/v${VERSION_KIND}/kind-linux-amd64 \
&& chmod +x /usr/local/bin/kind
Expand Down Expand Up @@ -201,6 +201,77 @@ RUN curl -sS https://downloads.1password.com/linux/keys/1password.asc | \

RUN mkdir -p /home/vscode/.vscode-server/data/Machine/ && echo '{"workbench.colorTheme": "VS Code Dark"}' > /home/vscode/.vscode-server/data/Machine/settings.json

# The apt `code` package installs the desktop (Electron) binary at /usr/bin/code.
# In these headless serve-web/tunnel sessions there is no X display, so running
# `code <file>` in the terminal crashes ("Missing X server or $DISPLAY").
# Drop a wrapper on $HOME/.local/bin (first on the interactive PATH, see .zshrc/.bashrc
# below) that forwards to the serve-web/remote-cli shim, which opens files in a running
# VS Code window over its $VSCODE_IPC_HOOK_CLI socket. The wrapper picks the newest shim
# so it survives VS Code updates, and routes to the newest live window socket so it keeps
# working in long-lived shells (e.g. tmux) whose captured socket has gone stale (see the
# inline comments). Only affects interactive shells; build-time `code --install-extension`
# above still resolves to /usr/bin/code.
RUN mkdir -p /home/vscode/.local/bin \
&& printf '%s\n' \
'#!/usr/bin/env sh' \
'# Route `code` to the VS Code serve-web/remote CLI shim instead of the GUI desktop' \
'# binary (/usr/bin/code), which has no display in this container and crashes.' \
'' \
'# 0. tunnel/serve-web are full-CLI subcommands the remote-cli shim does not implement' \
'# (it would treat "tunnel" as a filename to open) and they need no window socket.' \
'# Hand them to the real /usr/bin/code, which dispatches them to its bundled CLI and' \
'# runs fine headless. Use the absolute path -- calling `code` here would recurse' \
'# into this wrapper.' \
'case "$1" in' \
' tunnel|serve-web) exec /usr/bin/code "$@" ;;' \
'esac' \
'' \
'# 1. Locate the remote CLI shim. There is one per installed VS Code build and the' \
'# path embeds a build hash, so pick the newest to survive VS Code updates. The' \
'# -x check turns a found-but-not-executable match into the friendly error below' \
'# instead of an opaque `exec: Permission denied`.' \
'shim=$(ls -t "$HOME"/.vscode/cli/serve-web/*/bin/remote-cli/code \' \
' "$HOME"/.vscode-server/bin/*/bin/remote-cli/code \' \
' "$HOME"/.vscode-server/cli/servers/*/server/bin/remote-cli/code \' \
' 2>/dev/null | head -n1)' \
'if [ -z "$shim" ] || [ ! -x "$shim" ]; then' \
' echo "code: no usable VS Code remote CLI shim found; is a serve-web/remote session running?" >&2' \
' exit 1' \
'fi' \
'' \
'# 2. Choose the IPC socket of the window to open files in. $VSCODE_IPC_HOOK_CLI is' \
'# captured when the shell starts, so a long-lived shell (e.g. a tmux server that' \
'# outlives a VS Code reconnect) keeps pointing at an OLD window. That old socket' \
'# often still accepts connections, so files silently open in a window you can no' \
'# longer see. VS Code creates one socket per window/connection under /tmp, so the' \
'# newest is your current window: prefer the newest socket that still accepts a' \
'# connection, falling back to older ones. If none is reachable, keep whatever the' \
'# environment provided so socket-less subcommands (code --version, etc.) still work.' \
'# LIMITATION: "newest socket" is the current window only with a single window/tab' \
'# open. With multiple windows, or after an extension-host reload, files may open in' \
'# another window -- serve-web exposes no API to target a specific window, so this is' \
'# the best heuristic available.' \
'ipc_live() {' \
' [ -S "$1" ] || return 1' \
' # Best-effort connect probe to skip sockets whose window has gone away. socat is' \
' # optional here: if it is not installed, treat an existing socket as usable. The' \
' # timeout bounds the connect so a pathological socket can never wedge `code`.' \
' command -v socat >/dev/null 2>&1 || return 0' \
' timeout 2 socat -u OPEN:/dev/null UNIX-CONNECT:"$1" >/dev/null 2>&1' \
'}' \
'for sock in $(ls -t /tmp/vscode-ipc-*.sock 2>/dev/null); do' \
' if ipc_live "$sock"; then' \
' VSCODE_IPC_HOOK_CLI="$sock"' \
' export VSCODE_IPC_HOOK_CLI' \
' break' \
' fi' \
'done' \
'' \
'# 3. Hand off to the shim, preserving every argument and its exit status.' \
'exec "$shim" "$@"' \
> /home/vscode/.local/bin/code \
&& chmod +x /home/vscode/.local/bin/code

# Add backup warning to .zshrc for vscode user
RUN echo '\n# === Backup & Git Reminder ===' | tee -a /home/vscode/.zshrc && \
echo 'echo -e "\e[1;31m⚠️ WARNING: No backups are configured. You are responsible for any data loss.\e[0m"' | tee -a /home/vscode/.zshrc && \
Expand Down
Loading