Remote Editing with Kakoune and Sway
Out of the box, Kakoune comes with good IPC support. This means that Kakoune can extremely nicely be integrated with your window manager or tmux. When I work with Kakoune, I split windows and use Sway to manage them like regular window. It is quite magical.
I have a growing fear of third-party dependencies stealing my data, so I do most of my work as a separate user which I ssh into. I could use TMUX, but I do not like having separate window management system for my editor vs all my other programs.
Luckily, Sway comes with great IPC support, and exports a socket that you can communicate with. SSH also comes with a RemoteForward feature, which can be used to forward a socket to a remote system. I'll describe how these can be used to enable a remotely-running Kakoune session to leverage Sway for window management.
Recording of remote window management in action.
To start with, we need to forward the sway socket to the remote. Edit the ssh config and add RemoteForward, telling ssh the socket to the remote machine. This allows the remote machine to send messages to your locally running Sway session.
Host dev
HostName localhost
RemoteForward /tmp/sway-remote.sock ${SWAYSOCK}
StreamLocalBindUnlink yes
User dev
We will also need to setup the environment variable in our shell on the remote machine, so that sway knows where it can find the socket.
if [[ -n "$SSH_CONNECTION" ]] && [[ -S "/tmp/sway-remote.sock" ]]; then
export SWAYSOCK=/tmp/sway-remote.sock
fi
Now, you should be able to run ssh dev and communicate with Sway. Try for example swaymsg exec foot (or whichever terminal you use), and it should create a new terminal window. Unfortunately, if you attempt to ssh to the same machine in your new terminal window, it will have connection issues.
To fix it, you need to setup a ControlMaster so that you can multiplex the ssh session. You can read more about multiplexing in ssh_config(5).
Host dev
HostName localhost
RemoteForward /tmp/sway-remote.sock ${SWAYSOCK}
StreamLocalBindUnlink yes
User dev
ControlMaster auto
ControlPath /home/YOUR_USERNAME/.ssh-%r@%h:%p
Now, we can create a new terminal and automatically connect to the remote machine by running swaymsg exec "foot ssh dev". Step 1 complete.
Step 2. Connect Kakoune
We now need to setup so that when we run the "split" command in kakoune, we ssh into the session and then automatically connect to the Kakoune session.
If we open Kakoune in one window, we will see its session ID in the bottom right, it should be a five-digit number.
Using that, it is quite easy to connect to that same session. In a new window, you just simply need to run
ssh dev -t kak -c THE_SESSION
You should now be able to edit in both windows and see the sessions update in real time.
Step 3. Putting it all together
Now we need to draw the rest of the owl. Within Kakoune, we need to tell sway to open a new window, connect via ssh to the remote machine, and open the Kakoune session.
I won't explain how scripting in Kakoune works exactly, but generally it is as simple as a shell script. So we will define three simple commands in our kakrc.
# --- Run command
define-command wmterm -params 1.. %{
eval %sh{
swaymsg exec foot ssh -t dev "$@" > /dev/null 2>&1
}
}
# --- Open terminal in $PWD
define-command wmnew %{
eval %sh{
swaymsg exec "foot ssh -t dev 'cd $PWD && exec $SHELL' " > /dev/null 2>&1
}
}
# --- Split current kakoune session
define-command wmsplit %{
eval %sh{
swaymsg exec "foot ssh -t dev kak -c $kak_session" > /dev/null 2>&1
}
}
Now, running wmsplit in the ssh session will split the terminal in Sway. Neat!
Step 4. Workaround for high CPU
I had some issues with this approach that whenever I opened a new window, my CPU started going to 100%. A way around this is to use socat and instead use TCP as a middleman. It's a bit less pretty, but it works quite well.
So on your local machine, you're going to need to start socat to listen in the background. I added the following to my sway config:
exec socat TCP-LISTEN:10001,bind=127.0.0.1,fork,reuseaddr UNIX-CONNECT:$SWAYSOCK
Since in my case, I'm not remote forwarding to a separate "machine", I can just remove RemoteForward and ControlMaster settings I had earlier. However, if I were SSHing into a separate machine, I would just need to change the ssh config to forward a TCP connection.
Host dev HostName localhost User dev RemoteForward 10001 127.0.0.1:10001 ControlMaster auto ControlPath /home/ME/ssh-%r@%h:%p
Now on the remote machine, I will just need to setup so that socat is forwarding a unix socket again so that swaymsg is able to communicate with it.
export SWAYSOCK=/tmp/sway-remote.sock
if [[ -n "$SSH_CONNECTION" ]] && [ ! -S "$SWAYSOCK" ]; then
socat UNIX-LISTEN:$SWAYSOCK,fork,reuseaddr TCP:localhost:10001 &
fi
Bonus: Clipboard support
Using OSC 52 escape codes, it is possible to also setup so that the clipboard works from the remote session with your local session
Reply