Skip to content

fix: make code <file> work in serve-web terminals#519

Open
venkatamutyala wants to merge 3 commits into
mainfrom
fix/code-cli-terminal-wrapper
Open

fix: make code <file> work in serve-web terminals#519
venkatamutyala wants to merge 3 commits into
mainfrom
fix/code-cli-terminal-wrapper

Conversation

@venkatamutyala

@venkatamutyala venkatamutyala commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Problem

Running code <file> from the integrated terminal crashes:

[ERROR:ozone_platform_x11.cc] Missing X server or $DISPLAY
[ERROR:env.cc] The platform failed to initialize.  Exiting.

The apt code package installs the desktop (Electron) binary at /usr/bin/code. Our environments run VS Code via serve-web/tunnel with no X display, so that GUI binary can't start and dies. There's already a live IPC socket ($VSCODE_IPC_HOOK_CLI) and a proper CLI shim shipped inside the serve-web install (~/.vscode/cli/serve-web/<hash>/bin/remote-cli/code) — but it isn't what code resolves to on PATH.

Fix

Add a wrapper at $HOME/.local/bin/code (already first on the interactive PATH via the .zshrc/.bashrc line just below it) that forwards to the serve-web/remote-cli shim. The shim opens files in the already-running VS Code window via $VSCODE_IPC_HOOK_CLI — no display needed.

The wrapper:

  1. Resolves the newest shim (ls -t) so it keeps working across VS Code updates when the <hash> changes. Also matches .vscode-server layouts (Remote-SSH / Codespaces), so it's a no-op improvement there. Exits with a clear message if no shim is present.
  2. Recovers from a stale IPC socket after a reconnect. $VSCODE_IPC_HOOK_CLI is captured when the shell starts, so after a container/server restart it can name a socket that no longer exists. Only when that socket is gone, the wrapper falls back to the most recently created /tmp/vscode-ipc-*.sock. A still-present socket is left untouched, so routing stays correct when multiple windows (each with its own socket) are connected. Dependency-free, no double-invocation of code.

Only affects interactive shells. Build-time code --install-extension runs under /bin/sh (which doesn't include ~/.local/bin) and still resolves to /usr/bin/code, so image builds are unaffected.

Testing

Simulated the exact Dockerfile printf and verified the generated ~/.local/bin/code is byte-correct and passes sh -n, then exercised every path against a live serve-web session (3 sockets present in /tmp, i.e. a real multi-window case):

  • Valid env socket → opens the file, exit 0; env socket left untouched.
  • Stale socket ($VSCODE_IPC_HOOK_CLI pointed at a non-existent path) → falls back to newest socket, opens the file, exit 0.
  • Unset socket → falls back to newest socket, opens the file, exit 0.
  • No shim (empty $HOME) → clear error message, exit 1.
  • Reproduced the original crash with /usr/bin/code <file> for comparison.

🤖 Generated with Claude Code

The apt `code` package installs the desktop (Electron) binary at
/usr/bin/code. In our headless serve-web/tunnel sessions there is no X
display, so running `code <file>` from the integrated terminal crashes
with "Missing X server or $DISPLAY" (plus a dbus warning).

Add a small wrapper at $HOME/.local/bin/code (already first on the
interactive PATH via .zshrc/.bashrc) that forwards to the VS Code
serve-web/remote-cli shim, which opens files in the running window via
$VSCODE_IPC_HOOK_CLI. It resolves the newest shim so it survives VS Code
updates, and falls back with a clear message if no session is running.

Only affects interactive shells; build-time `code --install-extension`
still resolves to /usr/bin/code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
venkatamutyala and others added 2 commits July 10, 2026 15:21
Extend the `code` wrapper to handle a stale $VSCODE_IPC_HOOK_CLI. The
value is captured when the shell starts, so after a VS Code reconnect
(container/server restart) it can name a socket that no longer exists,
and `code <file>` fails.

When — and only when — the referenced socket is gone, fall back to the
most recently created /tmp/vscode-ipc-*.sock. A still-present socket is
left untouched, so routing stays correct when multiple windows (each
with its own socket) are connected. Dependency-free and no double-exec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Post-review hardening from a shell audit: `ls -t` can surface a shim
path that lacks the execute bit, in which case `exec` fails with an
opaque "exec: Permission denied". Add a `-x` check so that case takes
the existing friendly "no usable shim" branch instead.

Deliberately not adding a "fail if no live socket" guard: socket-less
subcommands (code --version/--list-extensions/--help/tunnel) must still
reach the shim, so socket presence is left for the shim to require.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants