update plugin Skills guidance for uninstall()

Agents were inferring naturally how to cleanup dependencies coming from community plugins by putting an uninstall() function sometimes. That wasn't always the case and now the flow is more bounded to the install(), uninstall() and preupdate() requirements when dependencies are involved.

Alessandro committed Apr 12, 2026 at 18:26 UTC 8240edb400bfe78e97366dbff25cdceba6dc55bc
5 files changed +23 -3
skills/a0-create-plugin/SKILL.md
+1
@@ -282,6 +282,7 @@ If your plugin needs framework-internal hook points, add a `hooks.py` file at th
282 - Current built-in usage:
283 - the plugin installer calls `install()` in `hooks.py` after placing a plugin in `usr/plugins/`
284 - the plugin updater calls `pre_update()` in `hooks.py` immediately before pulling new plugin code into place
285 + - the plugin uninstaller calls `uninstall()` in `hooks.py` before deleting the plugin directory — use this to clean up any dependencies or state created by `install()`
286 - Hook functions may be sync or async.
287 - Hooks should be reversible and cleanup-safe. Prefer framework-managed state and plugin-owned paths over permanent system modifications.
288
skills/a0-debug-plugin/SKILL.md
+15
@@ -138,6 +138,21 @@ print('Done')
138 "
139 ```
140
141 +If the `uninstall()` hook is not running when the plugin is removed:
142 +- Check the function is named exactly `uninstall` (not `on_uninstall` or similar)
143 +- Check for exceptions in the function
144 +- The `uninstall()` hook is called by `uninstall_plugin()` in `helpers/plugins.py` before the plugin directory is deleted. If the user removed the plugin manually (`rm -rf`), the hook was bypassed — always use the API or UI to uninstall.
145 +- Manually trigger it in the **framework runtime** the same way:
146 +
147 +```bash
148 +cd /a0 && /opt/venv-a0/bin/python -c "
149 +import asyncio
150 +from helpers.plugins import call_plugin_hook
151 +asyncio.run(call_plugin_hook('<plugin_name>', 'uninstall'))
152 +print('Done')
153 +"
154 +```
155 +
156 ---
157
158 ## 8. Check Agent Zero logs
skills/a0-plugin-router/SKILL.md
+1 -1
@@ -76,7 +76,7 @@ always_enabled: false # forces ON, disables toggle (framework use only)
76 | `extensions/webui/<point>/` | HTML/JS injected into UI breakpoints |
77 | `webui/config.html` | Plugin settings UI |
78 | `webui/*.html`, `webui/*.js` | Full plugin pages and Alpine stores |
79 -| `hooks.py` | Framework runtime hooks (install, pre_update, cache, registration) |
79 +| `hooks.py` | Framework runtime hooks (install, uninstall, pre_update, cache, registration) |
80 | `execute.py` | User-triggered script (setup, maintenance, repair) |
81 | `default_config.yaml` | Settings defaults |
82 | `README.md` | Optional locally; strongly recommended for community plugins so Plugin Hub users can inspect the plugin |
skills/a0-review-plugin/SKILL.md
+1 -1
@@ -52,7 +52,7 @@ Inspect the plugin directory layout:
52 - [ ] If `agents/` exists: agent profiles with `<profile>/agent.yaml` (standard directory)
53 - [ ] If `conf/` exists: configuration files such as `model_providers.yaml` (standard directory)
54 - [ ] If `webui/config.html` exists: plugin must declare at least one `settings_sections` entry
55 -- [ ] If `hooks.py` exists: review whether it defines the lifecycle hook functions the plugin appears to rely on, especially `install` and `pre_update` when the plugin needs install-time or update-time behavior
55 +- [ ] If `hooks.py` exists: review whether it defines the lifecycle hook functions the plugin appears to rely on, especially `install`, `pre_update`, and `uninstall` when the plugin needs install-time, update-time, or cleanup behavior — if `install()` adds dependencies, flag a missing `uninstall()` as WARN
56 - [ ] If `execute.py` exists: check it has a `main()` function and `if __name__ == "__main__": sys.exit(main())`
57 - [ ] `LICENSE` at plugin root: Agent Zero does not require it for local plugins, but it is **required** at the repo root before submitting to the Plugin Index. If missing → **WARN** — `LICENSE absent — required for community contribution (Plugin Index); optional for local-only use`
58 - [ ] `default_config.yaml` (if present): valid YAML
skills/a0-review-plugin/checklists.md
+5 -1
@@ -232,7 +232,7 @@ save_plugin_config(
232 ## hooks.py Environment Targeting
233
234 ```python
235 -# hooks.py - install/pre_update hook example
235 +# hooks.py - install/uninstall/pre_update hook example
236 import subprocess
237 import sys
238
@@ -241,6 +241,10 @@ def install():
241 # This installs into the Agent Zero FRAMEWORK runtime (/opt/venv-a0)
242 subprocess.run([sys.executable, "-m", "pip", "install", "some-package==1.0.0"], check=True)
243
244 +def uninstall():
245 + """Called by framework before deleting plugin directory. Clean up dependencies added by install()."""
246 + subprocess.run([sys.executable, "-m", "pip", "uninstall", "-y", "some-package"], check=True)
247 +
248 def pre_update():
249 """Called by framework immediately before plugin update pulls new code into place."""
250 # This installs into the Agent Zero FRAMEWORK runtime (/opt/venv-a0)