OPS on-demand: This skill should be used when the user asks to "unifi", "cameras", or "/ops:ops-unifi"

MITAuto-check: notes

Install Ops Unifi

skills CLI
$ npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-unifi -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install Lifecycle-Innovations-Limited/claude-ops ops-unifi --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git skills-src && mkdir -p .claude/skills && cp -r skills-src/claude-ops/skills/ops-unifi .claude/skills/ops-unifi && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
ops-unifi
GitHub stars
542
Token cost
~7k tokens
SKILL.md length
1,626 words
Files
2 (incl. references)
Skills in repo
67
Repo updated
First seen
Licence
MIT

At a glance

OPS on-demand: This skill should be used when the user asks to "unifi", "cameras", or "/ops:ops-unifi"

  • Works in 4 steps: Resolve credentials → Route by argument → Cross-channel integration → …
  • SKILL.md covers Runtime Context, Phase 1 — Resolve credentials, Phase 2 — Route by argument and STATUS (default — empty…, plus 16 more sections
  • Calls jq and curl; reaches api.ui.com; needs UNIFI_PROTECT_KEY and UNIFI_SM_KEY

What it does

Ops Unifi is an agent skill from Lifecycle-Innovations-Limited/claude-ops. OPS on-demand: This skill should be used when the user asks to "unifi", "cameras", or "/ops:ops-unifi"

Its SKILL.md is about 7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 2 other files, including reference files (for example `references/cli.md`).

The repository describes itself as: Business operating system for Claude Code — 57 skills, 21 agents, smart daemon. Unified inbox (WhatsApp/Email/Slack/Telegram), autonomous PR merge, full-AWS monitoring, revenue… The licence is MIT.

Example prompts

  • “cameras”
  • “/ops:ops-unifi”
  • “/ops-unifi”

Requirements

  • A credential in UNIFI_SM_KEY
  • A credential in UNIFI_LOCAL_KEY
  • Pre-approved tools (allowed-tools): Bash, Read, Write, Grep, Glob, Agent, TeamCreate, SendMessage, AskUserQuestion, WebFetch, WebSearch

Workflow steps

4 steps, taken from the step headings in SKILL.md.

  1. Resolve credentials
  2. Route by argument
  3. Cross-channel integration
  4. Error handling

What it can do on your machine

Read from SKILL.md and the folder at commit ee9c784. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves these tools, so the agent can use them without asking each time:

    • Bash
    • Read
    • Write
    • Grep
    • Glob
    • Agent
    • TeamCreate
    • SendMessage
    • AskUserQuestion
    • WebFetch

    …and 1 more on the same allowed-tools line.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • jq
    • curl

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • api.ui.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names these keys or tokens, usually read from environment variables:

    • UNIFI_PROTECT_KEY
    • UNIFI_SM_KEY
    • UNIFI_LOCAL_KEY
    • UNIFI_SITE_MANAGER_API_KEY
    • UNIFI_LOCAL_API_KEY
    • UNIFI_PROTECT_API_KEY

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Ops Unifi loads about 7k tokens when it runs, and up to ~8.5k if it reads all its reference files. Until then it costs about 28 tokens; SKILL.md has 1,626 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~28
When it runs · the whole SKILL.md, loaded when a task matches
~7k
With references · SKILL.md plus every file in references/, read only if the agent opens them
~8.5k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NotePre-approves every shell command (allowed-tools: Bash)SKILL.md
    allowed-tools: Bash, Read, Write, Grep, Glob, Agent, TeamCreate, SendMessage, AskUserQuestion, WebFetch, WebSearch

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from Lifecycle-Innovations-Limited/claude-ops at commit ee9c784, republished under its MIT licence (© Lifecycle-Innovations-Limited). 1,626 words, ~6,967 tokens.

Download SKILL.mdSave it as .claude/skills/ops-unifi/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
ops-unifi
description
OPS on-demand: This skill should be used when the user asks to "unifi", "cameras", or "/ops:ops-unifi"
allowed-tools
Bash, Read, Write, Grep, Glob, Agent, TeamCreate, SendMessage, AskUserQuestion, WebFetch, WebSearch
argument-hint
[status|sites|devices|clients|isp|sdwan|protect|snapshot|restart|block|predict|setup]
effort
medium
maxTurns
30
context
fork

OPS ► UNIFI — Network Command Center (UniFi OS)

Load ops-rules before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If AskUserQuestion / Workflow are missing, follow Rule 10 in ops-rules (Hermes: numbered options / two-turn Telegram card; delegate_task).

Control Ubiquiti UniFi infrastructure across all three official APIs:

  1. Site Manager API (cloud, api.ui.com) — fleet-wide oversight: every console, site, device, and ISP/WAN health metric across all your UniFi deployments in one call. Read-first (write endpoints roll out per-key).
  2. Network Integration API (local, https://<gateway>/proxy/network/integration/v1) — per-console control: list/restart devices, list/block clients, manage hotspot vouchers, read live statistics.
  3. Protect Integration API (local, https://<host>/proxy/protect/integration/v1) — cameras, NVR, sensors, lights, chimes, viewers: list, snapshot, stream, and patch device settings; real-time WebSocket event stream.

This skill is curl-native (works headless, no SDK dependency) — consistent with the rest of /ops:*. If you want a richer natural-language surface, an optional community MCP can be enabled (see Optional MCP path at the end); the skill never depends on it.

Runtime Context

Before executing, load available context:

  1. Preferences: Read ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json

    • timezone — display all timestamps in user's timezone
    • home_network.unifi_site_manager_api_key — cloud API key from unifi.ui.com (read-only multi-site)
    • home_network.unifi_local_gateway_url — e.g. https://192.168.1.1 (UniFi OS console LAN address)
    • home_network.unifi_local_api_key — Network Integration API key (generated in the Network app)
    • home_network.unifi_protect_url — Protect host (often same as gateway); defaults to gateway URL
    • home_network.unifi_protect_api_key — Protect Integration API key (defaults to local key if unset — one UniFi OS key often works for both)
  2. Daemon health: Read ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/daemon-health.json

    • If action_needed is not null → surface it before running any UniFi operations
    • On any auth/connectivity failure in this skill, write action_needed back to daemon-health.json
  3. Secrets: Resolve UniFi credentials via userConfig → env vars → Doppler → keychain (see Phase 1 below)

Phase 1 — Resolve credentials

Resolve UniFi credentials in this order (userConfig → env → Doppler → keychain). The three surfaces are independent — any subset may be configured; the skill degrades gracefully and only runs the surfaces it has keys for.

bash
PLUGIN_DATA_DIR="${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}"
PREFS_PATH="${PLUGIN_DATA_DIR}/preferences.json"

# Capture shell-exported protect host before prefs load overwrites UNIFI_PROTECT_URL
_ENV_UNIFI_PROTECT_URL="${UNIFI_PROTECT_URL:-}"

# 1. Plugin userConfig (preferences.json → home_network.*)
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)

# 2. Environment variables (override userConfig if set)
[ -n "$UNIFI_SM_KEY" ]      || UNIFI_SM_KEY="${UNIFI_SITE_MANAGER_API_KEY:-${UNIFI_SM_KEY:-}}"
[ -n "$UNIFI_LOCAL_URL" ]   || UNIFI_LOCAL_URL="${UNIFI_LOCAL_GATEWAY_URL:-${UNIFI_LOCAL_URL:-}}"
[ -n "$UNIFI_LOCAL_KEY" ]   || UNIFI_LOCAL_KEY="${UNIFI_LOCAL_API_KEY:-${UNIFI_LOCAL_KEY:-}}"
[ -n "$UNIFI_PROTECT_URL" ] || UNIFI_PROTECT_URL="${_ENV_UNIFI_PROTECT_URL:-}"
[ -n "$UNIFI_PROTECT_KEY" ] || UNIFI_PROTECT_KEY="${UNIFI_PROTECT_API_KEY:-${UNIFI_PROTECT_KEY:-}}"

# 3. 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

# 4. 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)

# 5. Sensible defaults — Protect commonly shares host + key with the Network console
[ -z "$UNIFI_PROTECT_URL" ] && UNIFI_PROTECT_URL="$UNIFI_LOCAL_URL"
[ -z "$UNIFI_PROTECT_KEY" ] && UNIFI_PROTECT_KEY="$UNIFI_LOCAL_KEY"

Unless the argument is setup, configure, init, or token, if none of (UNIFI_SM_KEY), (UNIFI_LOCAL_URL + UNIFI_LOCAL_KEY), nor (UNIFI_PROTECT_URL + UNIFI_PROTECT_KEY) is resolvable, tell the user and exit gracefully:

No UniFi credentials configured. Run /ops:setup --section network to configure your UniFi Site Manager and/or local console API keys.

Write action_needed: "configure_unifi" to ${PLUGIN_DATA_DIR}/daemon-health.json and exit.

Set helpers used by all phases below:

bash
SM_BASE="https://api.ui.com"
NET_BASE="${UNIFI_LOCAL_URL}/proxy/network/integration/v1"
PRO_BASE="${UNIFI_PROTECT_URL}/proxy/protect/integration/v1"

# Site Manager (cloud) call
sm_call() {  # sm_call <path> [method] [body]
  [ -z "$UNIFI_SM_KEY" ] && { echo '{"error":"no site-manager key"}'; return 1; }
  curl -s --max-time 15 -X "${2:-GET}" \
    -H "X-API-Key: ${UNIFI_SM_KEY}" -H "Accept: application/json" -H "Content-Type: application/json" \
    ${3:+--data "$3"} "${SM_BASE}$1"
}

# Network Integration (local) call — self-signed cert ⇒ -k
net_call() {  # net_call <path> [method] [body]
  [ -z "$UNIFI_LOCAL_URL" ] || [ -z "$UNIFI_LOCAL_KEY" ] && { echo '{"error":"no local network creds"}'; return 1; }
  curl -sk --max-time 12 -X "${2:-GET}" \
    -H "X-API-Key: ${UNIFI_LOCAL_KEY}" -H "Accept: application/json" -H "Content-Type: application/json" \
    ${3:+--data "$3"} "${NET_BASE}$1"
}

# Protect Integration (local) call — self-signed cert ⇒ -k
pro_call() {  # pro_call <path> [method] [body]
  [ -z "$UNIFI_PROTECT_URL" ] || [ -z "$UNIFI_PROTECT_KEY" ] && { echo '{"error":"no protect creds"}'; return 1; }
  curl -sk --max-time 12 -X "${2:-GET}" \
    -H "X-API-Key: ${UNIFI_PROTECT_KEY}" -H "Accept: application/json" -H "Content-Type: application/json" \
    ${3:+--data "$3"} "${PRO_BASE}$1"
}

Phase 2 — Route by argument

InputAction
(empty)Cross-surface status dashboard
status, dashboardCross-surface status dashboard
sites, hosts, consolesSite Manager: hosts + sites
devices, device, aps, switches, gatewayNetwork: devices per site
clients, who, wifi, onlineNetwork: clients
isp, wan, internet, uptime, latencySite Manager: ISP/WAN metrics
sdwan, sd-wanSite Manager: SD-WAN configs
protect, cameras, camera, nvr, surveillanceProtect: cameras + NVR
snapshot <camera>Protect: camera snapshot
restart, reboot <device>Network: device restart (CONFIRM — Rule 5)
block <client> / unblock <client>Network: client block/unblock (CONFIRM — Rule 5)
voucher [create|list|revoke]Network: hotspot vouchers
predict, insights, anomaly, healthPredict / insights (cross-surface anomaly scan)
setup, configure, init, tokenSetup flow

Pick the first site automatically when a surface needs a siteId and only one site exists; otherwise present sites via AskUserQuestion (max 4, Rule 1) and let the user choose.


STATUS (default — empty argument)

One-screen network dashboard. Probe Site Manager (hosts/devices/ISP), Network (devices/clients), and Protect (cameras) in parallel — separate Bash calls or the Agent Team in Agent Teams support below — then render.

bash
# Site Manager fleet view (skip surface when key missing)
[ -n "$UNIFI_SM_KEY" ] && sm_call "/v1/hosts" | jq '{hosts: ([.data // [] | .[] | {name:.reportedState.hostname, model:.reportedState.hardware.shortname, state:.reportedState.state}])}'
[ -n "$UNIFI_SM_KEY" ] && sm_call "/v1/devices" | jq '{fleet_devices: ([.data // [] | length])}'

# Local network (skip surface when creds missing)
if [ -n "$UNIFI_LOCAL_URL" ] && [ -n "$UNIFI_LOCAL_KEY" ]; then
  SITE=$(net_call "/sites" | jq -r '.data[0].id // .data[0].internalReference // empty')
  net_call "/sites/${SITE}/devices" | jq '{net_devices: (.data|length), online: ([.data[]|select(.state=="ONLINE")]|length)}'
  net_call "/sites/${SITE}/clients" | jq '{clients: (.data|length)}'
fi

# Protect (skip surface when creds missing)
[ -n "$UNIFI_PROTECT_URL" ] && [ -n "$UNIFI_PROTECT_KEY" ] && pro_call "/cameras" | jq '{cameras: length, recording: ([.[]|select(.isRecording==true)]|length), offline: ([.[]|select(.state!="CONNECTED")]|length)}'

Desktop render:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 OPS ► UNIFI — [host-name] — [timestamp]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

CONSOLE      [model]  ([fw])   state: [online]
SURFACES     site-manager [✓]  network [✓]  protect [✓]

NETWORK      [N online] / [N devices]   ([N] offline)
CLIENTS      [N connected]   (wired [N] · wifi [N])
WAN / ISP    [status]  latency [Nms]  uptime [N.NN%] (24h)

PROTECT      [N cameras]  [N recording]  [N offline]

ALERTS       [N]
  [device] offline / [WAN] degraded / [camera] disconnected   (if any)

──────────────────────────────────────────────────────
 [s] sites   [d] devices   [c] clients   [i] isp
 [p] protect   [x] predict   [setup] credentials
──────────────────────────────────────────────────────

Mobile mode ($SSH_CONNECTION set or $OPS_MOBILE=1): plain text, 5–8 lines, no banners.

unifi: [N]/[N] net devices online · [N] clients.
wan: [status] · latency [N]ms · uptime [N.NN]%.
protect: [N] cams ([N] recording, [N] offline).
alerts: [N].
next: /ops-unifi devices | isp | protect | predict

If any surface key is missing, show that surface as [—] and skip its calls (never error the whole dashboard on one missing key). If a device/WAN/camera alert is critical, surface it at the top and suggest piping to /ops:ops-comms (Rule 6 — stage draft, never auto-send).


SITES / HOSTS

Site Manager fleet inventory — every console and site across the account.

bash
sm_call "/v1/hosts" | jq -r '.data[]? | "• \(.reportedState.hostname // .id)  \(.reportedState.hardware.shortname // "?")  \(.reportedState.state // "?")  ip=\(.ipAddress // "?")"'
sm_call "/v1/sites" | jq -r '.data[]? | "  site: \(.meta.name // .name // .siteId)  devices=\(.statistics.counts.totalDevice // "?")  clients=\(.statistics.counts.totalClient // "?")"'

Render grouped by host → its sites, with model/fw/state and device+client counts. Footer offers [d] drill into a site's devices.


DEVICES

Local Network device inventory for a site — APs, switches, gateways with live state.

bash
SITE="${CHOSEN_SITE}"
net_call "/sites/${SITE}/devices" | jq -r '.data[]? | "• \(.name)  \(.model // .shortname)  \(.state)  fw=\(.firmwareVersion // "?")  uplink=\(.uplink.type // "?")"'
# Drill: latest stats for one device
net_call "/sites/${SITE}/devices/${DEVICE_ID}/statistics/latest" | jq '{cpu:.cpuUtilizationPct, mem:.memoryUtilizationPct, rxMbps:(.uplink.rxRateBps/1e6), txMbps:(.uplink.txRateBps/1e6), uptime_s:.uptimeSec}'

Filter from argument: devices aps → type=="uap"/class AP; devices switches → usw; devices gateway → ugw/udm. Render grouped by type, flag any state != "ONLINE". Offer [a] restart a device (→ goes through the confirmed RESTART path below).


CLIENTS

Connected clients on a site, wired + wireless.

bash
SITE="${CHOSEN_SITE}"
net_call "/sites/${SITE}/clients" | jq -r '.data[]? | "• \(.name // .hostname // .mac)  \(.ipAddress // "?")  \(if .uplinkDeviceId then "wifi@"+(.connectedToName//"?") else "wired" end)  rx=\(.rxBytes // 0)"'

Sort by usage; flag clients with weak signal (.signal < -70) or high retries. Footer offers [b] block a client / [u] unblock (confirmed path below).


ISP / WAN

Site Manager ISP metrics — WAN latency, packet loss, downtime, throughput. The backbone of predict mode.

bash
# 1h-granularity metrics for the trailing window
sm_call "/v1/isp-metrics/1h" | jq '{
  sites: [.data[]? | {
    site: (.siteId // .meta.name),
    avgLatencyMs: (.metrics.latencyAvgMs // null),
    maxLatencyMs: (.metrics.latencyMaxMs // null),
    packetLossPct: (.metrics.packetLossPct // null),
    downtimeSec: (.metrics.downtimeSec // 0),
    rxMbps: (.metrics.download.avgMbps // null),
    txMbps: (.metrics.upload.avgMbps // null)
  }]
}'

Render per-site WAN health. Flag: downtimeSec > 0 (outage in window), packetLossPct > 1, avgLatencyMs > 1.5× the site's trailing baseline. If any flagged → suggest predict mode for the full picture and offer to broadcast (Rule 6).

Mobile: wan [site]: [status] · lat [N]ms · loss [N]% · down [N]s.


SD-WAN

bash
sm_call "/v1/sd-wan-configs" | jq -r '.data[]? | "• \(.name)  type=\(.type // "?")  status=\(.deploymentStatus // "?")"'
# Detail + status for one
sm_call "/v1/sd-wan-configs/${CFG_ID}/status" | jq '.'

Render config list with deployment status; flag any not ACTIVE/DEPLOYED.


PROTECT (cameras / NVR)

bash
pro_call "/meta/info" | jq '{nvr:.name, version:.version, mac:.mac}'
pro_call "/cameras" | jq -r '.[]? | "• \(.name)  \(.type // .modelKey)  state=\(.state)  rec=\(.isRecording)  fw=\(.firmwareVersion // "?")"'

Render cameras grouped by state; flag state != "CONNECTED" and any with isRecording == false that are expected to record. Footer offers [snapshot] and [live] (WebSocket watch).

Snapshot
bash
CAM_ID="${CHOSEN_CAM}"
pro_call "/cameras/${CAM_ID}/snapshot?highQuality=true" > "/tmp/unifi-snap-${CAM_ID}.jpg"
echo "saved /tmp/unifi-snap-${CAM_ID}.jpg ($(wc -c < /tmp/unifi-snap-${CAM_ID}.jpg) bytes)"

Report the saved path; the snapshot is binary JPEG — do not inline it.

Camera settings (PATCH) — CONFIRM (Rule 5)

PATCH /cameras/{id} with partial JSON (e.g. toggle recording, mic sensitivity) is state-changing. Show the diff and require AskUserQuestion confirmation before firing.


RESTART / BLOCK — confirmed state-changing actions

All of the following REQUIRE AskUserQuestion confirmation (Rule 5) showing the exact target before executing, and are appended to the audit log.

bash
# Restart a device
net_call "/sites/${SITE}/devices/${DEVICE_ID}/actions" POST '{"action":"RESTART"}'

# Block / unblock a client
net_call "/sites/${SITE}/clients/${CLIENT_ID}/actions" POST '{"action":"BLOCK"}'
net_call "/sites/${SITE}/clients/${CLIENT_ID}/actions" POST '{"action":"UNBLOCK"}'

After firing, re-read the target once to confirm the new state and report it.


VOUCHER (hotspot)

bash
net_call "/sites/${SITE}/vouchers" | jq -r '.data[]? | "• \(.code)  \(.durationMinutes)min  used=\(.usedCount)/\(.quota)  expires=\(.expiresAt // "—")"'
# Create (CONFIRM — creates a credential)
net_call "/sites/${SITE}/vouchers" POST '{"count":1,"durationMinutes":1440,"quota":1,"name":"ops"}'
# Revoke (CONFIRM — destructive)
net_call "/sites/${SITE}/vouchers/${VOUCHER_ID}" DELETE

Create + revoke require AskUserQuestion confirmation.


PREDICT / INSIGHTS (predict, insights, anomaly, health)

Cross-surface anomaly scan that surfaces problems before they become outages. Pull ISP metrics (Site Manager), device stats (Network), and camera state (Protect), then score against simple thresholds and trailing baselines. Read-only — never changes state.

Signals scored:

  1. WAN degradation — downtimeSec > 0 in the trailing window, packetLossPct > 1, or avgLatencyMs > 1.5× the site's 24h baseline → WAN trending unhealthy.
  2. AP/switch flapping — any device with state toggling or uptimeSec reset within the window (recent reboot), or CPU/mem > 85% sustained → device under stress.
  3. Client RF health — share of wireless clients with signal < -72 dBm or high retry rate > 20% → coverage/interference risk in [zone/AP].
  4. Uplink saturation — any uplink at > 90% of negotiated speed sustained → capacity ceiling near.
  5. Protect — any camera state != CONNECTED, NVR storage > 90%, or expected-recording camera not recording → surveillance gap.
bash
SITE=$(net_call "/sites" | jq -r '.data[0].id // .data[0].internalReference // empty')
# Pull the three inputs in parallel (or via the Agent Team)
sm_call "/v1/isp-metrics/1h"            > /tmp/unifi_isp.json &
net_call "/sites/${SITE}/devices"       > /tmp/unifi_dev.json &
net_call "/sites/${SITE}/clients"       > /tmp/unifi_cli.json &
pro_call "/cameras"                     > /tmp/unifi_cam.json &
wait
# Score locally with jq (thresholds above) and rank findings CRITICAL→LOW.

Render:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 OPS ► UNIFI ► PREDICT — [host] — [timestamp]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

WAN          [healthy | degrading | down]
  ⚠ [site] latency 48ms → trending 2.1× baseline, loss 1.4%

DEVICES      [N] under stress
  ⚠ [AP name] CPU 91% sustained 20m — consider load-balance / reboot

CLIENTS      [N]% wireless below -72 dBm near [AP]
UPLINKS      [N] approaching capacity
PROTECT      [N] surveillance gaps

VERDICT      [all clear | watch | act now]

──────────────────────────────────────────────────────
 Actions:
 a) Restart the flagged device
 b) Broadcast WAN/outage risk to /ops:ops-comms
 c) Drill into a finding
 d) Re-run after [N] min
──────────────────────────────────────────────────────

Cross-channel: if VERDICT is act now (active WAN outage, NVR full, or a security camera offline), suggest piping to /ops:ops-comms (Rule 6 — stage draft, never auto-send) and writing the finding to daemon-health.json for /ops:ops-fires.

Mobile:

unifi predict: [verdict].
wan: [site] [status] (lat [N]ms, loss [N]%).
devices: [N] stressed · clients: [N]% weak RF.
protect: [N] gaps.
next: /ops-unifi devices | isp

Show full SKILL.md (570 more words)Show less

SETUP FLOW (setup, configure, init, token)

Delegate to the central setup wizard with the network section:

/ops:setup --section network

If the wizard is unavailable, run inline discovery (background per Rule 4):

bash
# 1. Env vars
printenv UNIFI_SITE_MANAGER_API_KEY UNIFI_LOCAL_GATEWAY_URL UNIFI_LOCAL_API_KEY UNIFI_PROTECT_URL UNIFI_PROTECT_API_KEY 2>/dev/null
# 2. Shell profiles
grep -hE 'UNIFI_' ~/.zshrc ~/.bashrc ~/.envrc ~/.mcp-secrets.env 2>/dev/null | grep -v '^#'
# 3. Doppler
doppler secrets --project unifi --config prd --json 2>/dev/null | jq -r 'to_entries[] | select(.key|test("UNIFI";"i")) | "\(.key)=(present)"'
# 4. Keychain
security find-generic-password -s "unifi-site-manager-key" 2>/dev/null
# 5. Discover the console on the LAN (mDNS / common gateway IPs)
for ip in 192.168.1.1 192.168.0.1 10.0.0.1; do curl -sk --max-time 2 "https://$ip" -o /dev/null -w "$ip → %{http_code}\n" 2>/dev/null; done

Instruct the user where to mint each key (Rule 3 — never silently skip):

  1. Site Manager (cloud): unifi.ui.com → Settings → Control Plane → Integrations → Create API Key. Header X-API-Key.
  2. Network (local): Network app → Settings → Control Plane → Integrations → Create API Key. UniFi OS consoles only.
  3. Protect (local): Protect → Settings → Control Plane → Integrations → Create API Key (or reuse the OS key).

Verify each acquired key before writing it to preferences.json under home_network.*:

bash
# Site Manager
sm_call "/v1/hosts" | jq -e '.data' >/dev/null && echo "site-manager OK"
# Network
net_call "/sites" | jq -e '.data' >/dev/null && echo "network OK"
# Protect
pro_call "/meta/info" | jq -e '.version' >/dev/null && echo "protect OK"

After each surface passes its smoke test, merge verified values into $PREFS_PATH (omit empty fields — keep existing prefs for skipped surfaces):

bash
mkdir -p "$(dirname "$PREFS_PATH")"
jq --arg sm "${UNIFI_SM_KEY:-}" \
   --arg url "${UNIFI_LOCAL_URL:-}" \
   --arg lk "${UNIFI_LOCAL_KEY:-}" \
   --arg pu "${UNIFI_PROTECT_URL:-}" \
   --arg pk "${UNIFI_PROTECT_KEY:-}" \
   '.home_network = ((.home_network // {}) + {
     unifi_site_manager_api_key: (if $sm != "" then $sm else (.home_network.unifi_site_manager_api_key // "") end),
     unifi_local_gateway_url: (if $url != "" then $url else (.home_network.unifi_local_gateway_url // "") end),
     unifi_local_api_key: (if $lk != "" then $lk else (.home_network.unifi_local_api_key // "") end),
     unifi_protect_url: (if $pu != "" then $pu else (.home_network.unifi_protect_url // "") end),
     unifi_protect_api_key: (if $pk != "" then $pk else (.home_network.unifi_protect_api_key // "") end)
   })' \
   "$PREFS_PATH" > "$PREFS_PATH.tmp" && mv "$PREFS_PATH.tmp" "$PREFS_PATH"

Clear action_needed in daemon-health.json when at least one surface is configured.

401/403 → key invalid; re-prompt via AskUserQuestion ([Paste new key], [Skip this surface]).


Agent Teams support

If CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is set, use Agent Teams for parallel surface probing:

TeamCreate("unifi-team")
Agent(team_name="unifi-team", name="fleet-scanner",   prompt="Site Manager: list hosts + sites + fleet device count + ISP metrics, return structured JSON")
Agent(team_name="unifi-team", name="network-scanner", prompt="Network Integration API for the chosen site: devices (online/offline) + clients + per-device latest stats, return structured JSON")
Agent(team_name="unifi-team", name="protect-scanner", prompt="Protect Integration API: cameras + NVR state + recording status + storage, return structured JSON")

If the flag is NOT set, dispatch ops:unifi-agent as standard fire-and-forget subagents per surface (site-manager, network, protect).


Phase 3 — Cross-channel integration

After the main output, evaluate cross-channel triggers (suggestions only — never auto-execute Rule-5/Rule-6 actions):

  1. WAN outage / security-camera offline → comms — stage a /ops:ops-comms draft (WhatsApp/Telegram) to emergency contacts; Rule 6 per-message approval.
  2. Predict verdict = act now → fires — write the finding to daemon-health.json under action_needed; suggest /ops:ops-fires.
  3. Recurring device offline → status — if a device has been offline across consecutive scans, note it for the next /ops:ops-go briefing.
  4. Both Site Manager and local unreachable → status — write action_needed: "unifi_unreachable" to daemon-health and exit with a banner.

Phase 4 — Error handling

FailureBehavior
Site Manager 401Cloud key expired/invalid. Tell user to regenerate at unifi.ui.com.
Site Manager 429Rate-limited. Back off; note "site-manager throttled" and use cached/local data.
Local connection refused / timeoutConsole unreachable on LAN (off-site or wrong IP). Fall back to Site Manager for read-only fleet view; note transport=cloud-only.
Local 401Network/Protect key invalid. Tell user to regenerate in the app.
Protect 404 on integration pathsProtect Integration API not enabled / older firmware. Note "protect integration unavailable".
All surfaces failReport which failed; write action_needed: "unifi_unreachable" to daemon-health; exit with banner.
jq missingPrint raw JSON, suggest installing jq.
No credentials at allExit gracefully with /ops:setup --section network.

Audit every state-changing call (device RESTART, client BLOCK/UNBLOCK, camera PATCH, voucher create/revoke) to ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/ops-unifi-audit.log with timestamp, action, target id, and result.


Optional MCP path

The skill is fully self-sufficient via curl. If you want a richer natural-language tool surface, community UniFi MCP servers exist (no official Ubiquiti MCP as of 2026):

  • ry-ops/unifi-mcp-server — local consoles and cloud Site Manager in one server.
  • sirkirby/unifi-mcp — Network (stable, ~169 tools), Protect, Access.
  • DataKnifeAI/unifi-network-mcp + unifi-protect-mcp — split Network / Protect servers.

To use one, register it via the on-demand MCP registry (~/.claude/mcp-ondemand.json → mcp-toggle.sh on unifi) and restart Claude Code. Treat these as untrusted third-party code — security-review before install. This skill does not require any of them.


Output style

  • Terse-direct. Plain text in mobile mode (Rule 7). Tables only on desktop.
  • Always show the hotkey footer ([s] sites [d] devices [c] clients [i] isp [p] protect [x] predict) on desktop.
  • Use AskUserQuestion (max 4 options, Rule 1) for any state-changing action and for site selection when ambiguous.
  • Never auto-send messages — always stage drafts per Rule 6.
  • Local calls always use -k (self-signed cert) and a short --max-time; degrade to Site Manager read-only when the console is off-LAN.

Additional resources

CLI detail: references/cli.md.

© Lifecycle-Innovations-Limited, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file (references) in claude-ops/skills/ops-unifi of Lifecycle-Innovations-Limited/claude-ops.

  • SKILL.md
  • references/cli.md

Open the folder on GitHubat commit ee9c784

Compare with similar skills

Ops Unifi next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Ops Unifi compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Ops Unifi this skillLifecycle-Innovations-Limited/claude-ops542—~7kAutomated safety check: NotesMIT
Unified Notifications Opsaffaan-m/ECC277k1 repos~1.4kAutomated safety check: PassMIT
Unified Notifications Opsaffaan-m/ECC276k—~829Automated safety check: PassMIT
Unified Notifications Opsaffaan-m/ECC276k—~603Automated safety check: PassMIT
Knowledge Opsaffaan-m/ECC277k2 repos~1.7kAutomated safety check: PassMIT
Research Opsaffaan-m/ECC277k2 repos~902Automated safety check: PassMIT

Similar skills

  • Operate notifications as one ECC-native workflow across GitHub, Linear, desktop alerts, hooks, and connected communication surfaces.

    277k GitHub starsUsed in 1 repo~1.4k tokens
    Data & AnalyticsAuto-check passed
  • GitHub、Linear、デスクトップアラート、フック、接続された通信インターフェースを網羅する、統合されたECCネイティブワークフローとして通知を運用する。真の問題がアラートルーティング、重複排除、エスカレーション、またはインボックス崩壊である場合に使用する。

    276k GitHub stars~829 tokensUpdated yesterday
    Auto-check passed
  • 将通知作为统一的 ECC 原生工作流进行操作,涵盖 GitHub、Linear、桌面提醒、钩子以及连接的通信界面。当真正的问题是告警路由、去重、升级或收件箱崩溃时使用。

    276k GitHub stars~603 tokensUpdated yesterday
    Auto-check passed
  • Knowledge Ops

    affaan-m/ECC

    Knowledge base management, ingestion, sync, and retrieval across multiple storage layers (local files, MCP memory, vector stores, Git repos).

    277k GitHub starsUsed in 2 repos~1.7k tokens
    Knowledge ManagementAuto-check passed
  • Research Ops

    affaan-m/ECC

    Evidence-first current-state research workflow for ECC. An agent skill from affaan-m/ECC.

    277k GitHub starsUsed in 2 repos~902 tokens
    Research & ScienceAuto-check passed
  • Terminal Ops

    affaan-m/ECC

    Evidence-first repo execution workflow for ECC. An agent skill from affaan-m/ECC.

    277k GitHub starsUsed in 2 repos~750 tokens
    Testing & QAAuto-check passed

More from Lifecycle-Innovations-Limited/claude-ops

All 67 skills in this repo
  • Ops Dash

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "ops dashboard", "pixel HQ", or…

    542 GitHub stars~4.7k tokensUpdated yesterday
    Auto-check: notes
  • Ops Gtm

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "go to market", "GTM plan", or…

    542 GitHub stars~3.7k tokensUpdated yesterday
    Auto-check: notes
  • Ops Marketing

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "klaviyo", "ads spend", or…

    542 GitHub stars~3.5k tokensUpdated yesterday
    Auto-check: notes
  • Ops Socials

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "tweet", "post to linkedin", or…

    542 GitHub stars~3.6k tokensUpdated yesterday
    Auto-check: notes
  • Ops Yolo

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "yolo mode", "run the business today"…

    542 GitHub stars~4k tokensUpdated yesterday
    Auto-check: notes
  • Ops Monitor

    Lifecycle-Innovations-Limited/claude-ops

    OPS on-demand: This skill should be used when the user asks to "datadog", "APM alerts", or…

    542 GitHub starsUsed in 1 repo~1.5k tokens
    Auto-check: notes

Questions about Ops Unifi

What does Ops Unifi do?

OPS on-demand: This skill should be used when the user asks to "unifi", "cameras", or "/ops:ops-unifi". Ops Unifi is an agent skill from Lifecycle-Innovations-Limited/claude-ops.

How do I install Ops Unifi in Claude Code?

Run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-unifi -a claude-code`. Or copy the skill folder (claude-ops/skills/ops-unifi in Lifecycle-Innovations-Limited/claude-ops) into .claude/skills/ops-unifi in your project. Claude Code loads it when a task matches its description.

How do I install Ops Unifi in Codex?

Run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-unifi -a codex`. Or copy the skill folder (claude-ops/skills/ops-unifi in Lifecycle-Innovations-Limited/claude-ops) into .agents/skills/ops-unifi in your project. Codex loads it when a task matches its description.

Can I use Ops Unifi in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Lifecycle-Innovations-Limited/claude-ops --skill ops-unifi -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ops-unifi, .gemini/skills/ops-unifi, .github/skills/ops-unifi and .opencode/skills/ops-unifi in your project.

What does Ops Unifi need to run?

Going by SKILL.md and its folder, Ops Unifi needs the command-line tools its instructions call (jq and curl) and credentials named UNIFI_PROTECT_KEY, UNIFI_SM_KEY, UNIFI_LOCAL_KEY and UNIFI_SITE_MANAGER_API_KEY. Our summary lists: A credential in UNIFI_SM_KEY; A credential in UNIFI_LOCAL_KEY. Its frontmatter pre-approves these tools: Bash, Read, Write, Grep, Glob, Agent, TeamCreate, SendMessage, AskUserQuestion, WebFetch, WebSearch.

Does Ops Unifi access the network?

SKILL.md names 1 domain. In commands or code: api.ui.com; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.

Is Ops Unifi safe to install?

Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Ops Unifi use?

Ops Unifi is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Ops Unifi use?

About 7k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 1.6k tokens, read only when the agent opens those files.

What are the alternatives to Ops Unifi?

Skills that share tags, products or a category with Ops Unifi: Unified Notifications Ops (affaan-m/ECC, 277k stars), Unified Notifications Ops (affaan-m/ECC, 276k stars), Unified Notifications Ops (affaan-m/ECC, 276k stars) and Knowledge Ops (affaan-m/ECC, 277k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Ops Unifi?

Lifecycle-Innovations-Limited (a GitHub organization) maintains it in Lifecycle-Innovations-Limited/claude-ops, which has 542 GitHub stars. The repository holds 67 skills in this directory. The repository was last updated on October 10, 2026.

Source: Lifecycle-Innovations-Limited/claude-ops on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.