Furious plugins
Furious core support is provided through FuriousPlugin implementations. The
host GUI owns application lifecycle, storage, subscriptions, routing setup, and
the tun2socks sidecar. A plugin owns everything specific to a proxy core:
- configuration recognition, URI import/export, and blank configurations;
- server protocols and their Add Server menu metadata;
- configuration editor construction;
- optional management actions and routing choices;
- core process construction and startup;
- download-test configuration adaptation;
- optional environment setup and post-connection maintenance, such as core asset updates;
- optional native TUN configuration, replacing the host's
tun2sockssidecar; - plugin-specific process exit messages and version strings;
- plugin-specific log timestamp highlighting.
The bundled implementations live under Furious.Plugins.Official. Core,
configuration, and editor implementations are imported from their plugin
packages; host packages intentionally expose only host-owned components.
Registered core plugins appear under Plugins > Core in the main window.
Plugins may return actions from createManagementActions to populate their own
submenu. Plugins without management actions remain visible as supported cores.
Third-party discovery
Third-party packages register an entry point in pyproject.toml:
[project.entry-points."furious.plugins"]
example-core = "furious_example.plugin:ExamplePlugin"
The entry point may expose a FuriousPlugin instance, a FuriousPlugin
subclass, a zero-argument callable returning one plugin, or a list/tuple of
plugins. Plugins execute inside the Furious process and must therefore be
treated as trusted Python code.
from Furious.Plugins import FuriousPlugin, PluginProtocol, PluginRouting
class ExamplePlugin(FuriousPlugin):
apiVersion = 1
pluginId = 'example.core'
displayName = 'Example Core'
protocols = (
PluginProtocol(
id='example',
displayName='Example',
addActionText='Add Example Server...',
menuOrder=100,
separatorBefore=True,
),
)
configurationTypes = (ExampleConfig,)
coreTypes = (ExampleCore,)
# Implement configFromString/configFromDict, blankConfig,
# createEditorForProtocol, startCore, and prepareDownloadTest as needed.
# createManagementActions, routingOptions,
# prepareTUN, configureEnvironment, afterConnected, and
# logTimestampPatterns are optional.
routingOptions(config) may return PluginRouting values for routing modes
supported by the given configuration. The tray Routing submenu follows the
active server's plugin and is hidden when that plugin returns no routing modes.
The host validates the current setting and falls back to the plugin's first
option before starting its core. Routing display names are treated as literal
text by default; set translatable=True only when the display name is an
application translation key. User-provided labels should remain literal.
Configuration classes should subclass ConfigFactory and implement its table
display, proxy endpoint, validity, serialization, and URI methods. Core process
classes normally subclass CoreProcessWorker; editor dialogs normally subclass
GuiEditorWidgetQDialog.
Plugin modules can be discovered while the Furious.Qt package is still being
initialized. Keep metadata, configuration, routing, and core imports at module
scope, but defer imports of Qt-dependent editors, windows, actions, and managers
until their plugin hook is called.
prepareTUN(config) is called only for a normal connection while the host is
in TUN mode. It may modify the copied runtime configuration and return True
to indicate that the plugin handles TUN itself. Returning False keeps the
host-provided tun2socks implementation.
Protocol IDs are case-insensitive. Plugin IDs, protocol IDs, configuration types, and core types must be unique. Conflicting or incompatible third-party plugins are rejected without preventing other entry points from loading.