unifi-network-setup — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited unifi-network-setup (Agent Skill) and scored it 92/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 2 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 2 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Walk the user through configuring their UniFi Network controller connection. Ask one question at a time and wait for the answer before continuing.
Use the client target that matches the current agent runtime:
claudecodexopenclawIf the runtime is unclear, ask which client to configure. For questions, use the platform's blocking question tool when available (AskUserQuestion in Claude Code, request_user_input in Codex). If no blocking question tool is available, ask in chat with numbered options and wait for the user's reply.
This skill may come from a complete UniFi plugin or a standalone npx skills install. Before using a helper script, verify that the plugin's scripts/ directory exists. If it does not, do not guess a relative path: follow the canonical agent installation guide for the client's native MCP registration path. That guide covers OpenCode, Antigravity, Devin Desktop, Cursor, and other manual clients. A standalone skill install does not install or register the MCP server by itself.
On macOS and Linux, resolve setup scripts relative to this skill file:
../../scripts/check-prereqs.sh../../scripts/set-env.shWhen the host exposes a plugin-root variable such as CLAUDE_PLUGIN_ROOT, using $CLAUDE_PLUGIN_ROOT/scripts/... is also valid. Do not assume the current shell directory is the plugin root.
On Windows, use ../../scripts/set-env.ps1 -Target <claude|codex|openclaw> for every target. Use the matching PowerShell prerequisite checker. Both helpers require uv/uvx and the selected client's CLI (claude, codex or openclaw). A working Python 3.11+ on PATH is used first; otherwise uv supplies managed Python (with a possible first-run download). No separate Python installation is needed. Do not substitute direct client registration commands, which can expose env values in process arguments.
Before asking for credentials, run the prereq checker for the current OS.
On macOS/Linux:
bash <path-to-plugin>/scripts/check-prereqs.sh --target <claude|codex|openclaw> "unifi-network"On Windows PowerShell:
powershell -ExecutionPolicy Bypass -File <path-to-plugin>/scripts/check-prereqs.ps1 -Target <claude|codex|openclaw> -PluginName "unifi-network"If the script exits non-zero, stop and report the error. Do not proceed to credentials.
Ask: "What is your UniFi controller's IP address or hostname?" Example: 192.168.1.1.
Ask which authentication path the user needs:
API-key-only Integration API lookups
the session fails
Ask for the local username when session authentication is selected. Never ask the user to send a password or API key in chat, and never place a raw secret in a tool call or command argument. Ask for exactly one indirect provider per secret: UNIFI_NETWORK_PASSWORD_FILE=<absolute-path> or UNIFI_NETWORK_PASSWORD_COMMAND=<absolute argv>, and UNIFI_NETWORK_API_KEY_FILE=<absolute-path> or UNIFI_NETWORK_API_KEY_COMMAND=<absolute argv>. A command provider can call a Keychain, pass, or 1Password helper; it is not run through a shell and must not prompt. If no indirect provider already exists, explain how to create one outside the chat transcript or use a client-native masked secret UI, then wait. In Claude Code that UI is the plugin's options dialog (/plugin, then unifi-network, then Configure options): its password and API key fields are masked and stored in the system keychain.
All three servers apply the same precedence: non-empty UNIFI_<PRODUCT>_* values override shared UNIFI_* values; empty values count as unset. This applies to host, username and credentials even where bundled YAML defaults name different variables. Shared providers are fallback only. Multiple non-empty spellings (plain, _FILE, _COMMAND) at the selected level refuse startup.
The setup helper switches providers atomically: selecting one spelling removes its saved siblings at the same level while preserving unrelated settings. To remove an authentication path, pipe a JSON patch setting all three saved spellings to null (for example UNIFI_NETWORK_PASSWORD, UNIFI_NETWORK_PASSWORD_FILE, UNIFI_NETWORK_PASSWORD_COMMAND). Remove or override shared fallback settings deliberately too; deleting product settings alone can reactivate shared credentials. Inherited environment providers must also be corrected in the launcher. Never delete a working provider in a separate preparatory write.
Claude Code 2.1.296 and earlier are the exception for a raw password or API key held in the system keychain: they cannot clear one through claude plugin configure or the options dialog. Setup therefore refuses, with nothing changed, any change that would clear it, such as selecting a _FILE or _COMMAND provider for that credential or a null deletion. The message names the variable and the choices: keep the saved secret, or run claude plugin uninstall and claude plugin install with the plugin id it names (usually unifi-network@unifi-plugins), then rerun setup with the provider and the options the message lists. Uninstalling clears every option of the plugin, so offer it to the user and never run it without their consent.
On a newer or unrecognized Claude Code release, setup clears a keychain secret only in a run that changes that one credential: send its patch alone, then other settings in a second run. Setup refuses a combined patch with nothing changed. It saves and verifies the new options first, then clears the secret. If Claude Code keeps the secret, setup removes the credential's providers so only the secret remains, and refuses with the same choices. If a step of a provider switch fails or is interrupted, the credential still has a saved value: rerun setup with the same settings to finish the switch. Until then the server refuses to start if two spellings of the credential are set. A deletion has no replacement: if its step fails, setup reports that whether the secret was cleared is unknown.
Before changing or skipping API-key setup, remove obsolete UNIFI_NETWORK_API_KEY, UNIFI_NETWORK_API_KEY_FILE, and UNIFI_NETWORK_API_KEY_COMMAND spellings with null deletions in the same patch; keep only the selected replacement, or delete all three when deselecting it. In Claude Code, a keychain-held UNIFI_NETWORK_API_KEY cannot be removed this way; see above.
Explain that UniFi API-key support is limited to inventory reads and explicit Integration API tools; legacy mutations and full details may still require a local username and password provider. If selected, configure only an API-key file or command provider, never the raw key.
Ask whether to use defaults or customize:
443, site default, SSL verification false, lazy tool loadingUNIFI_NETWORK_PORT), site (UNIFI_NETWORK_SITE), SSLverification (UNIFI_NETWORK_VERIFY_SSL), and tool registration mode (UNIFI_TOOL_REGISTRATION_MODE: lazy, eager or meta_only; the Claude Code option is registration_mode)
Ask whether to enable write permissions. For Codex and OpenClaw, offer:
For Claude Code, the plugin's options hold only the server-level gates. Offer: read-only (the default), allow updates, allow creates and updates, or allow creates, updates and deletes. Set UNIFI_POLICY_NETWORK_CREATE, UNIFI_POLICY_NETWORK_UPDATE and UNIFI_POLICY_NETWORK_DELETE to true or false, and keep UNIFI_NETWORK_TOOL_PERMISSION_MODE=confirm so every mutation is previewed first. Per-category overrides (UNIFI_POLICY_NETWORK_<CATEGORY>_<ACTION>) are not available for Claude Code and setup refuses them. A user who wants only some categories writable can allow the action server-wide and decline the previews they do not want, or keep the action off.
For Codex and OpenClaw, before writing policy values, inspect a sanitized list of the selected client's existing unifi-network MCP environment variable names (for Codex and OpenClaw, the key names in ~/.config/unifi-mcp/network.env). Remove every existing category-specific UNIFI_POLICY_NETWORK_<CATEGORY>_<ACTION> entry by including null deletions in the same JSON patch, because those entries take precedence over server-level defaults. Preserve unrelated variables. Set UNIFI_NETWORK_TOOL_PERMISSION_MODE=confirm, then add back only the category/action overrides the user selected.
For read-only setup, explicitly configure:
UNIFI_POLICY_NETWORK_CREATE=false
UNIFI_POLICY_NETWORK_UPDATE=false
UNIFI_POLICY_NETWORK_DELETE=falseFor requested writes on Codex or OpenClaw, keep those server-level defaults and add only the selected category/action overrides using the existing UNIFI_POLICY_NETWORK_<CATEGORY>_<ACTION>=true format.
On macOS/Linux, run the target-aware setup script with only values the user provided or selected:
bash <path-to-plugin>/scripts/set-env.sh --target <claude|codex|openclaw> \
UNIFI_NETWORK_HOST=<host> \
UNIFI_NETWORK_USERNAME=<username> \
'UNIFI_NETWORK_PASSWORD_FILE=<absolute-path>' \
UNIFI_NETWORK_TOOL_PERMISSION_MODE=confirm \
UNIFI_POLICY_NETWORK_CREATE=false \
UNIFI_POLICY_NETWORK_UPDATE=false \
UNIFI_POLICY_NETWORK_DELETE=falseAdd optional values and policy variables to the same command. Per-category overrides apply to Codex and OpenClaw only, for example:
bash <path-to-plugin>/scripts/set-env.sh --target <codex|openclaw> \
UNIFI_NETWORK_HOST=<host> \
UNIFI_NETWORK_USERNAME=<username> \
'UNIFI_NETWORK_PASSWORD_COMMAND=<absolute-argv>' \
'UNIFI_NETWORK_API_KEY_FILE=<absolute-path>' \
UNIFI_NETWORK_TOOL_PERMISSION_MODE=confirm \
UNIFI_POLICY_NETWORK_CREATE=false \
UNIFI_POLICY_NETWORK_UPDATE=false \
UNIFI_POLICY_NETWORK_DELETE=false \
UNIFI_POLICY_NETWORK_FIREWALL_POLICIES_UPDATE=trueThe script handles the client-specific write:
with claude plugin configure --values-stdin (values on stdin): non-secret options in user settings.json (pluginConfigs), a raw password or API key in the system keychain. The options apply in every project
~/.config/unifi-mcp/network.env (%USERPROFILE%\.config\unifi-mcp\network.env on Windows), readable by the user only. The plugin's own server reads it through UNIFI_SETTINGS_FILE; setup writes no config.toml entry. Env never enters argv
~/.config/unifi-mcp/network.env, readable by the user only. The plugin's own server reads it through UNIFI_SETTINGS_FILE; setup writes no openclaw.json entry
For raw values or null deletions, use JSON stdin: set-env.sh --target <target> --input-json or set-env.ps1 -Target <target> -InputJson. Have the user supply this JSON locally from a private file or a masked input UI; never put raw secrets in chat, a tool call, command arguments, or a shell history entry. Provider references in the examples are non-secret paths or helper argv, never embedded passwords or API keys. Setup checks that provider files are readable and non-empty and provider executables exist; it does not read secrets, execute providers, or contact the controller. Provider output and controller authentication are checked only when the server starts.
The plugin's own MCP server is the one Codex runs, and it reads the settings file setup wrote, so a plugin upgrade upgrades the server with nothing to rerun. Codex installs an upgrade in the background as a session starts; the next session runs the new server.
Setup before plugin 1.0.0 saved a [mcp_servers.unifi-network] entry in Codex's config.toml instead. That entry takes precedence over the plugin's server and keeps an old server version. Step 0 then prints a notice naming the entry and --refresh. Relay it and, once the user agrees, run refresh from this skill's plugin root, then restart Codex:
bash <plugin-root>/scripts/set-env.sh --target codex --refreshOn Windows: & <plugin-root>/scripts/set-env.ps1 -Target codex -Refresh. Refresh needs no credential input. It moves the entry's UNIFI_ settings, provider references included, into the settings file, removes the entry from config.toml after saving a private backup beside it, and names any other entry settings it did not move. Ordinary setup does the same when it finds the entry. It is needed once. If a settings file already exists and holds different settings, refresh changes nothing and says which to remove.
Setup edits only that entry's tables in config.toml, so every other setting and comment stays as written. If the file lays out its MCP servers in a form setup cannot edit in place (dotted or inline mcp_servers keys), setup lets Codex remove the entry, which drops the comments inside every [mcp_servers.*] table, and says so in its output.
OpenClaw runs the plugin's own MCP server, which reads the settings file setup wrote, so openclaw plugins update upgrades the server with nothing to rerun. A running Gateway applies the update at the next agent turn.
Setup before plugin 1.0.0 saved an mcp.servers.unifi-network entry in openclaw.json instead. That entry replaces the plugin's server and keeps an old server version. Step 0 then prints a notice naming the entry and --refresh. Relay it and, once the user agrees, run refresh from this skill's plugin root:
bash <plugin-root>/scripts/set-env.sh --target openclaw --refreshOn Windows: & <plugin-root>/scripts/set-env.ps1 -Target openclaw -Refresh. Refresh needs no credential input. It moves the entry's UNIFI_ settings, provider references included, into the settings file, saves a private backup of openclaw.json beside it, then removes the entry with openclaw mcp unset and names any other entry settings it did not move. Ordinary setup does the same when it finds the entry. It is needed once. If a settings file already exists and holds different settings, refresh changes nothing and says which to remove.
Earlier versions saved Claude Code settings in the project's .claude/settings.local.json. This version no longer reads them; setup, the prerequisite check and a session-start notice name the leftover variables. From that project, run:
bash <plugin-root>/scripts/set-env.sh --target claude --migrateOn Windows: & <plugin-root>/scripts/set-env.ps1 -Target claude -Migrate. It copies this plugin's settings into its options, then removes only this plugin's keys from the project file atomically. Shared UNIFI_* keys are kept unless every possible consumer is proven migrated; setup currently verifies only this plugin's options. It names the retained shared keys and explains that other consumers have not been verified as migrated. Output includes only variable names, including what it moved and what has no Claude Code option (per-category policy overrides). A missing provider file stops it with nothing changed, as does a provider that would replace a password or API key held in the keychain.
Plugin options apply in every project. If options saved from another project already hold a different host, username, port or site, --migrate refuses and names those variables without values. Ask the user which settings every project should use: rerun with --replace (-Replace) to make this project's settings the options for every project, or remove this plugin's leftover UNIFI_NETWORK_* keys from the project file to keep the saved options. A session-start notice also fires in a project that still holds its own UNIFI_NETWORK_* keys while options from another project are in use; offer the same choice there. When the project's host, username, port and site equal the saved options, the notice says nothing changes instead; offer to remove the leftover keys, or to tidy up with --migrate, which also copies the project's other settings, such as its credential source, into the options.
After the migration, in a session that was already open, run /reload-plugins or start a new session. /mcp reconnect alone keeps the options the session started with: it reports success, but the server stays in setup mode. Use /mcp reconnect plugin:unifi-network:unifi-network only if /mcp shows the server as failed. Once no UniFi plugin keys remain in the project file, the prerequisite check names any shared UNIFI_* keys still there: Claude Code exports them into every process in that project, so suggest removing them once nothing else needs them.
On validation, dependency, registration, or write failure the previous file and registration remain in place. Repair malformed configuration without discarding unrelated settings, install the reported dependency, or correct the provider, then rerun. --dry-run / -DryRun validates the patch without changing files and omits values. OpenClaw setup reads openclaw.json as strict JSON; a JSON5 configuration is refused unchanged. After a forced termination, remove adjacent .setup-lock and .unifi-setup-* staging directories only after confirming no setup process is running. Staging files are private and may contain credentials; delete them without displaying their contents. An interruption at publication leaves either the old configuration or the complete new one.
For Claude Code, tell the user:
"Saved as the unifi-network plugin's Claude Code options (a raw password or API key goes to the system keychain). In this session, run /reload-plugins (a new session also loads the options); /mcp reconnect alone keeps the options the session started with, so the server would stay in setup mode. Then run /mcp and check that plugin:unifi-network:unifi-network offers more than one tool: a server offering only its setup-status tool is still unconfigured. Use /mcp reconnect plugin:unifi-network:unifi-network only if /mcp shows the server as failed. Review or change the options with /plugin, then unifi-network, then Configure options."
For Codex, tell the user:
"Saved the settings for unifi-network to ~/.config/unifi-mcp/network.env, readable by you only. The plugin's own server reads them and follows plugin upgrades on its own. Restart Codex so the server loads them."
For OpenClaw, tell the user:
"Saved the settings for unifi-network to ~/.config/unifi-mcp/network.env, readable by you only. The plugin's own server reads them and follows plugin updates on its own. OpenClaw starts it with these settings in a new session or after openclaw gateway restart; a session that is already open keeps the unconfigured server until then."
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.