hx-remote 0.1.2

Open files in new or existing Helix sessions through a tiny LSP bridge
Documentation

hx-remote | hxr

hx-remote is a small Unix-only bridge for opening files in new or already-running Helix sessions. It uses a Unix-domain socket for local commands and Helix's LSP window/showDocument support to open and focus files.

The installed executable is named hxr:

hxr README.md
hxr --listen
hxr --status
hxr --open src/main.rs Cargo.toml
hxr --open src/main.rs:50:12
hxr --stop
git diff | hxr --stdin-name changes.diff --open -

Install

Helix 24.03 or newer is required.

cargo install hx-remote

You can also clone this repository and install from the local copy.

git clone https://github.com/FluxKraken/hxr
cd hxr
cargo install --path .

Helix LSP Config

Add this once to ~/.config/helix/languages.toml (or print the snippet with hxr --print-config; a copy is also in examples/helix/languages.toml):

[language-server.hx-remote]
command = "hxr"
args = ["--lsp"]

[[language]]
name = "hx-remote"
scope = "source.hx-remote"
file-types = ["hxremote"]
language-servers = ["hx-remote"]

You can check that Helix sees the executable with:

hx --health hx-remote

Use

To start a receiving Helix instance and open files in one command, pass the paths directly:

hxr README.md
hxr src/main.rs:50:12 Cargo.toml

This launches Helix with the requested files followed by the bridge's sentinel buffer. Several files may be passed. In the normal layout Helix focuses the first one; when using --helix-arg=--vsplit or --helix-arg=--hsplit, the last requested split is focused. The sentinel starts the bridge in the background. Use -- before a filename that begins with a hyphen, for example hxr -- -notes.md.

The original two-command workflow remains available. Start the receiving Helix instance from the directory you want to use as its workspace:

hxr --listen

This creates and opens a small sentinel file under the user cache directory. Keep that buffer open: its language server is the bridge. From another process, shell, or file explorer, open files in that instance with:

hxr --open /absolute/path/to/file

Relative paths are resolved by the sending hxr process, so file explorers may pass either relative or absolute paths. Several files may be sent in one call; Helix focuses the last one.

Positions use one-based line and column numbers in either workflow:

hxr src/main.rs:50:12
hxr --open src/main.rs:50
hxr --open src/main.rs:50:12

To open piped text, use -. The bridge keeps a temporary file alive for the rest of the Helix session. --stdin-name supplies an extension for syntax detection:

git diff | hxr --stdin-name working-tree.diff --open -

The default socket is $XDG_RUNTIME_DIR/hx-remote.sock when that directory is available, otherwise a per-user socket in the system temporary directory. Set HXR_SOCKET or pass --socket PATH to run independent Helix listeners:

HXR_SOCKET=/tmp/project-a.sock hxr --listen
HXR_SOCKET=/tmp/project-a.sock hxr --open src/lib.rs

Extra Helix arguments can be supplied when launching a session by repeating --helix-arg:

hxr --helix-arg=-w --helix-arg=/tmp/helix-working-directory --listen
hxr --helix-arg=-w --helix-arg=/tmp/helix-working-directory README.md

Check whether the selected socket is open and accepting connections with:

hxr --status

The command exits successfully while a listener is present and unsuccessfully otherwise. Stop the bridge sidecar gracefully with hxr --stop. If it is not responding normally, hxr --stop --force terminates it immediately. Both commands affect only the server selected by --socket or HXR_SOCKET; they do not close Helix itself.

How it works

When paths are passed directly, hxr launches Helix with those files followed by the .hxremote sentinel buffer (or reverses that file order for a split layout). This keeps a requested file focused while Helix starts hxr --lsp for the sentinel in the background. That process performs the minimal LSP initialization handshake and listens on a local Unix socket. Later, hxr --open sends a path to the socket, and the sidecar emits a window/showDocument request with takeFocus = true. The socket is permissioned to the current user (0600) and stale socket files are removed safely at startup.