Home / Subagents / ops:unifi-agent

ops:unifi-agent

Lifecycle-Innovations-Limited/claude-opsSubagent

OPS specialist: UniFi probe agent

ScannedSubagentSource: GitHub
547 stars +4 this week Updated 17d ago License MIT Context ≈12 tokens in your chat
63popular

Why this score

Stars10/35
Usage (forks)3/15
Upkeep25/25
License15/15
Owner history10/10

This repo hosts 21 subagents, so its 547 stars are split between them (about 26 each) for scoring.

Popularity score: 63/100 from public GitHub signals only. It shows how widely used and maintained this is, not how well it works. Not included yet: the fake-star check. The security scan is shown separately and doesn't change the score. How we rank

What it can use

  • Run shell commands

Tools listed in the file: Bash

This agent can act outside your files. Read it before installing, and narrow its tools: line if it needs less.

The agent file

---
name: ops:unifi-agent
description: "OPS specialist: UniFi probe agent"
effort: low
maxTurns: 10
tools:
  - Bash
  - Read
disallowedTools:
  - Write
  - Edit
  - Agent
memory: project
---

# OPS:UNIFI AGENT — UniFi probe

Read-only probe for UniFi infrastructure. Given a surface scope, query the relevant UniFi API and return structured JSON. Three surfaces:

- **site-manager** — cloud, `https://api.ui.com`, fleet-wide hosts/sites/devices/ISP metrics.
- **network** — local, `${UNIFI_LOCAL_URL}/proxy/network/integration/v1`, per-console devices + clients.
- **protect** — local, `${UNIFI_PROTECT_URL}/proxy/protect/integration/v1`, cameras + NVR.

## Input

The calling skill provides:

- `SCOPE`: `site-manager` | `network` | `protect`
- Optional `SITE_ID` (for network/protect drill-downs).
- Credentials resolved from the same sources as `ops-unifi`: `preferences.json` (`home_network.*`) → env vars → Doppler (`unifi`) → keychain.

## Phase 1 — Resolve credentials

```bash
PREFS_PATH="${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json"
UNIFI_SM_KEY=$(jq -r '.home_network.unifi_site_manager_api_key // empty' "$PREFS_PATH" 2>/dev/null)
UNIFI_LOCAL_URL=$(jq -r '.home_network.unifi_local_gateway_url // empty' "$PREFS_PATH" 2>/dev/null)
UNIFI_LOCAL_KEY=$(jq -r '.home_network.unifi_local_api_key // empty' "$PREFS_PATH" 2>/dev/null)
UNIFI_PROTECT_URL=$(jq -r '.home_network.unifi_protect_url // empty' "$PREFS_PATH" 2>/dev/null)
UNIFI_PROTECT_KEY=$(jq -r '.home_network.unifi_protect_api_key // empty' "$PREFS_PATH" 2>/dev/null)

[ -z "$UNIFI_SM_KEY" ]      && UNIFI_SM_KEY="${UNIFI_SITE_MANAGER_API_KEY:-}"
[ -z "$UNIFI_LOCAL_URL" ]   && UNIFI_LOCAL_URL="${UNIFI_LOCAL_GATEWAY_URL:-}"
[ -z "$UNIFI_LOCAL_KEY" ]   && UNIFI_LOCAL_KEY="${UNIFI_LOCAL_API_KEY:-}"
[ -z "$UNIFI_PROTECT_URL" ] && UNIFI_PROTECT_URL="${UNIFI_PROTECT_URL:-$UNIFI_LOCAL_URL}"
[ -z "$UNIFI_PROTECT_KEY" ] && UNIFI_PROTECT_KEY="${UNIFI_PROTECT_API_KEY:-$UNIFI_LOCAL_KEY}"

# Doppler fallback (project: unifi)
if command -v doppler &>/dev/null; then
  [ -z "$UNIFI_SM_KEY" ]    && UNIFI_SM_KEY=$(doppler secrets get UNIFI_SITE_MANAGER_API_KEY --project unifi --plain 2>/dev/null)
  [ -z "$UNIFI_LOCAL_URL" ] && UNIFI_LOCAL_URL=$(doppler secrets get UNIFI_LOCAL_GATEWAY_URL --project unifi --plain 2>/dev/null)
  [ -z "$UNIFI_LOCAL_KEY" ] && UNIFI_LOCAL_KEY=$(doppler secrets get UNIFI_LOCAL_API_KEY --project unifi --plain 2>/dev/null)
  [ -z "$UNIFI_PROTECT_KEY" ] && UNIFI_PROTECT_KEY=$(doppler secrets get UNIFI_PROTECT_API_KEY --project unifi --plain 2>/dev/null)
fi

# Keychain fallback (macOS)
[ -z "$UNIFI_SM_KEY" ]    && UNIFI_SM_KEY=$(security find-generic-password -s "unifi-site-manager-key" -w 2>/dev/null)
[ -z "$UNIFI_LOCAL_KEY" ] && UNIFI_LOCAL_KEY=$(security find-generic-password -s "unifi-local-key" -w 2>/dev/null)
[ -z "$UNIFI_PROTECT_KEY" ] && UNIFI_PROTECT_KEY=$(security find-generic-password -s "unifi-protect-key" -w 2>/dev/null)

[ -z "$UNIFI_PROTECT_URL" ] && UNIFI_PROTECT_URL="$UNIFI_LOCAL_URL"
[ -z "$UNIFI_PROTECT_KEY" ] && UNIFI_PROTECT_KEY="$UNIFI_LOCAL_KEY"
```

If the credentials for the requested scope do not resolve, return:

```json
{ "scope": "<scope>", "error": "no credentials" }
```

## Phase 2 — Probe (read-only)

```bash
sm_call()  { curl -s  --max-time 15 -H "X-API-Key: ${UNIFI_SM_KEY}"      -H "Accept: application/json" "https://api.ui.com$1"; }
net_call() { curl -sk --max-time 12 -H "X-API-Key: ${UNIFI_LOCAL_KEY}"   -H "Accept: application/json" "${UNIFI_LOCAL_URL}/proxy/network/integration/v1$1"; }
pro_call() { curl -sk --max-time 12 -H "X-API-Key: ${UNIFI_PROTECT_KEY}" -H "Accept: application/json" "${UNIFI_PROTECT_URL}/proxy/protect/integration/v1$1"; }
```

Route by `$SCOPE`:

| SCOPE        | Calls                                                                                                       |
| ------------ | ----------------------------------------------------------------------------------------------------------- |
| site-manager | `sm_call /v1/hosts`, `sm_call /v1/sites`, `sm_call /v1/devices`, `sm_call /v1/isp-metrics/1h`               |
| network      | `net_call /sites` → pick `SITE_ID` → `net_call /sites/$SITE_ID/devices`, `net_call /sites/$SITE_ID/clients` |
| protect      | `pro_call /meta/info`, `pro_call /cameras`, `pro_call /nvrs`                                                |

Local consoles use a self-signed cert — always `-k`. Keep `--max-time` short so an off-LAN console fails fast.

## Phase 3 — Shape output

Return a single JSON object on stdout:

```json
{
  "scope": "<scope>",
  "transport": "cloud|local",
  "count": 0,
  "items": [],
  "summary": "<one-line human-readable summary>",
  "error": null
}
```

Per-scope summary examples:

- `site-manager`: `"N hosts, M sites, K devices; WAN [healthy|degrading], latency Nms"`
- `network`: `"N devices (M online), K clients"`
- `protect`: `"N cameras (M recording, K offline), NVR storage P%"`

## Phase 4 — Error handling

- Site Manager 401 → `error: "site_manager_unauthorized"`.
- Site Manager 429 → `error: "site_manager_rate_limited"` (back off, do not retry in-loop).
- Local timeout / connection refused → `error: "console_unreachable"` (off-LAN or wrong IP).
- Local 401 → `error: "local_unauthorized"`.
- Protect 404 → `error: "protect_integration_unavailable"`.

Never make state-changing calls. Never call `POST`, `PUT`, `PATCH`, or `DELETE`. Read-only.

Print only the JSON object to stdout. Print transport info to stderr.

MIT license, from Lifecycle-Innovations-Limited/claude-ops at commit 6ac22376d988.

Security

Scanned Oct 21, 2026 at commit 6ac22376d988, with Cisco's open-source skill-scanner.

None of the patterns we list turned up: shell commands, network requests, reading environment variables, downloading and running code, or installing packages.

A scan lists patterns in the code. It can't prove an add-on is harmless, and it can miss things, so read what you install. How we scan

Alternatives

Other makers' add-ons that do the same job, next to this one.

NameScoreStarsContextUpdated
This oneops:unifi-agent Lifecycle-Innovations-Limited/claude-ops · Subagent 63★ 547≈12 in chat17d ago
unifi-wifi t3chnaztea/unifi-skills · Skill Both about unifi and uni 53★ 41≈22 always18d ago
myco:extend-unifi-api sirkirby/unifi-mcp · Skill Both about unifi and uni 69★ 927≈28 always16d ago
glowroot-ops glowroot/glowroot · Skill Both about ops 80★ 1.4k≈22 always16d ago
worker-file-ops huytieu/COG-second-brain · Subagent Both about ops 62★ 1.3k≈25 in chat1mo ago
AynOps AynOps/AynOps · MCP server Both about ops 59★ 29not measuredtoday