app.context - Context API

Access Finder selection context and plugin directory information.

Not the same thing as the context argument your menu handler receives.

function MyPlugin:handleAction(context)
    local files = context.selectedFiles       -- property, snapshot of this click
    local files = app.context.selectedFiles() -- function, queried right now
end
  • The handler’s context argument is a snapshot taken when the menu was clicked, with just selectedFiles and currentDirectory. Prefer it inside handlers — it is guaranteed to match what the user had selected.
  • The app.context.* global API queries live, at call time. Use it outside handlers: in getMenuTitle, in background timers, in coroutines — places where no context argument exists.

During a long-running task the user may change the selection, and the two will disagree. If you want “what was selected when they clicked”, use the argument.

Permission: L0 Safe — always available, no declaration needed

Methods

app.context.selectedFiles()

Gets the file paths selected in Finder.

Returns: table - Array of absolute paths

local files = app.context.selectedFiles()
for _, path in ipairs(files) do
    app.log.info(path)
end

app.context.currentDirectory()

Gets the directory of the current Finder window.

Returns: string - Directory path

local dir = app.context.currentDirectory()
-- "/Users/username/Documents"

app.context.pluginsDirectory()

Gets the plugin installation directory.

Returns: string - Directory path

local dir = app.context.pluginsDirectory()
-- "~/Library/Group Containers/group.net.ymlab.iRightMenu.pro/Plugins"

app.context.pluginDirectory()

Gets the current plugin’s install directory.

Returns: string - Directory path

local dir = app.context.pluginDirectory()
-- "~/Library/Group Containers/.../Plugins/com.example.my-plugin"

-- Read a plugin resource file
local configPath = app.path.join(dir, "config.json")

Read-only. This holds content shipped inside the plugin bundle, and updating the plugin replaces the whole directory. Writing here means losing the data on the next update at best, and breaking signature verification at worst. Use dataDirectory() below for anything you need to write.

app.context.dataDirectory()

Gets the plugin’s own writable directory (since 1.3.0). Caches, databases and state files belong here.

Returns: string - Directory path; returns nil, error on failure

The directory is created on first call. Because it lives outside the install directory:

  • Updating the plugin does not wipe it — that is the whole point
  • Uninstalling the plugin deletes it along with the plugin
  • It is included in iCloud backup and restore when that is enabled

app.settings already stores its data in this directory, so you do not have to manage it.

local dataDir = app.context.dataDirectory()
-- "~/Library/Group Containers/group.net.ymlab.iRightMenu.pro/PluginData/com.example.my-plugin"

-- Keep a cache that survives updates
local cachePath = app.path.join(dataDir, "cache.json")
app.file.write(cachePath, app.json.stringify(myCache))

Failure only happens when there is no plugin context (for example when called outside the plugin lifecycle). Normal plugin code will not hit it, but handle it anyway:

local dataDir, err = app.context.dataDirectory()
if not dataDir then
    app.log.error("Could not get data directory: " .. tostring(err))
    return
end

Examples

Processing selected files

function MyPlugin:handleAction(context)
    local files = app.context.selectedFiles()
    local dir = app.context.currentDirectory()

    app.log.info("Current directory: " .. dir)
    app.log.info("Selected files: " .. #files)

    for i, file in ipairs(files) do
        app.log.info("File " .. i .. ": " .. file)
    end
end

Reading plugin configuration

function MyPlugin:loadConfig()
    local pluginDir = app.context.pluginDirectory()
    local configPath = app.path.join(pluginDir, "config.json")

    if app.path.exists(configPath) then
        local content = app.file.read(configPath)
        return app.json.parse(content)
    end
    return {}
end
Developer Documentation
User Guide
Getting Started Menu Editor Guide Plugin Manager Settings Script Menus FAQ
Script Development
Development Guide
Plugin Development
Quick Start Development Guide Example Plugins
API Reference
Overview API Query Plugin Info Logging Finder Context Plugin Settings Internationalization
UI & Interaction
Dialog Progress Notification Chooser WebView Status Bar Dock
Files & Paths
File Operations Path Utilities Finder Actions Trash Extended Attributes Metadata File Watcher
Data Formats
JSON Plist CSV XML PDF Image
Text & Encoding
String Regex Date & Time Color Crypto
System
Shell Commands Process Application System Info AppleScript Shortcuts
System Info
Network Power/Battery Screen/Appearance Audio Bluetooth Location
Network
HTTP WebSocket URL
Input & Clipboard
Keyboard Mouse Hotkey Clipboard Window
Storage
SQLite Keychain UserDefaults
Media
OCR QR Code
Utilities
Archive UTI Share Timer Wake Lock Thread