Skip to content

Browser editor

Every session’s </> button opens VS Code on that session’s worktree, in a pane beside its agent: same browser tab, same port, same login as the rest of spwn. It works the same on your laptop, in the Docker container and on a cluster, which is the point. A desktop editor only helps if you’re sitting at the machine spwn runs on.

Click </> on a session row in the sidebar. A pane titled IDE · session opens and the editor starts. The agent pane stays open beside it, and the editor pane keeps its open files while you switch between them.

⌥-click (or ⌘-click) </> opens desktop VS Code on the worktree instead. That runs open -a "Visual Studio Code" on the machine spwn runs on, so it’s for a Mac you’re sitting at. The Inspector’s Open in VS Code does the same.

Stop the editor at the bottom of the pane shuts it down; Start it again brings it back. The editor also stops when its session is deleted.

If a hook gave the session an environment (an exec prefix, for example a container; see per-session dev environments), code-server is launched through that same prefix. The editor’s terminal, its language servers and its extensions see the session’s toolchain, not your laptop’s.

That session’s image needs code-server on its PATH, and the worktree’s git directory mounted at the same path (the docker-env recipe already does this). If it’s missing, the pane says the editor didn’t start and shows its boot log, which is where code-server: command not found shows up. The first start inside a container can take a minute; spwn waits up to 150 seconds there, and 45 on the host.

code-server listens on a unix socket, never a port, and spwn reverse-proxies it at /ide/<session id>/. There’s nothing to publish or forward, and the container case works without spwn knowing how your hook built the container.

  • On the host, sockets and editor state live under spwn’s data folder, in ide/.
  • In an environment, the socket is spwn-ide.sock in the worktree’s own git directory (<repo>/.git/worktrees/<name>/), the one path both sides already share. It can’t go in the worktree itself: the per-turn commit runs git add -A, and git can’t index a socket.

code-server runs with --auth none. The socket sits in a 0700 directory with mode 600, and spwn’s own login (plus an Origin check on everything under /ide) is the gate.

On your own machine, spwn looks for code-server in this order:

  1. Settings → Sessions → code-server path, if set.
  2. code-server on $PATH.
  3. Its own copy, which it downloads the first time you open an editor.

The download is a pinned code-server release (4.138.0), checked against a SHA-256 digest and unpacked into ide/dist/ under spwn’s data folder. It’s a one-time download of about 200 MB, shared by every session; the pane shows progress while it runs. Builds exist for macOS and Linux on x86_64 and arm64; anywhere else, install code-server yourself and set its path.

The deployment image ships code-server already. Sessions inside an environment never use the host copy: a macOS binary can’t run in a Linux container.

code-server is a few hundred megabytes resident, and a spwn is meant to run many sessions. So an editor nobody has used for 30 minutes is stopped. Its files and state are on disk, so restarting costs a click and a few seconds. An open editor tab holds a live connection, and an editor with a live connection is never reaped.

Change the timeout with SPWN_IDE_IDLE_MINUTES in spwn’s environment; 0 turns reaping off.

Terminal window
SPWN_IDE_IDLE_MINUTES=120 spwn

On the host, extensions are shared: install one once and every session’s editor has it. Each session gets its own editor user-data directory (settings, open editors, state). In a containerised session, code-server keeps everything inside that environment, so it starts clean.

Git inside the editor can use the GitHub token saved in spwn, the same as your shells.