# How exteraGram plugins work ## How exteraGram plugins actually work A plugin, as exteraGram loads it, is exactly **one Python file** on the device: `/data/user/0/com.exteragram.messenger/files/plugins/.py`. The distribution convention names the same content `.plugin`. The app reads plugin metadata **statically via AST** — it looks for top-level constant assignments (`__id__`, `__name__`, `__description__`, `__author__`, `__version__`, `__icon__`, `__app_version__`, `__sdk_version__`, `__requirements__`) without executing the file. Only `__id__` and `__name__` are required. The file must define exactly one class inheriting `BasePlugin` (`from base_plugin import BasePlugin`). Lifecycle methods (`on_plugin_load`, `on_plugin_unload`, `create_settings`) and hooks (`on_send_message_hook`, `pre_request_hook`, `post_request_hook`, `on_update_hook(s)`, `on_app_event`) are all called by the host; hooks must be registered inside `on_plugin_load` (e.g. `self.add_on_send_message_hook()`). A hook returns a `HookResult(strategy=HookStrategy.MODIFY, params=params)` to apply changes, or a bare `HookResult()` to pass through. Settings rows returned from `create_settings` come from `ui.settings` (`Header`, `Input`, `Switch`, `Text`, `Selector`, `Divider`) and persist through `self.get_setting`/`self.set_setting`. Logging goes through `android_utils.log`; Chaquopy also redirects `sys.stdout`/`sys.stderr` to the logcat tags `python.stdout`/`python.stderr`. This repo does not use the official Elyx/ElyxBuilder archive format — see [`sdk-notes.md`](sdk-notes.md) for why.