Official local Integration API · no reverse-engineered endpoints

Hand your agent
the network console,
not the root password.

ufi drives Ubiquiti UniFi Network from an AI agent — devices, clients, WiFi, firewall, DNS as bounded JSON. Reads are safe by default; every mutation is gated, and high-stakes config is reviewed by hash before it ever runs.

brew install rnwolfe/tap/ufi
go install github.com/rnwolfe/ufi/cmd/ufi@latest
curl -fsSL https://uficli.sh/install.sh | sh
linux · macOS · windows — amd64/arm64Releases →
// the operator's safety model

Two ways to change the network. Both make the agent ask first.

single-target actions restart · port-cycle · authorize
$ ufi device restart ap-living-room
{ "code": "MUTATION_BLOCKED" } exit 12
default-deny. the agent gets a code, not a reboot.
$ ufi device restart ap-living-room --allow-mutations
{ "ok": true, "action": "RESTART" } exit 0
one explicit, auditable opt-in.
declarative config network · firewall · dns · acl
$ ufi firewall policy create --data @rule.json --dry-run
plan · hash a1b2c3d4e5f6
computes the change, persists the plan. nothing applied.
$ ufi apply a1b2c3d4e5f6 --allow-mutations
{ "ok": true } exit 0
runs exactly the reviewed plan — no TOCTOU gap.
// a guest controls their own device name

The network is full of attacker-controlled text. ufi quarantines it.

Device names, client hostnames, SSIDs, voucher notes — anyone on the WiFi can set them. In agent mode ufi fences every one so a hostile string can't become an instruction your agent follows.

// every port is safe by design

Built to the Agent CLI Guidelines — Full.

Read-only by default

Listing devices, clients, WiFi, firewall, and DNS is always safe. A state change needs an explicit --allow-mutations; a blocked one returns MUTATION_BLOCKED (exit 12).

Reviewed config writes

network / firewall / dns / acl writes never run blind. --dry-run emits a plan + content hash; ufi apply <hash> runs exactly that plan — no time-of-check/time-of-use gap.

Bounded, structured JSON

Lists return { schema_version, items, count, next_cursor }. --limit / --select / --cursor keep responses inside an agent's context budget.

Prompt-injection fenced

A guest can name their device “Ignore previous instructions…”. ufi wraps network-controlled names and notes in [UNTRUSTED_DATA_BEGIN]…[END] by default.

Structured errors + exit codes

Every failure is { error, code, remediation } on stderr with a stable, documented exit code — never a raw stack trace or an opaque HTTP 400.

Official API only

Ubiquiti's versioned local Integration API — no reverse-engineered endpoints. Validated live against UniFi Network 10.4.57. One static binary.

Verify it from the binary, not this page: ufi schema | jq .conformance · ufi agent prints the full contract.

Give your agent the console floor.