Skip to content

IPC

The boundary between the debugger and the editor. Two crates: source-frontend-protocol for the wire types, nvim-ipc for the server.

Why there is a boundary at all

Because the editor is not the owner. If Neovim held the session, there would be no boundary and no protocol — and no way for the session to survive the editor.

The boundary is what makes the source frontend replaceable: anything that speaks this protocol can take Neovim's place, and nothing about the debugger changes.

The transport

A Unix domain socket, created at /tmp/rust-debugger-nvim-<pid>.sock.

Unix sockets rather than TCP: the frontend is always on the same machine, and a filesystem socket carries permissions with it — the file is created 0600, so another user cannot connect to your debug session.

What crosses it

Direction Messages
frontend → debugger start a session with a profile; the breakpoint set; execution commands; a request to focus the window
debugger → frontend the current stop location; breakpoint states from the adapter; the session phase

Conspicuously not crossing it: variables, stack contents, watch results. Those are held and drawn by the window, which already has them. Sending them to the editor as well would create a second holder of the same state, and with it the question of which one is right.

Reconnection

hello is the reconnection handshake. A frontend that connects — for the first time, or after the editor restarted — receives a snapshot of the current state, not a replay of what it missed.

A replay would be both larger and wrong: the frontend does not need the history of a session, it needs to draw the present. This is what makes closing Neovim mid-session harmless.

With auto_attach = true in the plugin, starting Neovim reconnects to the project's running session silently.

The control socket

bugsaur gui --control-socket <path> is a second, separate channel used to control an already running window — for instance to raise it, which is what :DebugFocus and gui_focus_on_stop do.

Window raising is bound to the stop generation: however many frames pass, one stop produces exactly one raise, and replacing the session restarts the count. A window that raised itself once per frame would be unusable.

Testing

nvim-ipc has its own tests, and the acceptance scripts drive a real Neovim headlessly:

make test-m8

The CI matrix runs macOS and Linux because this is precisely the layer where they differ: Unix socket behaviour, 0600 permissions, and what happens on close are not identical across the two.

ADR Subject
ADR-005 the source frontend IPC
ADR-007 raising the window on a stop

See Architecture Decision Records.