=================
== Claus' Blog ==
=================
Made with Hugo and ❤️

Open a tab in an existing yazi instance

#howto #personal #kitty #yazi #terminal #macos

Recently I have been trying to switch to a terminal only workflow. I am doing this partly for fun, but honestly the terminal is the fastest way to work with a computer once you get the hang of it.

Because of this shift I am using Yazi [1]. Yazi is a blazing fast terminal file manager written in Rust that offers asynchronous operations and a highly customizable interface.

The problem with multiple windows

I wanted to integrate Yazi with the other tools on my macOS system. However I ran into a small annoyance. Every time I triggered a folder to open from another application it launched a completely separate instance of Yazi. I was looking for a way to open a new tab within an existing Yazi window instead of spawning a new process every single time.

The solution using DDS

It turns out that Data Distribution Service is the way to go. Yazi uses this internally as a publish and subscribe messaging system between its instances.

When you launch Yazi normally it automatically generates its own internal ID. This is exposed inside a Yazi subshell as the environment variable $YAZI_ID. But you can also use the --client-id flag. This flag lets you define that ID in advance so your external scripts can reference it easily. It is important to note that this ID is not a standard process ID. It is a Data Distribution Service subscriber ID.

You can define your ID in a few ways. For example you can drop it right into your .zshrc file. Here is how you can set it up and send commands to it:

1export YA_ID="$(date +%s)$RANDOM"
2# or just hardcode it
3export YA_ID="123456"
4
5yazi --client-id "$YA_ID"
6
7# then from elsewhere:
8ya emit-to "123456" ~/Downloads
9ya emit-to "123456" tab_create ~/Cloud

Bringing it all together with Kitty

As an extra touch I wanted to bring my Kitty terminal to the front automatically using osascript on macOS. I wrote a quick script to handle the logic. It tries to open a tab in the existing instance. If that succeeds it brings Kitty into focus. If it fails because Yazi is not running yet it launches a fresh instance.

 1#!/bin/bash
 2MY_ID=12345678
 3FOLDER="${1:-$HOME}"
 4
 5if ya emit-to "$MY_ID" tab_create "$FOLDER" 2>/dev/null; then
 6  # emit succeeded so the instance with that ID is running
 7  osascript -e 'tell application "System Events" to set frontmost of process "kitty" to true'
 8else
 9  # emit failed so there is no instance with that ID, launch one
10  kitty yazi --client-id "$MY_ID" "$FOLDER" &
11fi

This setup makes my workflow feel incredibly smooth. I get the speed of Yazi without cluttering my screen with a dozen different file manager windows.

References

[1] Yazi - https://yazi-rs.github.io/