Every VAPIX call you'd reach for, plus a local SQLite history, fleet sweep, and an MCP server no other Axis wrapper has.
A single Go binary for fleet operations against Axis IP cameras. It absorbs every operation in the open VAPIX wrapper landscape (param.cgi, PTZ, applications, analytics, events, MQTT bridge), keeps a per-camera SQLite history of parameters and presets, and exposes an MCP server so an LLM agent can sweep a subnet, drive a PTZ camera to a preset, or diff parameter trees from a conversation. Built around the quirks that bite real Axis fleets: the Q6325-LE basicdeviceinfo digest loop, the AXIS OS 12 ONVIF/VAPIX user-database split, and the AOA + analytics-MQTT surfaces that landed in OS 12.2.
git clone https://github.com/oneshot2001/vapix-pp-cli ~/Projects/vapix-pp-cli
cd ~/Projects/vapix-pp-cli
go build -o ~/go/bin/vapix-pp-cli ./cmd/vapix-pp-cliOr, once tagged:
go install github.com/oneshot2001/vapix-pp-cli/cmd/vapix-pp-cli@latestThe MCP server lives at ./cmd/vapix-pp-mcp:
go build -o ~/go/bin/vapix-pp-mcp ./cmd/vapix-pp-mcpWire vapix-pp-mcp into your agent's MCP config like any stdio server.
This CLI was developed and verified against three personally-owned Axis cameras on a private LAN — not customer or production deployments:
- AXIS Q6358-LE (192.168.1.33, AXIS OS 12.9) — PTZ thermal, full surface
- AXIS Q6325-LE (192.168.1.32, AXIS OS 12.9) — PTZ visible
- AXIS P3285-LVE (192.168.1.19, AXIS OS 12.7, HTTPS-only) — fixed dome
The Q6325-LE quirk (basicdeviceinfo digest loop) and the P3285's HTTPS-only
listener both shipped the live test surface and informed the routing in
device info and discover.
Auth is per-camera HTTP Digest (Basic fallback). Pass credentials via --user/--password flags, the VAPIX_USER/VAPIX_PASSWORD env vars, or a ~/.config/vapix-pp-cli/config.toml registry that maps camera aliases to credentials. The CLI never persists secrets in its SQLite store.
# fingerprint every Axis camera in the subnet — model, firmware, MAC, OS major
vapix-pp-cli discover 192.168.1.0/24 --json
# fingerprint a single camera (uses param.cgi route — Q6325-LE-safe)
vapix-pp-cli device info --host 192.168.1.32
# drive a Q6358-LE to a named preset via PTZ goto
vapix-pp-cli ptz gotoserverpresetname --host 192.168.1.33 --preset Gate
# list every ACAP app installed on the camera with status + license
vapix-pp-cli applications list --host 192.168.1.33 --json
# discover all event topics on a P3285-LVE — feeds straight into events watch
vapix-pp-cli events list-topics --host 192.168.1.19 --json
These capabilities aren't available in any other tool for this API.
-
discover— Sweep a CIDR range and fingerprint every Axis camera it finds in one parallel shot.When an installer drops you on a network with 'somewhere between 4 and 40 Axis cameras', this turns 'go figure out the inventory' into one command.
vapix-pp-cli discover 192.168.1.0/24 --json
-
sweep param— Run the same param.cgi query against every camera in the local store and return one table.'What hostname is each camera reporting?' takes one command instead of an ad-hoc loop you re-write every audit.
vapix-pp-cli sweep param --group root.Network.HostName --json
-
param diff— Diff the current param.cgi tree of a camera against the previous snapshot stored in the local SQLite cache.Answers 'did anything change on this camera in the last week?' without trusting whoever last touched the on-camera config.
vapix-pp-cli param diff --host 192.168.1.33 --since 7d --json
-
preset copy— Read presets from one camera and write them to another using their stored coordinates.Replacing or duplicating a PTZ rig stops being a 30-minute click-through and becomes one line.
vapix-pp-cli preset copy --from Q6358 --to Q6325
-
applications drift— Diff the installed ACAP application set per camera against last sync; flag installs, uninstalls, version bumps.Catches 'who installed an unsigned ACAP on the front-door camera' without manually walking each device.
vapix-pp-cli applications drift --json
-
ptz tour— Walk a sequence of named presets with a configurable dwell at each.Manual rounds for an integrator becomes scriptable; useful for demos and for late-night perimeter sweeps.
vapix-pp-cli ptz tour --host 192.168.1.33 --presets Gate,Lobby,Lot --dwell 8
-
events watch— Tail the MQTT bridge for a topic and shell out to a snapshot command when it fires.Captures evidence frames the second a camera detects motion — without standing up a separate event broker.
vapix-pp-cli events watch --host 192.168.1.33 --topic tns1:VideoSource/MotionAlarm --on-fire 'snapshot.sh {topic} {ts}' -
doctor— Composite health check — param reachability, PTZ whoami, ACAP app list, system clock skew, current firmware.Pre-flight before a demo or an installation handoff in one command.
vapix-pp-cli doctor --host 192.168.1.33 --json
-
device info— Probes param.cgi first (works on Q6325-LE where basicdeviceinfo.cgi loops on digest 401) then falls back to richer endpoints for newer OS.Avoids the silent 401-loop failure mode that has bitten every team that wrote 'a quick Python script' against a Q6325-LE.
vapix-pp-cli device info --host 192.168.1.32
Run vapix-pp-cli --help for the full command reference and flag list.
AXIS Object Analytics (AOA) and analytics-metadata configuration
vapix-pp-cli aoa aoa-config- Get AXIS Object Analytics configuration (scenarios, triggers, classes)vapix-pp-cli aoa aoa-supported- List supported scenario types and capabilitiesvapix-pp-cli aoa metadata-producers- List RTSP analytics metadata producers and their per-channel statevapix-pp-cli aoa metadata-sample- Request a one-shot sample of metadata from a named producervapix-pp-cli aoa mqtt-data-sources- AXIS OS 12.2+ — list available analytics-MQTT data sources
AXIS Camera Application Platform (ACAP) — manage installed apps via /axis-cgi/applications/*
vapix-pp-cli applications list- List installed ACAP applications: name, version, status, licensevapix-pp-cli applications remove- Uninstall an ACAP application. Destructive — use --dry-run first.vapix-pp-cli applications restart- Restart an ACAP applicationvapix-pp-cli applications start- Start an ACAP application by package namevapix-pp-cli applications stop- Stop a running ACAP application
Device identity, capabilities, and lifecycle
vapix-pp-cli device info- Fingerprint device — model, firmware, serial, MAC, AXIS OS via param.cgi (works on Q6325-LE where basicdeviceinfo.cgi loops on digest 401)vapix-pp-cli device properties- List root.Properties tree — capability flags, AXIS OS major/minor, supported featuresvapix-pp-cli device restart- Reboot the device. Use --dry-run first.vapix-pp-cli device systemtime- Get device system time
Event subscription and topic discovery
vapix-pp-cli events action-configurations- List action configurations (SOAP GetActionConfigurations)vapix-pp-cli events action-rules- List configured action rules (SOAP GetActionRules)vapix-pp-cli events action-templates- List supported action types (SOAP GetActionTemplates)vapix-pp-cli events change-virtual-input- Trigger a virtual input event (SOAP ChangeVirtualInputState) — useful for testing rulesvapix-pp-cli events list-topics- List all event topics on this device (SOAP GetEventInstances). Returns ONVIF-shaped topic tree.vapix-pp-cli events recipient-templates- List supported recipient templatesvapix-pp-cli events recipients- List configured recipients
Snapshots and live image capture
vapix-pp-cli media snapshot- Capture a JPEG snapshot. Use --output to write to a file; default is base64.vapix-pp-cli media streamprofiles- List configured stream profiles
MQTT client + Event Bridge configuration via /axis-cgi/mqtt/*
vapix-pp-cli mqtt activate-client- Activate (start) the MQTT clientvapix-pp-cli mqtt client-config- Get MQTT client configuration (broker, credentials, TLS, last will)vapix-pp-cli mqtt client-status- Get MQTT client status (running, broker URL, last error)vapix-pp-cli mqtt deactivate-client- Deactivate (stop) the MQTT clientvapix-pp-cli mqtt event-bridge-publish- Get current event publication map (which event topics → MQTT topics)vapix-pp-cli mqtt event-bridge-subscribe- Get current MQTT subscription map (incoming MQTT → device events)
Universal parameter tree (param.cgi). The most reliable VAPIX surface — works across every Axis device.
vapix-pp-cli param add- Add a new dynamic parameter (motion windows, stream profiles, etc.)vapix-pp-cli param list- List all parameters or a specific group. Returns key=value pairs.vapix-pp-cli param listdefinitions- List parameter definitions (type, range, default) — useful for discoveryvapix-pp-cli param remove- Remove a dynamic parametervapix-pp-cli param update- Update an existing parameter. Use param.update KEY VALUE.
PTZ preset save / rename / delete via /axis-cgi/com/ptzconfig.cgi
vapix-pp-cli preset list- List all server presets on this cameravapix-pp-cli preset remove- Remove a named presetvapix-pp-cli preset removeall- Remove every server preset on this camera. Destructive — use --dry-run first.vapix-pp-cli preset rename- Rename a preset by numbervapix-pp-cli preset save- Save current PTZ position as a named preset
Pan / tilt / zoom control via /axis-cgi/com/ptz.cgi
vapix-pp-cli ptz areazoom- Area zoom — center on pixel coords + zoom factorvapix-pp-cli ptz autofocus- Enable or disable autofocusvapix-pp-cli ptz autoiris- Enable or disable autoirisvapix-pp-cli ptz auxiliary- Trigger an auxiliary function (e.g. wiper, washer, defogger). Device-specific.vapix-pp-cli ptz center- Center on pixel coordinates within the live imagevapix-pp-cli ptz continuouspantiltmove- Continuous pan/tilt move at given speed (-100..100, comma-separated). Set 0,0 to stop.vapix-pp-cli ptz continuouszoommove- Continuous zoom at given speed (-100..100). 0 to stop.vapix-pp-cli ptz gotoserverpresetname- Move to a server-side preset by namevapix-pp-cli ptz gotoserverpresetno- Move to a server-side preset by numbervapix-pp-cli ptz info- List supported PTZ commands on this devicevapix-pp-cli ptz ircutfilter- Control IR cut filter (auto | on | off)vapix-pp-cli ptz move- Move in a named direction (up/down/left/right/upleft/upright/downleft/downright/home/stop)vapix-pp-cli ptz pan- Absolute pan position (-180..180 degrees)vapix-pp-cli ptz query- Query PTZ status: position, presets, limitsvapix-pp-cli ptz tilt- Absolute tilt positionvapix-pp-cli ptz whoami- Identify PTZ driver + capabilities. First call to confirm a camera is PTZ-capable.vapix-pp-cli ptz zoom- Absolute zoom position (1..9999, device-dependent)
# Human-readable table (default in terminal, JSON when piped)
vapix-pp-cli applications list
# JSON for scripting and agents
vapix-pp-cli applications list --json
# Filter to specific fields
vapix-pp-cli applications list --json --select id,name,status
# Dry run — show the request without sending
vapix-pp-cli applications list --dry-run
# Agent mode — JSON + compact + no prompts in one flag
vapix-pp-cli applications list --agentThis CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--jsonoutput to stdout, errors to stderr - Filterable -
--select id,namereturns only fields you need - Previewable -
--dry-runshows the request without sending - Explicit retries - add
--idempotentto create retries when a no-op success is acceptable - Confirmable -
--yesfor explicit confirmation of destructive actions - Piped input - write commands can accept structured input when their help lists
--stdin - Offline-friendly - sync/search commands can use the local SQLite store when available
- Agent-safe by default - no colors or formatting unless
--human-friendlyis set
Exit codes: 0 success, 2 usage error, 3 not found, 5 API error, 7 rate limited, 10 config error.
Install the focused skill — it auto-installs the CLI on first invocation:
npx skills add mvanhorn/printing-press-library/cli-skills/pp-vapix -gThen invoke /pp-vapix <query> in Claude Code. The skill is the most efficient path — Claude Code drives the CLI directly without an MCP server in the middle.
Use as an MCP server in Claude Code (advanced)
If you'd rather register this CLI as an MCP server in Claude Code, install the MCP binary first:
Install the MCP binary from this CLI's published public-library entry or pre-built release.
Then register it:
claude mcp add vapix vapix-pp-mcpThis CLI ships an MCPB bundle — Claude Desktop's standard format for one-click MCP extension installs (no JSON config required).
To install:
- Download the
.mcpbfor your platform from the latest release. - Double-click the
.mcpbfile. Claude Desktop opens and walks you through the install.
Requires Claude Desktop 1.0.0 or later. Pre-built bundles ship for macOS Apple Silicon (darwin-arm64) and Windows (amd64, arm64); for other platforms, use the manual config below.
Manual JSON config (advanced)
If you can't use the MCPB bundle (older Claude Desktop, unsupported platform), install the MCP binary and configure it manually.
Install the MCP binary from this CLI's published public-library entry or pre-built release.
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"vapix": {
"command": "vapix-pp-mcp"
}
}
}vapix-pp-cli doctorVerifies configuration and connectivity to the API.
Config file: ~/.config/vapix-pp-cli/config.toml
Static request headers can be configured under headers; per-command header overrides take precedence.
Not found errors (exit code 3)
- Check the resource ID is correct
- Run the
listcommand to see available items
- Q6325-LE returns 401 in a loop on basicdeviceinfo.cgi — use
vapix-pp-cli device info— it routes through param.cgi by default for exactly this reason - ONVIF user works for VAPIX but not for events on AXIS OS 12.x — AXIS OS 12.x uses separate user databases for VAPIX and ONVIF; set up a VAPIX-only user for events
- auxiliary command (
speeddry,wiper:on) returns 'unsupported' — auxiliaries are device-specific; runvapix-pp-cli ptz infofirst to enumerate what this camera supports - snapshot returns base64 blob and floods the terminal — pass
--output frame.jpgto write binary to disk — base64 is the default for agent piping
Realistic recipes that use the focused VAPIX subset (param.cgi + PTZ + applications + analytics + events).
vapix-pp-cli --user root --password pass discover 192.168.1.0/24 --json --select host,model,firmware,axis_os_majorThe CIDR sweep tries HTTP first; HTTPS-only cameras (P3285-LVE) fall through to a TLS-skip-verify probe automatically. Non-Axis 200s (routers, NAS web UIs) are filtered out. Hits are upserted into ~/.local/share/vapix-pp-cli/data.db.
# move
vapix-pp-cli --host 192.168.1.33 --user root --password pass \
ptz gotoserverpresetname --preset Gate
# snap (give the lens 2s to settle)
sleep 2
vapix-pp-cli --host 192.168.1.33 --user root --password pass \
media snapshot --resolution 1920x1080 --output gate.jpgvapix-pp-cli --host 192.168.1.33 --user root --password pass \
ptz tour --presets Gate,Lobby,Lot --dwell 8 --repeat 3 --speed 90Wire it as a cron job. The tour walks each preset, sleeps, walks the next.
The CLI stages an MQTT bridge handoff in v1 (it prints the mosquitto_sub invocation that hooks the camera's MQTT bridge) — point it at any MQTT client:
vapix-pp-cli --host https://192.168.1.19 --insecure --user root --password pass \
events watch --topic 'tns1:VideoSource/MotionAlarm' --on-fire 'snapshot.sh' --duration 60Configure the camera's MQTT bridge first via vapix-pp-cli mqtt event-bridge-publish.
# 7 days ago you ran:
# vapix-pp-cli --host 192.168.1.33 --user root --password pass param diff --since 0s
# (any param diff invocation also persists a snapshot; the first run reports "no baseline")
# today:
vapix-pp-cli --host 192.168.1.33 --user root --password pass \
param diff --group root.PTZ --since 7d --jsonReturns added/removed/changed keys. Aimed at "did anything drift since the integrator left the site?" audits.
vapix-pp-cli --user root --password pass sweep param --group root.Network.HostNameHits every camera saved by discover. One table out, no per-camera scripting.
# Run weekly as a cron:
for ip in 192.168.1.32 192.168.1.33 192.168.1.19; do
vapix-pp-cli --host $ip --user root --password pass applications drift --since 7d --json
doneEach call snapshots the running ACAP set and diffs against the prior week. Catches "who installed an unsigned ACAP on the front-door camera."
vapix-pp-cli --host 192.168.1.33 --user root --password pass doctor --jsonReports auth status, brand, firmware probe, and cache state in one shot.
This CLI was built by studying these projects and resources:
- edgexfoundry/device-camera-go — Go (100 stars)
- Cacsjep/goxis — Go (70 stars)
- gluxon/node-vapix — JavaScript (40 stars)
- trunnion/vapix — Rust (30 stars)
- derens99/vapix-python — Python (20 stars)
Generated by CLI Printing Press
A linted OpenAPI 3.1 + llms.txt generated from spec.yaml and corrected against live devices: https://github.com/oneshot2001/vapix-openapi