Skip to content

Plugin API

Nathaki edited this page Sep 20, 2026 · 1 revision

Anatomy of a Plugin

Each plugin on Lupa should be a lua file with the following defined globals. The example plugin provides additional context for these.

Plugin Metadata

--- Prefix to use in the query for explicit search
--- It is filtered out in the rust side before calling GET_RESULTS
--- It should be a singular character
PREFIX
--- The name of the plugin
--- Must never contain a comma, case insensitive
NAME

Flags

--- Whether the provider supports the sidebar or not
--- It defaults to false, but if it is true, the appropriate functions should be present
SUPPORT_SIDEBAR
--- Whether the results should be sorted after the fact using SkimMatcherV2
--- It defaults to false
SORT_RESULTS

Functions

--- The function for obtaining the results from a query
--- @param query string
--- @return table
function GET_RESULTS(query)
--- This function is run when the user confirms the entry
--- The window will close after it is run
--- @param entry table
function EXECUTE_ENTRY(entry)
    print("You executed " .. entry.name .. "!")
end
--- The function for obtaining the sidebar actions for a specific entry
--- @param entry_name string
--- @return table
function GET_SIDEBAR_ACTIONS(entry_name)
--- This function is run when the user confirms a sidebar action to run
--- The window will close after it is run
--- @param entry table
function EXECUTE_SIDEBAR_ACTION(entry)

The Entry Table

Both GET_RESULTS and GET_SIDEBAR_ACTIONS shall return a table of entry tables, each entry table should have the following data:

{
    --- The name of the entry or sidebar action, must always be present
    name: string,
    --- The subtitle of the entry, unused in sidebar, can be nil if unused
    description: string?,
    --- The icon of the entry or sidebar action, can be nil if unused
    icon: string?
}

The lupa global

All plugins have access to a global value called lupa, it is a table containing actions that make more sense being handled in the Rust side, whether it is to avoid headaches or to unify behavior.

As it stands, the lupa global contains the following functions:

--- Spawns the given command in a new process
--- Use over os.execute() as this one would keep lupa hanging until the child process ends
--- @param exec: string
lupa.spawn(exec)

--- Copies the given text to the clipboard
--- Uses GTK4's clipboard tooling, simplifies copying
--- @param text: string
lupa.clipboard_copy(text)

Clone this wiki locally