Plugin System Overview

Lightfall’s plugin system enables extending the application with custom functionality without modifying core code. Plugins are discovered automatically via Python entry points and loaded using a manifest-based system.

Architecture

The plugin system consists of:

  1. Plugin Types: Abstract base classes defining interfaces (e.g., SettingsPlugin, PanelPlugin)

  2. Plugin Manifests: Collections of plugin entries that declare available plugins

  3. Plugin Loader: Discovers manifests via entry points and loads plugins in the background

  4. Plugin Registry: Tracks all registered plugins by type and name

┌─────────────────────────────────────────────────────────────────┐
│                         Application                              │
├─────────────────────────────────────────────────────────────────┤
│  PluginLoader                                                    │
│  ├── Discovers manifests via entry points                       │
│  ├── Loads plugin classes (background thread)                   │
│  └── Instantiates plugins                                        │
├─────────────────────────────────────────────────────────────────┤
│  PluginRegistry                                                  │
│  ├── Tracks plugins by type:name                                │
│  └── Provides lookup APIs                                        │
├─────────────────────────────────────────────────────────────────┤
│  Plugin Types                                                    │
│  ├── SettingsPlugin    - Preferences pages                       │
│  ├── PanelPlugin       - UI panels                              │
│  ├── PlanPlugin        - Bluesky plans                          │
│  ├── EnginePlugin      - Execution backends                     │
│  ├── ThemePlugin       - Color themes                           │
│  ├── StatusBarPlugin   - Status indicators                      │
│  ├── ControllerPlugin  - Device control widgets                 │
│  ├── MCPToolPlugin     - Claude assistant tools                 │
│  └── SkillPlugin       - Claude assistant expertise             │
└─────────────────────────────────────────────────────────────────┘

Plugin Types

Lightfall supports 9 plugin types, each serving a specific purpose:

Type

Base Class

Purpose

Singleton

settings

SettingsPlugin

Add preferences pages

Yes

panel

PanelPlugin

Add application panels

Yes

plan

PlanPlugin

Register Bluesky plans

Yes

engine

EnginePlugin

Provide execution backends

Yes

theme

ThemePlugin

Define color themes

Yes

statusbar

StatusBarPlugin

Add status bar indicators

Yes

controller

ControllerPlugin

Device-specific control widgets

Yes

mcp_tool

MCPToolPlugin

Claude assistant tools

Yes

skill

SkillPlugin

Claude assistant expertise

Yes

See Plugin Type Reference for detailed documentation on each type.

Loading Lifecycle

Plugins go through these states during loading:

  1. DISCOVERED: Manifest entry found, not yet loaded

  2. QUEUED_LOAD: Waiting in load queue

  3. LOADING: Class being imported

  4. QUEUED_INIT: Class loaded, waiting for instantiation

  5. INITIALIZING: Instance being created

  6. READY: Plugin fully loaded and available

  7. FAILED_LOAD / FAILED_INIT: Error during loading

  8. DISABLED: User disabled this plugin

Preload Plugins

Plugins with preload=True are loaded synchronously before the main window is created. Use this for plugins that must be ready immediately, such as:

  • Theme plugins (to apply colors before any UI appears)

  • Appearance settings (to load saved theme preference)

PluginEntry(
    type_name="settings",
    name="appearance",
    import_path="lightfall.ui.preferences.builtin:AppearanceSettingsPlugin",
    preload=True,  # Load before main window
)

Manifest System

Plugins are declared in manifests, which are collections of PluginEntry objects:

from lightfall.plugins import PluginManifest, PluginEntry

manifest = PluginManifest(
    name="my-beamline-plugins",
    version="1.0.0",
    description="Custom plugins for beamline 7.0.1.1",
    plugins=[
        PluginEntry(
            type_name="plan",
            name="my_scan",
            import_path="my_beamline.plans:MyScanPlan",
        ),
        PluginEntry(
            type_name="settings",
            name="beamline_config",
            import_path="my_beamline.settings:BeamlineConfigPlugin",
        ),
    ],
)

Built-in Manifest

Lightfall’s built-in plugins are defined in lightfall.plugins.builtin_manifest. This manifest is loaded directly by the application and contains core plugins like:

  • Theme plugins (light, slate, darkblue, islands)

  • Settings plugins (appearance, devices, claude, etc.)

  • Engine plugins (bluesky, mock)

  • Panel plugins (devices, bluesky, claude, etc.)

  • Status bar plugins (user, auth, connection, tiled)

External Package Manifests

External packages can provide plugins via entry points. See External Packages for details.

Audit

Because plugins are distributed as ordinary Python packages in version-controlled repositories, a beamline’s customization is auditable with the tools the lab already uses — no separate audit pipeline. The git history of a beamline’s plugin repository is the record of what changed, when, and by whom:

  • Review recent changesgit log on the plugin repository.

  • Roll back a single changegit revert <sha>.

  • Compare two statesgit diff <a>..<b>.

This is the foundation the design-mode workflow builds on: staff-authored interface changes land as commits in the beamline plugin repository, so every change is reviewable and reversible by construction.