Back to blog
Jul 19, 2026
5 min read

I wrote my first Yazi plugin: date-diff.yazi

A tiny Yazi plugin that shows the modification-time difference between two selected files. My first step into the Yazi Lua plugin API.

I have been using Yazi as my terminal file manager for a while now, and the more I use it, the more I want small workflow shortcuts that live right next to the files I am looking at. So I finally sat down and wrote my first Yazi plugin: date-diff.yazi.

It does one thing: select exactly two files, press a key, and Yazi shows a notification with each file’s modification time and the duration between them.

That is it. But building it taught me a lot about how Yazi’s plugin system actually works.

Why this plugin?

I often end up with two versions of the same file sitting next to each other: an old backup, a freshly generated artifact, or two downloaded copies with similar names. Sorting by mtime in Yazi already tells me which one is newer, but it does not immediately tell me how much newer. I wanted a quick comparison without leaving the file manager or reaching for stat and date.

Installing it

The plugin is published on Yazi’s package registry, so installing it is a one-liner:

ya pkg add rio-gesulgon/date-diff

Then bind it to a key in yazi.toml:

[[mgr.prepend_keymap]]
on = "<C-S-d>"
run = "plugin date-diff"
desc = "Show modification-time difference between two selected files"

I picked Ctrl+Shift+D because it is easy to hit and I do not already use it for anything else.

What the code looks like

The whole plugin is a single main.lua file. Here are the interesting parts.

Reading the selection

The plugin entry point runs in a worker thread, so you cannot access cx.active.selected directly. Yazi gives you ya.sync for that:

local get_selected_urls = ya.sync(function(_)
    local urls = {}
    for _, url in pairs(cx.active.selected) do
        urls[#urls + 1] = url
    end
    return urls
end)

I missed this detail on my first attempt and spent a few minutes staring at an empty selection before I realized the sync wrapper was required.

Fetching file metadata

With the URLs in hand, fs.cha reads each file’s attributes:

local cha, err = fs.cha(url)
if not cha then
    notify("DateDiff", string.format("Failed to read metadata for %s: %s", tostring(url), err or "unknown error"), "error", 5)
    return
end

local mtime = cha.mtime

cha.mtime is an epoch timestamp in seconds, which is exactly what you need for math and os.date formatting.

Formatting the result

The diff itself is just subtraction, then a little helper breaks the duration into years, months, days, hours, minutes, and seconds:

local function format_duration(seconds)
    seconds = math.floor(math.abs(seconds))
    if seconds == 0 then
        return "0 seconds"
    end

    local years = math.floor(seconds / 31536000)
    seconds = seconds % 31536000
    local months = math.floor(seconds / 2592000)
    seconds = seconds % 2592000
    -- ... days, hours, minutes, seconds

    local parts = {}
    if years > 0 then table.insert(parts, pluralize(years, "year")) end
    -- ... etc

    return table.concat(parts, ", ")
end

I sort the two items so the older file is always shown first, which makes the difference read naturally.

Showing the notification

Yazi’s ya.notify is simple but effective:

ya.notify({
    title = "DateDiff",
    content = message,
    timeout = 6,
    level = "info",
})

The final message looks something like this:

2026-07-10 14:22:01  —  backup.tar.gz
2026-07-19 09:15:33  —  latest.tar.gz

Difference: 8 days, 18 hours, 53 minutes, 32 seconds

Lessons from my first plugin

  1. Start tiny. A plugin that does one narrowly defined thing is easier to reason about, and you can always expand it later.
  2. Read the API version. This plugin targets Yazi >= 25.5.28 because it uses APIs introduced around that release. Declaring the @since comment at the top of the file keeps that clear.
  3. Use ya.err for debugging. When the notification did not show up early on, adding ya.err("[date-diff] entry start") let me trace the flow in Yazi’s log.
  4. Handle the boring cases. Exactly two files must be selected, metadata must exist, and mtime might be missing. Bailing out early with a clear warning is much better than a silent failure.

What is next

For now the plugin only compares modification times. Possible small extensions include:

  • Comparing creation times or access times when the filesystem provides them.
  • Supporting directories by using their own mtime values.
  • A config option to control the output format or notification timeout.

But I am resisting feature creep until I have used the current version for a while.

Try it

If you use Yazi and run into the same “which copy is newer, and by how much?” question, give it a shot:

ya pkg add rio-gesulgon/date-diff

Source and issue tracker are on GitHub: rio-gesulgon/date-diff.yazi.

It is a small thing, but it is my first published Yazi plugin, and it feels good to have a file-manager shortcut that I actually built.