Create and run NetAlertX plugins. Use this when asked to create plugin, run plugin, test plugin, plugin development, or execute plugin script.
69
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
server/plugins/<code_name>/.config.json and script.py to understand its functionality and settings.python3 server/plugins/<code_name>/script.py./tmp/log/plugins/last_result.<PREF>.log) quickly, as the backend may delete it after processing.python3 server/plugins/<code_name>/script.pyEnsure sys.path includes /app/server/plugins and /app/server (as in the template).
server/plugins/<code_name>/
├── config.json # Manifest with settings
├── script.py # Main script
└── ...server/plugins/<code_name>/config.json
code_name == folder nameunique_prefix drives settings and filenames (e.g., ARPSCAN)<PREF>_RUN: execution phase<PREF>_RUN_SCHD: cron-like schedule<PREF>_CMD: script path<PREF>_RUN_TIMEOUT: timeout in seconds — this is enforced by the core plugin runner as the whole script's kill-timeout (server/plugin.py passes it straight to subprocess(..., timeout=...)). It is 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.<PREF>_WATCH: columns to watch for changes<PREF>_IMPORT_ON: optional — gates whether this run's rows get promoted into CurrentScan (only relevant if mapped_to_table: "CurrentScan"). See docs/PLUGINS_IMPORT_BEHAVIOR.md for the related per-row scanCreatesDevice/scanNotificationMode/scanPresence columns.dataType and default_value must agree. dataType: "array"/"object" needs a real JSON literal for default_value ('["default"]'), not a bare string ("default"). setting_value_to_python_type() (server/helper.py) json.loads()s the default at runtime; a bare string fails silently — logged, and [] is returned instead of your default (e.g. devParentRelType, UI_theme, UI_TOPOLOGY_ORDER). If elementOptions already sets multiple/orderable: "false", the setting is scalar — use dataType: "string" instead.Scripts write to /tmp/log/plugins/last_result.<PREF>.log
Important: The backend will almost immediately process this result file and delete it after ingestion. If you need to inspect the output, run the plugin and immediately retrieve the result file before the backend processes it.
Use server/plugins/plugin_helper.py:
from plugin_helper import Plugin_Objects
plugin_objects = Plugin_Objects()
plugin_objects.add_object(...) # During processing
plugin_objects.write_result_file() # Exactly once at endonce: runs once at startupschedule: runs on cron schedulealways_after_scan: runs after every scanbefore_name_updates: runs before name resolutionon_new_device: runs when new device detectedon_notification: runs when notification triggered| Format | Purpose | Runs |
|---|---|---|
| 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 |
Check the plugin against the Conventions Checklist in docs/PLUGINS_DEV.md — RUN default, schedule precedent, RUN_TIMEOUT semantics, reusing core settings, description length, and the multi-instance settings pattern. Most plugin PR review comments trace back to one of these.
Copy from server/plugins/__template and customize.
014b960
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.