plugin-development
GitHub用于创建、运行和测试 NetAlertX 插件的开发技能,涵盖插件结构定义、配置管理、数据契约及执行流程。
Trigger Scenarios
Install
npx skills add netalertx/NetAlertX --skill plugin-development -g -y
SKILL.md
Frontmatter
{
"name": "plugin-development",
"description": "Create and run NetAlertX plugins. Use this when asked to create a plugin, run a plugin, test a plugin, or develop plugin functionality."
}
Plugin Development
Expected Workflow
- Read this skill and
docs/PLUGINS_DEV.mdfor full context. - Find or create the plugin in
server/plugins/<code_name>/. - Read the plugin's
config.jsonand script to understand its functionality and settings. - Run:
python3 server/plugins/<code_name>/script.py - Retrieve the result from
/tmp/log/plugins/last_result.<PREF>.logquickly — the backend processes and deletes it almost immediately.
Plugin Structure
server/plugins/<code_name>/
├── config.json # Manifest: settings, data contract, DB column mapping
├── script.py # Main script (or equivalent, depending on data_source)
└── README.md # Setup/usage docs
code_namemust match the folder name.unique_prefixdrives every setting key and filename (e.g.ARPSCAN→ARPSCAN_RUN,last_result.ARPSCAN.log). Uppercase letters only, no underscores/numbers, must be unique across all plugins.- Ensure
sys.pathincludes/app/server/pluginsand/app/server(as inserver/plugins/__template/rename_me.py).
Settings Pattern
<PREF>_RUN: execution phase (see below). Should default to"disabled"for any non-core plugin.<PREF>_RUN_SCHD: cron-like schedule — check a similar existing plugin for precedent (e.g.pihole_api_scanuses*/5 * * * *) rather than inventing a new cadence.<PREF>_CMD: script path.<PREF>_RUN_TIMEOUT: timeout in seconds — enforced by the core plugin runner as the whole script's kill-timeout (server/plugin.pypasses it straight tosubprocess(..., timeout=...)). Not a safe per-HTTP-call timeout — don't reuse it for individual network calls in a loop, or one slow call can burn the whole budget and get the process killed before it writes its result file. Two correct alternatives:config.json's"timeoutMultiplier": trueon aparams[]entry for a config-declared, known-length loop (seearp_scan);plugin_helper.per_item_timeout()for a runtime-variable-length loop (see the_publisher_*plugins).<PREF>_WATCH: columns to watch for changes.
Data Contract
from plugin_helper import Plugin_Objects
plugin_objects = Plugin_Objects(RESULT_FILE)
plugin_objects.add_object(...) # once per discovered item
plugin_objects.write_result_file() # exactly once, at the end
Full column spec: docs/PLUGINS_DEV_DATA_CONTRACT.md. Note helpVal1-4/watchedValue1-4 both preserve a real 0/False you pass explicitly — only an omitted (None) value defaults to "".
Execution Phases
| Phase | Trigger |
|---|---|
once |
Once at startup |
schedule |
On cron schedule |
always_after_scan |
After every scan |
before_name_updates |
Before name resolution |
on_new_device |
When new device detected |
on_notification |
When notification triggered |
Plugin Formats
| Format | Purpose | Phase |
|---|---|---|
| publisher | Send notifications | on_notification |
| dev scanner | Create/manage devices | schedule |
| name discovery | Discover device names | before_name_updates |
| importer | Import from services | schedule |
| system | Core functionality | schedule |
Before Opening a PR
Check the plugin against the Conventions Checklist — RUN default, schedule precedent, RUN_TIMEOUT semantics, reusing core settings instead of duplicating them, description length (renders in the Settings UI — keep it short), and the multi-instance settings pattern (nested array + popup-form, see rest_import, not a hardcoded "primary"/"secondary" pair). Most plugin PR review comments trace back to one of these, and test/plugins/test_plugin_conventions.py mechanically enforces the RUN-default, description-length, hardcoded-default-drift, and RUN_TIMEOUT-reuse-in-loop items — run it after touching a plugin.
Starting Point
Copy server/plugins/__template/ and customize. Read docs/PLUGINS_DEV.md for the full development guide.
Version History
- a686a01 Current 2026-09-03 06:46


