Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/sxyazi/yazi/llms.txt

Use this file to discover all available pages before exploring further.

The ps namespace provides a publish/subscribe messaging system for communication between plugins and Yazi components.

Overview

The PubSub system allows plugins to:
  • Subscribe to events from Yazi (DDS events)
  • Publish custom events to other plugins
  • Communicate between plugin instances
  • React to system events

Subscription

ps.sub(kind, callback)

Subscribe to a local event.
kind
string
required
Event kind/name to subscribe to
callback
function
required
Callback function to handle events
ps.sub("my-event", function(body)
  ya.dbg("Received event:", body)
end)
Calling ps.sub() twice for the same event kind will error. Each event can only have one subscriber per plugin.

ps.sub_remote(kind, callback)

Subscribe to a remote event (from other Yazi instances or DDS).
kind
string
required
Event kind to subscribe to
callback
function
required
Callback function
ps.sub_remote("cd", function(body)
  ya.dbg("Directory changed:", body.url)
end)
As of #3638, ps.sub() can be used directly in init.lua without requiring a plugin.

Publishing

ps.pub(kind, value)

Publish an event locally.
kind
string
required
Event kind
value
any
required
Event data (must be serializable)
ps.pub("my-event", { message = "Hello", count = 42 })

ps.pub_to(receiver, kind, value)

Publish an event to a specific receiver.
receiver
Id
required
Receiver ID
kind
string
required
Event kind
value
any
required
Event data
local target_id = ya.id("app")
ps.pub_to(target_id, "custom-event", { data = "targeted" })

Unsubscription

ps.unsub(kind)

Unsubscribe from a local event.
kind
string
required
Event kind to unsubscribe from
return
bool
True if was subscribed, false otherwise
if ps.unsub("my-event") then
  ya.dbg("Unsubscribed successfully")
end

ps.unsub_remote(kind)

Unsubscribe from a remote event.
kind
string
required
Event kind to unsubscribe from
return
bool
True if was subscribed, false otherwise
ps.unsub_remote("cd")

DDS Events

Yazi emits various DDS (Data Distribution Service) events that plugins can subscribe to:

File Events

  • cd - Directory changed
    ps.sub_remote("cd", function(body)
      ya.dbg("New dir:", body.url)
    end)
    
  • duplicate - Files copied (#3456)
    ps.sub_remote("duplicate", function(body)
      -- Handle file copy
    end)
    
  • download - Remote files downloaded (#3687)
    ps.sub_remote("download", function(body)
      ya.dbg("Downloaded:", body.urls)
    end)
    

UI Events

  • ind-app-title - Customize app title (#3684)
    ps.sub_remote("ind-app-title", function()
      return "Custom Title - " .. tostring(cx.active.current.cwd)
    end)
    
  • ind-which-activate - Change which-key behavior (#3608)
    ps.sub_remote("ind-which-activate", function(body)
      -- Customize which-key display
    end)
    
  • ind-sort - Change sorting in Lua (#3391)
    ps.sub_remote("ind-sort", function(files, sort_by)
      -- Custom sorting logic
      return sorted_files
    end)
    

Key Events

  • key-* - Allow changing or canceling key events (#3005, #3037)
    ps.sub_remote("key-enter", function(key)
      -- Intercept Enter key
      return { consume = true }
    end)
    
  • key-sort - Sorting key events (#3391)

System Events

  • relay-notify-push - Customize notification handler (#3642)
    ps.sub_remote("relay-notify-push", function(notification)
      -- Custom notification handling
    end)
    
  • hey - Fires when static messages are restored from persistence (#3725)
    ps.sub_remote("hey", function()
      -- Handle message restoration
    end)
    

Yank Events

  • @yank - Files yanked (copied/cut)
    ps.sub_remote("@yank", function(yanked)
      for url, _ in pairs(yanked) do
        ya.dbg("Yanked:", url)
      end
    end)
    

Examples

Subscribe to Directory Changes

-- In init.lua
ps.sub("cd", function()
  local cwd = cx.active.current.cwd
  ya.dbg("Changed to: " .. tostring(cwd))
end)

Custom Event Communication

-- Plugin A: Publisher
function publish_status()
  ps.pub("status-update", {
    progress = 75,
    message = "Processing..."
  })
end

-- Plugin B: Subscriber
ps.sub("status-update", function(data)
  ya.notify {
    title = "Status",
    body = string.format("%s (%d%%)", data.message, data.progress),
  }
end)

DDS Event Bridge (from preset)

The dds.lua preset plugin bridges DDS events to Yazi actions:
ps.sub_remote("dds-emit", function(action)
  -- Convert DDS action to Yazi action
  local args = {}
  for i = 2, #action do
    local word = string.char(table.unpack(action[i]))
    local key = word:match("^%-%-([^=]+)")
    if key then
      args[key] = word:sub(#key + 4) or true
    else
      args[#args + 1] = word
    end
  end
  ya.emit(action[1], args)
end)

Clean Up Subscriptions

local cleanup = function()
  ps.unsub("my-event")
  ps.unsub_remote("cd")
end

-- Call cleanup when plugin is done
return {
  setup = function()
    ps.sub("my-event", handler)
  end,
  cleanup = cleanup,
}

Best Practices

  1. Subscribe early - Set up subscriptions in init.lua or plugin setup function
  2. Handle errors - Wrap callback logic in pcall to prevent crashes
  3. Unsubscribe - Clean up subscriptions when no longer needed
  4. Serialize data - Ensure published data is JSON-serializable
  5. Avoid loops - Be careful not to create event loops (A publishes → B subscribes and publishes → A subscribes…)

See Also

Build docs developers (and LLMs) love