2026-04-26 16:49:23 -07:00
# Plugins
2026-04-19 00:41:09 -07:00
2026-04-26 16:49:23 -07:00
This folder is the primary home for bundled plugins and also the default search
path for drop-in plugins.
2026-04-19 00:41:09 -07:00
2026-05-16 15:26:08 -07:00
User-facing docs and CLI flows treat these integrations as plugins. Some Python
types and some stored config keys still use older `Provider` naming internally,
but that is a legacy implementation detail rather than the preferred public
term.
2026-04-26 16:49:23 -07:00
Preferred layout:
- Put each plugin in its own folder under `plugins/<name>/` with an `__init__.py` .
- Keep plugin-specific assets beside the code in that same folder.
- Single-file `.py` plugins are still supported, but package folders are the
2026-05-16 15:26:08 -07:00
recommended plug-and-play format.
2026-04-26 16:49:23 -07:00
That means a plugin can ship as a drag-and-drop folder with extras such as:
- `cookies.txt`
- templates or fixture files
- helper modules
- small static assets
Built-in bundled plugins use the same layout as external plugins. Additional
drop-in plugin search paths are:
2026-04-19 00:41:09 -07:00
- `plugins/` in the repo root
- `plugins/` in the current working directory
- Any directory listed in `MM_PLUGIN_PATH`
- Any directory listed in `MEDEIA_PLUGIN_PATH`
2026-04-26 16:49:23 -07:00
Plugin rules:
2026-04-19 00:41:09 -07:00
- A plugin can be a single `.py` file or a package directory with `__init__.py` .
2026-05-21 16:19:17 -07:00
- Current plugin classes inherit from `PluginCore.base.Provider` .
2026-05-16 15:26:08 -07:00
- Give the plugin a stable name using `PLUGIN_NAME` or the class name.
2026-04-19 00:41:09 -07:00
Example skeleton:
``` python
2026-05-21 16:19:17 -07:00
from PluginCore . base import Provider , SearchResult
2026-04-19 00:41:09 -07:00
class MyPlugin ( Provider ) :
PLUGIN_NAME = " myplugin "
URL_DOMAINS = ( " example.com " , )
def search ( self , query , limit = 50 , filters = None , * * kwargs ) :
text = str ( query or " " ) . strip ( )
if not text :
return [ ]
return [
SearchResult (
table = " myplugin " ,
title = f " Result for { text } " ,
path = f " https://example.com/ { text } " ,
)
]
2026-04-27 21:17:53 -07:00
```
Bundled walkthrough:
2026-05-16 15:26:08 -07:00
- Plugins can expose named config instances. The current stored config may still
use legacy key paths such as `provider.<plugin>.<instance>` , and cmdlets target
instances with `-instance <name>` .
- Use `.config plugins` in the CLI to browse configured plugin instances.
2026-04-27 21:17:53 -07:00
- The repo now includes a real FTP example plugin in [plugins/ftp/__init__.py ](plugins/ftp/__init__.py ).
2026-05-03 21:20:05 -07:00
- The walkthrough is in [docs/ftp_plugin_tutorial.md ](docs/ftp_plugin_tutorial.md ) and shows `search-file -plugin ftp -instance <name>` , folder drill-in via `@N` , file download routing, `@N | add-file -instance ...` , and `add-file -plugin ftp -instance <name>` uploads.
2026-04-27 21:17:53 -07:00
- The repo also includes an SCP example plugin in [plugins/scp/__init__.py ](plugins/scp/__init__.py ).
2026-05-03 21:20:05 -07:00
- The walkthrough is in [docs/scp_plugin_tutorial.md ](docs/scp_plugin_tutorial.md ) and shows `search-file -plugin scp -instance <name>` , SSH-backed directory drill-in, file download routing, `@N | add-file -instance ...` , and `add-file -plugin scp -instance <name>` uploads.
2026-05-16 15:26:08 -07:00
- The repo also includes a built-in HydrusNetwork plugin in [plugins/hydrusnetwork/__init__.py ](plugins/hydrusnetwork/__init__.py ). Its Hydrus client API now lives in the plugin-owned package [plugins/hydrusnetwork/api/__init__.py ](plugins/hydrusnetwork/api/__init__.py ), its registry-facing store adapter lives in [plugins/hydrusnetwork/store_proxy.py ](plugins/hydrusnetwork/store_proxy.py ), and its heavy internal operations live in [plugins/hydrusnetwork/store_backend.py ](plugins/hydrusnetwork/store_backend.py ). This `plugins/<name>/api/` package shape is the intended pattern for plugin-owned API helpers going forward. The plugin resolves configured Hydrus instances directly from plugin config instead of routing back through `Store.registry` ; the proxy exists only so generic store callers can still target configured Hydrus stores. [API/HydrusNetwork.py ](API/HydrusNetwork.py ) and [Store/HydrusNetwork.py ](Store/HydrusNetwork.py ) are legacy compatibility shims only, and store discovery prefers the plugin-owned Hydrus hook over those shims.