External Extensions#
EEGPrep extensions are normal Python packages. Install them with standard
Python package tooling, then start eegprep-gui or eegprep-console in
the same environment. EEGPrep discovers installed extensions through the
eegprep.extensions entry-point group and validates their declarative
ExtensionSpec records before they contribute menus, actions, help, or
pop_* functions.
The Extension Manager is available from File > Manage EEGPrep extensions or
from Python:
import eegprep
plugins = eegprep.plugin_menu(show=False)
print(eegprep.format_plugin_menu())
The Extension Manager separates installed runtime state from curated catalog metadata. Installed state comes from the local Python environment. Catalog entries are metadata-only records that point to a package name, repository, documentation URL, maintainer, and capabilities. EEGPrep does not host extension zips, does not host arbitrary extension zip files, and the manager does not download, unzip, install, update, or remove extension code.
Installing Extensions#
Install EEGPrep first, then add extension packages to the same project or virtual environment. The manager shows copyable commands when catalog metadata is available; it never runs them for you.
Local or private editable extension#
Use an editable install while developing an extension or keeping a lab-only extension on disk:
uv add --editable /path/to/eegprep-ext-foo
This is the best path for private lab workflows, prototype methods, and extensions that should never leave a controlled environment. If the extension uses optional dependencies, install the extra declared by that package:
uv add --editable "/path/to/eegprep-ext-foo[models]"
GitHub extension#
A researcher does not need to publish to PyPI to share an extension. A GitHub repository can be installed directly:
uv add git+https://github.com/lab/eegprep-ext-foo
Pin a branch, tag, or commit when reproducibility matters:
uv add git+https://github.com/lab/eegprep-ext-foo --tag v0.3.0
PyPI extension#
Use the package name when the extension is published on PyPI:
uv add eegprep-ext-foo
PyPI is useful when an extension is public, versioned, and meant for broad reuse. It is not required for GitHub-only or private lab distribution.
Private package index#
For a private package index, point uv at the lab or institution index:
uv add --index https://packages.lab.example/simple eegprep-ext-foo
When the private index should replace PyPI rather than supplement it, use:
uv add --default-index https://packages.lab.example/simple eegprep-ext-foo
Configure authentication through uv-supported environment variables, keyring
configuration, or your institution’s package-index instructions. Do not put
passwords in committed pyproject.toml files.
Using Installed Extensions#
After installation, launch EEGPrep from the same environment:
uv run eegprep-gui --full
uv run eegprep-console --full
Use --no-plugins when troubleshooting startup or when you need a session
with only core EEGPrep menus and console exports:
uv run eegprep-gui --no-plugins
uv run eegprep-console --no-plugins
Extension menus and actions appear automatically when the extension record is
active. In eegprep-console, extension pop_* functions should behave like
EEGPrep pop_* functions: GUI actions and console calls share one
EEGPrepSession, update EEG and ALLEEG when data changes, and append
the returned command to LASTCOM and ALLCOM.
For example, a user-facing extension function should support:
EEG, LASTCOM = pop_my_extension(EEG, return_com=True)
pop_my_extension(EEG)
Normal Python imports still use standard Python semantics. The automatic
session storage behavior is specific to eegprep-console and registered GUI
actions.
Startup and Extension Loading#
EEGPrep registry discovery imports only the lightweight entry-point target that
returns ExtensionSpec. Processing functions, Qt dialogs, optional machine
learning stacks, and large model loaders should stay behind LazyImport so
import eegprep, eegprep-gui, eegprep-console, Extension Manager
inspection, and menu construction do not import them until the user invokes the
extension action or pop_* function.
Disabled extensions remain visible in the Extension Manager for inspection, but
they do not contribute menus, actions, help resources, or console pop_*
wrappers after registry rediscovery. Failed, incompatible, invalid, and
missing-dependency extensions are also listed without becoming active, so one
broken package should not prevent GUI or console startup.
Required Package Format#
An EEGPrep extension package must provide:
A
pyproject.tomlproject.A
[project.entry-points."eegprep.extensions"]entry point.A lightweight
register()function that returnsExtensionSpec.Declarative
ExtensionAction,ExtensionMenu, andExtensionPopFunctionrecords where applicable.LazyImporttargets for heavy modules, GUI modules, processing code, and model code.Packaged Markdown help and package data declared through
ExtensionResourcewhen those files are user-facing or required at validation time.pop_*functions that supportreturn_com=Truewhen the call is user-facing or history-relevant.No runtime dependency on
src/eegprep/eeglabor any local EEGLAB checkout.
Minimal pyproject.toml metadata:
[project]
name = "eegprep-ext-foo"
version = "0.1.0"
dependencies = ["eegprep"]
[project.entry-points."eegprep.extensions"]
foo = "eegprep_ext_foo.register:register"
Minimal registration:
from eegprep import (
ExtensionAction,
ExtensionMenu,
ExtensionPopFunction,
ExtensionResource,
ExtensionSpec,
LazyImport,
)
def register():
return ExtensionSpec(
name="foo",
display_name="Foo",
version="0.1.0",
package_name="eegprep-ext-foo",
eegprep_requires=">=0.2",
actions=(
ExtensionAction(
name="foo.run",
target=LazyImport("eegprep_ext_foo.actions", "run"),
),
),
menus=(
ExtensionMenu(path=("Tools", "Foo"), action="foo.run", label="Run Foo"),
),
pop_functions=(
ExtensionPopFunction(
name="pop_foo",
target=LazyImport("eegprep_ext_foo.pop_foo", "pop_foo"),
),
),
help_resources=(
ExtensionResource("eegprep_ext_foo", "help/pop_foo.md"),
),
)
register() should import only the SDK and small metadata. Import processing
functions, Qt dialogs, and model loaders lazily through LazyImport so a
broken optional module does not slow or break EEGPrep startup.
Menus must be declarative. Do not mutate EEGPrep Qt objects, monkeypatch menu
builders, or write directly to EEGPrepSession internals from an extension.
If an extension needs a new integration surface, add or request SDK support
instead of reaching into private EEGPrep modules.
pop_* History and Console Rules#
Extension pop_* functions should follow EEGPrep interactive conventions:
Accept an EEG dict or EEG-like object explicitly.
Return the updated EEG object for data-changing calls.
Support
return_com=Trueand return(EEG, com)when the call should be recorded in history.Use user-facing 1-based values in command strings when users provide channel, component, dataset, epoch, or event positions, and convert to Python 0-based indexing internally.
Keep GUI and console workflows synchronized through the registered action and
EEGPrepSessionhelpers instead of mutating GUI-only state.Add packaged help resources for GUI Help buttons and
pophelpsurfaces.
Package Data, Optional Dependencies, and Large Files#
Use package resources for help text, small calibration files, montages, and
other data that must ship with the extension. Declare required runtime files
with ExtensionResource so validate_extension_spec can catch missing
resources before users click the action.
Resolve files with package-relative resource paths, not absolute paths into a
source checkout. ExtensionResource uses Python package resources, which keeps
extension data portable across editable installs, wheels, Windows paths with
spaces, macOS/Linux virtual environments, and private package indexes.
For optional dependencies, declare ExtensionDependency(..., optional=True)
when the dependency unlocks optional behavior. Declare required dependencies
without optional=True so missing packages appear as
missing_dependency rather than a runtime crash.
Large model files need an explicit distribution choice. Prefer package extras, an institution-controlled package index, or an explicit first-run download implemented by the extension. Do not imply that a curated catalog entry hosts or downloads large model artifacts for EEGPrep.
Trust Levels and States#
Installing Python packages executes third-party code. Review the package, maintainer, source repository, documentation, and your lab’s software policy before running any install command. Treat private package indexes and editable local paths with the same care as public packages.
The Extension Manager may show installed packages that are not in the curated catalog. Those are not automatically unsafe, but they are outside EEGPrep’s catalog metadata. Manage them through the package source you used to install them.
The Extension Manager and registry use these user-facing meanings:
- Bundled/Core
Ships with EEGPrep and is covered by the EEGPrep CI and release process. Registry value:
bundled.- Curated
Appears in an EEGPrep catalog that has been reviewed for metadata quality, package-format requirements, and mechanical validation. Curated does not mean SCCN, EEGLAB, or EEGPrep scientifically endorses the method, results, claims, or clinical suitability. Registry value:
curated.- Installed
Present in the user’s Python environment and discovered through
eegprep.extensions. Installed does not imply catalog review. Registry value:installed.- Disabled
Present but intentionally turned off by the user or configuration. Disabled extensions remain visible so users can re-enable them or inspect why they are inactive. Registry value:
disabled.- Failed or incompatible
Present but not active because import, registration, validation, dependency, or version checks failed. Registry values include
failed_import,invalid_spec,missing_dependency,incompatible, andunknown. The user action is to update, reinstall with missing dependencies, disable, or contact the extension maintainer.
The important combinations are:
Curated but not installed: visible as reviewed catalog metadata only; it does not run until the user installs the package.
Installed but not curated: usable if valid, but not reviewed by the catalog.
Curated and installed: both reviewed in the catalog and present locally.
Installed then broken after an EEGPrep update: visible as incompatible or failed, with errors preserved so the user can update or disable it.
Experimental: can be installed or curated as experimental, but the docs and UI must not imply scientific endorsement.
Catalog Schema#
EEGPrep ships a packaged resources/extension_catalog.json file and can load
a local JSON catalog for tests or future download integration. Set
EEGPREP_EXTENSION_CATALOG or pass catalog_path= to plugin_menu.
Catalog loading is local-file-only; it does not fetch URLs. This Extension
Manager catalog uses catalog_kind: "extension_manager"; public curation
submissions use the separate extension_curation format described below.
Minimal catalog:
{
"catalog_kind": "extension_manager",
"schema_version": 1,
"extensions": [
{
"name": "example_extension",
"display_name": "Example Extension",
"version": "1.0.0",
"package_name": "eegprep-ext-example",
"description": "Example EEGPrep extension metadata.",
"maintainer": "Example Lab",
"docs_url": "https://example.org/eegprep-ext-example",
"source": {
"type": "pypi",
"url": "https://pypi.org/project/eegprep-ext-example/"
},
"repository_url": "https://github.com/example/eegprep-ext-example",
"capabilities": ["preprocessing", "reporting"],
"eegprep_requires": ">=0.2.23"
}
]
}
Supported source.type values are pypi, git, local, and
private. Source URLs must point to package metadata, documentation, local
paths, or repositories, not zip archives or wheel files. The catalog is a guide
for users and tests; installed extension compatibility is still determined by
the extension registry.
Catalog Submission Checks#
Catalog submission and governance automation are maintained separately from runtime extension loading. Before submitting an extension for curation, check that:
The package installs from a normal Python distribution path.
The entry point returns a valid
ExtensionSpec.validate_extension_specpasses in a clean environment.Menus and
pop_*functions are declarative and useLazyImporttargets.Help and package data are included in the built wheel or source distribution.
GUI extensions pass the relevant visual parity and user-flow checks.
The README or package metadata states whether the method is experimental.
Large files, optional dependencies, and private indexes are documented.
No runtime code imports from the vendored EEGLAB reference checkout.
See Extension SDK and Registry for the SDK API reference.