{
  "markdown": "<div align=\"center\">\n\n<img src=\"docs/banner.svg\" alt=\"Reolink CLI\" width=\"320\">\n\n**A local-first command-line tool for operating Reolink cameras — JSON by default, with a built-in MCP server and a cross-agent skill so AI agents drive the same core.**\n\n![release](https://img.shields.io/github/v/release/reolink/reolink-cli)\n![platform](https://img.shields.io/badge/platform-macOS%20·%20Linux%20·%20Windows-lightgrey)\n![build](https://img.shields.io/badge/build-external%20·%20LAN--only-green)\n\n</div>\n\n---\n\nOperate Reolink IP cameras from the command line over your **local network** —\nJSON out by default, so everything pipes into `jq` or a script. The bundled MCP\nserver and agent skill drive the same runtime, so an AI agent can do it in plain\nlanguage.\n\n```console\n$ reolink-cli --camera front-door info | jq '{model, firmware, name}'\n{\n  \"model\": \"Reolink Video Doorbell\",\n  \"firmware\": \"v3.0.0.6696_26062799\",\n  \"name\": \"Front Door\"\n}\n```\n\n## Highlights\n\n- 🔍 **Discovery** — LAN broadcast, plus bulk `device import`\n- 🎥 **Live media** — `preview play`, file/stdout capture, batch capture, JPEG snapshot\n- 🕹️ **PTZ** — pan/tilt/zoom, presets, patrol, guard, autotrack, real timed jog\n- 💡 **Lights** — IR, spotlight (with native **blink**), white-LED, status LED\n- 🎚️ **Video encoder** — read/change resolution, frame rate, bit rate, H.264/H.265, GOP per stream\n- 📢 **Siren** — sound / silence the built-in siren on demand\n- 🧠 **Detection** — motion + AI (person / vehicle / dog_cat / package)\n- 📼 **Recording & storage** — schedule, SD/HDD status, VOD search & download\n- 🔔 **Events** — query/stream + a declarative rule engine (`events monitor`)\n- 🗣️ **Two-way audio** — talkback / TTS straight to the camera speaker\n- 🌐 **Stream URLs** — RTSP / RTMP / FLV for Frigate, Home Assistant, go2rtc, VLC\n- 🤖 **AI-native** — built-in MCP stdio server + cross-agent operator skill\n- 🧩 **Fleet-aware** — camera & tag selectors, local session daemon for a fast control plane\n\n## Commands\n\nThe full, always-current list comes from the binary itself — run `reolink-cli\n--help` for every command, `reolink-cli <command> --help` for its options, or\n`reolink-cli features` for a machine-readable manifest (what agents read). The\ntable below is a snapshot for browsing.\n\nAlmost every control command needs the local gateway running\n(`reolink-cli gateway start &`); read-only lookups like `discover` / `ping` do\nnot. All operations are LAN-only in these public builds.\n\n| Area | Commands | What you can do |\n|---|---|---|\n| **Setup & registry** | `init`, `device`, `config`, `doctor`, `setup` | Scaffold config, register/import cameras, tag them, health-check the install |\n| **Connect & inspect** | `ping`, `login`, `info`, `capabilities`, `status`, `benchmark` | Reach a camera, read model/firmware/serial, list what the model supports, measure round-trip latency |\n| **Discovery** | `discover` | Find cameras on the LAN (broadcast) |\n| **Live media** | `preview`, `snapshot`, `stream` | Play or capture live video, grab a JPEG, print RTSP/RTMP/FLV URLs for Frigate / Home Assistant / go2rtc / VLC |\n| **Image & encoder** | `image`, `encode`, `osd` | Flip/mirror, read/change resolution · frame rate · bit rate · H.264/H.265 · GOP per stream, on-screen name/time overlay |\n| **Lights** | `light` | IR / night vision, spotlight (with **blink**), white-LED, status LED |\n| **Audio** | `audio` | Volume, alarm mute, **siren** (sound/stop), quick replies, two-way talkback / TTS |\n| **PTZ** | `ptz` | Pan / tilt / zoom, focus, presets, patrol, guard, autotrack, timed jog |\n| **Detection & events** | `detect`, `notify`, `events` | Motion + AI (person / vehicle / dog_cat / package), push settings, query/stream events + a declarative rule engine (`events monitor`) |\n| **Recording & storage** | `record`, `vod`, `storage`, `log` | Recording schedule, VOD search & download, SD/HDD status, device logs |\n| **Privacy & users** | `privacy`, `users` | Privacy-mask regions, manage device accounts |\n| **Network** | `wifi` | Push a new SSID + PSK (pre-validated), auto-rediscover, update the registry |\n| **System** | `system` | Reboot |\n| **Gateway & tooling** | `gateway`, `mcp-server`, `plugin`, `cache`, `self-update`, `raw` | Run the control-plane gateway, expose MCP tools to AI agents, maintain the skill cache, send a raw Baichuan request |\n\n> **Support varies by model.** A command existing here does not guarantee your\n> camera implements it — an unsupported operation returns a clear \"device does\n> not support\" error rather than failing silently. Check a specific model with\n> `reolink-cli --camera <name> capabilities` or\n> `reolink-cli --camera <name> device inventory --capabilities`. `v30`-protocol\n> cameras are still provisional; `v20` is the stable surface.\n\n## Install\n\n### AI agents\n\n**Claude Code — no Node required.** Install the plugin from inside Claude Code:\n\n```text\n/plugin marketplace add reolink/reolink-cli\n/plugin install reolink-cli@reolink-cli\n```\n\nThe binary for your platform is fetched automatically the first time you ask\nabout a camera. Then just talk to your agent: *“show me the front door camera”*,\n*“point the back-yard camera left”*, *“blink the porch spotlight 3 times”*.\n\n**Other agents (Codex / Cursor / Gemini / Copilot / OpenCode / 70+) — requires\n[Node.js](https://nodejs.org).** The cross-agent `skills` installer places the\nskill into each agent’s own directory:\n\n```bash\nnpx skills@latest add reolink/reolink-cli\n```\n\nPick `reolink-cli` and the agents to install it into; the binary is fetched on\nfirst use, exactly as above.\n\n### Command line only — no Node required\n\nOne line — detects your platform, installs `reolink-cli` + `reolink-gateway` to\n`~/.local/bin`, and initializes config:\n\n```bash\n# macOS / Linux\ncurl -fsSL https://raw.githubusercontent.com/reolink/reolink-cli/main/install.sh | sh\n```\n\n```powershell\n# Windows — works from PowerShell or the Command Prompt\npowershell -NoProfile -Command \"iwr https://raw.githubusercontent.com/reolink/reolink-cli/main/install.ps1 -UseBasicParsing | iex\"\n```\n\nTwo details in that line, both learned the hard way:\n\n- `iwr` and `iex` are PowerShell aliases, so the bare `iwr … | iex` only works\n  if you are already in PowerShell. Pasted into the Command Prompt it fails with\n  `'iwr' is not recognized`, which names the alias rather than the cause. The\n  `powershell -NoProfile -Command \"…\"` wrapper works from either shell.\n- `-UseBasicParsing` matters on Windows PowerShell 5.1, where\n  `Invoke-WebRequest` otherwise hands the response to the Internet Explorer\n  engine for DOM parsing. On a machine where IE's first-launch configuration\n  never ran, that stalls or fails with `Access is denied` before anything is\n  downloaded. On PowerShell 7 it is already the default and the flag is a no-op.\n\nAlready installed? On macOS/Linux, upgrade in place with\n`reolink-cli self-update --yes`. On Windows, re-run the installer\n(`install.ps1`) — see [Platform support](#platform-support) for why.\n\n<details>\n<summary>Prefer a downloadable archive?</summary>\n\nGrab the archive for your platform from the\n[latest Release](https://github.com/reolink/reolink-cli/releases/latest),\nextract, and run the bundled installer:\n\n```bash\ntar -xzf reolink-cli-*.tar.gz && cd reolink-cli-*/ && ./install.sh\n# Windows: extract the .zip and run .\\install.ps1\n```\n\nThe archive is self-contained: binaries + the skill/plugin + installer +\n`THIRD-PARTY-LICENSES.txt`.\n\nTo verify it, use `checksums/<tag>.sha256` on this repository's default branch,\n**not** the `SHA256SUMS` attached to the release — see\n[Verifying a download](#verifying-a-download) for why the difference matters.\n\n</details>\n\n<details>\n<summary>Uninstall</summary>\n\n```bash\nreolink-cli setup --uninstall --purge && npx skills remove reolink-cli\n```\n\nClaude Code users: also run `/plugin uninstall reolink-cli` to clean the marketplace entry.\n\n</details>\n\n## Quick start\n\n```bash\n# Write the config and registry templates. Both land in your OS config\n# directory and are created owner-only (0600).\nreolink-cli config init\n\n# Start the local gateway — most control commands route through it\nreolink-cli gateway start --addr 127.0.0.1:9000 &\nexport REOLINK_GATEWAY_ADDR=127.0.0.1:9000\n\n# Register your first camera. Pick a name of your own: `config init` writes\n# placeholder entries (front-door, garage, lab-v30) to show the file format,\n# and `device add` refuses to overwrite an existing one.\nreolink-cli device add porch --host 192.168.1.41 --user admin --tags outdoor,entry --password-stdin\n\nreolink-cli --camera porch login\nreolink-cli --camera porch info\nreolink-cli --camera porch snapshot --file ./porch.jpg\n```\n\nThe placeholder entries are examples, not cameras. Remove them once you have\nregistered your own: `reolink-cli device remove front-door`.\n\nBulk-import discovered devices (credentials via `REOLINK_PASSWORD`, never\nplaintext `--password` on the command line):\n\n```bash\nexport REOLINK_PASSWORD='<device-password>'\nreolink-cli --user admin device import\nunset REOLINK_PASSWORD\n```\n\n## Multi-device workflow\n\nTarget selection stays explicit — there is no hidden “current device” state.\n\n| Selector | Meaning |\n|---|---|\n| `--camera <name>` | one registered device |\n| `--cameras <a,b,c>` | several registered devices |\n| `--tag <tag>` | every device carrying a tag |\n| `--all-devices` | the whole registry |\n| `--host <ip[:port]>` | an ad-hoc device by address |\n\n```bash\nreolink-cli device list\nreolink-cli --tag outdoor device inventory --capabilities\nreolink-cli --tag outdoor snapshot           # fan out across a tag group\n```\n\n## AI agents & MCP\n\n`reolink-cli` is built to be driven by AI agents. There are two ways in — a\nnatural-language **skill** and a structured **MCP server** — both reusing the\nexact same core runtime as the CLI.\n\n### 1. Operator skill — talk to your cameras\n\n`npx skills@latest add reolink/reolink-cli` installs the `reolink-cli` skill\ninto whichever agents you use. The skill teaches the agent the full command\nsurface and the safety rules, so you just say what you want:\n\n> *“is the front door camera online?”*\n> *“point the driveway cam to preset 2, then take a snapshot”*\n> *“let me know if anyone shows up at the door tonight”*\n\nThe agent maps intent to the right `reolink-cli` invocation, chains multi-step\nflows, and **never guesses device state** — it only reports what a command\nactually returned.\n\n### 2. MCP server — structured tools\n\nFor agents that prefer typed tool calls, or tight automation loops:\n\n```bash\nreolink-cli mcp-server\n```\n\nJSON-RPC 2.0 over stdio, reusing the same core runtime. Wire it into Claude Code:\n\n```json\n\"mcpServers\": {\n  \"reolink-cli\": {\n    \"command\": \"reolink-cli\",\n    \"args\": [\"mcp-server\"],\n    \"env\": { \"REOLINK_GATEWAY_ADDR\": \"127.0.0.1:9000\" }\n  }\n}\n```\n\nThe gateway must be running separately — the MCP server routes through it,\nexactly as the CLI does.\n\n## Platform support\n\nPrebuilt binaries are published on each [Release](https://github.com/reolink/reolink-cli/releases):\n\n- macOS arm64 (Apple Silicon)\n- Linux x86_64 and arm64 (glibc)\n- Linux x86_64 and arm64 (musl, statically linked) — Alpine, Home Assistant OS,\n  and slim Docker images, where the glibc archives cannot load at all\n- Linux armv7 and armv6 — a Raspberry Pi on a **32-bit** OS. armv7 covers the\n  Pi 2/3/4; armv6 covers the Pi 1 and Zero, whose CPUs cannot execute armv7 code\n  at all. Built against glibc 2.28, so Raspberry Pi OS Buster and later work.\n- Windows x86_64\n\n`uname -m` alone does not decide this on a Pi. 32-bit Raspberry Pi OS has booted\na 64-bit kernel by default since Bullseye, so `uname -m` says `aarch64` while the\nuserland is 32-bit and has no arm64 loader — the arm64 archive cannot start\nthere. What settles it is the userland:\n\n```bash\ngetconf LONG_BIT    # 64 → arm64 archive;  32 → armv7 (or armv6 on a Pi 1/Zero)\n```\n\n`install.sh` reads that rather than the kernel, alongside the C library and the\nARM revision, and picks the archive accordingly. Each is a separate asset\n(`…-linux-arm64.tar.gz` vs `…-linux-arm64-musl.tar.gz` vs\n`…-linux-armv7.tar.gz`) so an existing install keeps resolving the archive it\nwas installed from — including `self-update`, which replaces a build with its\nown kind rather than guessing from the CPU it happens to be running on.\n\n**Which one did I get?** `--version` does not say, so read it off the binary:\n\n```bash\nfile \"$(command -v reolink-cli)\"   # \"statically linked\" = musl build\n```\n\nThis matters if you move the binary between machines. A glibc build on a musl\nhost does not fail gracefully — it cannot load at all, and the error names a\nmissing symbol rather than the real problem:\n\n```\nError relocating ./reolink-cli: __res_init: symbol not found\n```\n\nThe static musl build runs on both, so when in doubt use that one.\n\n### Home Assistant OS\n\nThe `homeassistant` core container is aarch64 Alpine, so `shell_command` needs\nthe musl build. Install it inside that container, not on the host:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/reolink/reolink-cli/main/install.sh | sh\n```\n\nThe gateway must be reachable from wherever the command runs — start it in the\nsame container, or point `REOLINK_GATEWAY_ADDR` at one on the LAN.\n\n`self-update` covers macOS and Linux. On Windows it exits with the download\nlink instead: the archive is a `.zip`, and a running `.exe` cannot be replaced\nin place — upgrade by extracting the new archive and running `install.ps1`.\n\n`preview play` expects `ffplay` on `PATH` (or pass `--player`, or set\n`REOLINK_PLAYER`).\n\n> Best supported on current Reolink IP cameras and NVRs over the LAN. Support\n> for some newer models may be partial — check a specific command with\n> `reolink-cli --camera <name> device inventory --capabilities`.\n\n## Responsible use\n\nThis tool controls cameras and reads their recordings. Use it only on devices\nyou own or are authorised to administer.\n\n- **Authorised devices only.** Discovery broadcasts on your LAN and login\n  attempts against cameras you do not control are unauthorised access in most\n  jurisdictions, regardless of intent.\n- **Not a scanner.** `discover` is a UDP broadcast for locating your own\n  cameras. Do not use it, or `ping`, to sweep networks you were not asked to\n  work on.\n- **The footage is someone's home.** Snapshots, recordings and the event\n  history this tool writes to disk are personal data. Protect them the way you\n  would protect the camera's own storage, and delete what you no longer need.\n\n## Security\n\n- **The gateway binds `127.0.0.1` by default** and refuses browser\n  cross-origin requests. Passing `--addr 0.0.0.0:9000` exposes camera control\n  to everyone on your LAN — do it deliberately, never by default.\n- **This is a LAN-only build.** It reaches cameras over the local network\n  (`--host <ip>`); remote access via Reolink's P2P relay is not included.\n  Confirm with `reolink-cli --version` → `(external · LAN-only)`.\n- **Report vulnerabilities privately** — see [SECURITY.md](SECURITY.md).\n\n### Safe credential handling\n\n- **Never pass `--password` on the command line.** It is visible to every other\n  user via `ps` and lands in your shell history. Use `--password-stdin`, the\n  `REOLINK_PASSWORD` environment variable, or register the camera once with\n  `device add` and refer to it by name.\n- **Stored passwords are encrypted at rest.** Camera passwords in\n  `aliases.toml` are AES-256-GCM ciphertext (`RLENC1:…`), decrypted with a key\n  in `credentials.key` beside it — beside whichever file holds the password, so\n  a registry redirected with `--cameras-file` / `REOLINK_CAMERAS_FILE` carries\n  its key in its own directory, and so does a redirected `config.toml` (it can\n  hold a password too). An existing plaintext config is converted automatically\n  the first time you run any command — you do not have to do anything. Both\n  files are owner-only (`0600`), and the CLI refuses to read them if they are\n  group- or world-readable. Do not relax that, and do not commit them anywhere.\n- **Back up the file and the `credentials.key` next to it, as a pair.** Neither\n  is usable without the other. If the key is lost the passwords cannot be\n  recovered and must be re-entered with `device update <camera>\n  --password-stdin`. The pair rule holds in every layout — a redirected profile\n  is self-contained:\n\n  ```bash\n  # everything this profile needs, from ITS directory (not the default one)\n  cp /srv/cams/site-a/aliases.toml /srv/cams/site-a/credentials.key /backup/site-a/\n  ```\n\n  Restoring a registry without its neighbouring key fails loudly — every stored\n  password reports \"cannot be decrypted — the key file is missing\" — never\n  silently.\n- **Separate registries are separate secrets.** Each `--cameras-file` profile\n  keeps its own key, so sharing one profile's pair does not let anyone decrypt\n  another profile's registry. Before 0.12.4 every profile shared a single key\n  in the default config directory; a key still living there is read as a\n  fallback until the next write places it beside its file.\n- **This protects the file, not the account.** The key sits next to the data, so\n  anything that can read both can decrypt. What it removes is the casual\n  exposure: a copied config, a backup, or an AI agent reading the file no longer\n  hands over every camera credential in the clear.\n- **Credentials never go in a URL.** Gateway media endpoints take a session\n  token instead, which expires after 300 s of inactivity.\n- **`stream url --with-auth` is the one exception** — it embeds\n  `user:password@` in the printed RTSP/RTMP/FLV URL because players need it\n  there. That URL is a live credential: do not paste it into a ticket, a chat,\n  or a dashboard others can read. Without the flag, no credentials are printed.\n- **Redact before sharing output.** Command output can contain UIDs, serial\n  numbers, LAN addresses and stream URLs.\n\n## Installers\n\n`install.sh` and `install.ps1` fetch and run executables, so here is exactly\nwhat they do:\n\n- resolve the latest release from the GitHub API, then download that release's\n  asset from `github.com` — no other host is contacted\n- **verify the download against `checksums/<tag>.sha256` committed to this\n  repository's default branch**, and abort on any mismatch, missing entry, or\n  missing checksum file — never against the checksum attached to the release\n  itself. A release asset can be replaced by one API call and the attached\n  checksum regenerated with it; a file on the default branch sits behind a\n  reviewed pull request and permanent history. This is an integrity check, not\n  a signature: it moves the anchor out of the release, it does not prove who\n  built the archive.\n- install two binaries to `~/.local/bin` (`%USERPROFILE%\\.local\\bin` on\n  Windows) — **no `sudo`, no system directories, no services**\n- stop a running `reolink-gateway` **only if it runs from that same prefix**,\n  so another installation is never touched\n- overwrite previous binaries in that prefix; nothing else on disk is modified\n- add the prefix to your user `PATH` if it is missing (Windows)\n\nThey are ordinary text files: read them before running, as you should with any\ninstall script.\n\n### Verifying a download\n\nTo skip the installers, download an archive from the\n[Releases](https://github.com/reolink/reolink-cli/releases) page and verify it\nagainst the checksum committed to this repository, then copy the two binaries\nwherever you like:\n\n```bash\ntag=v0.10.6                                   # the release you downloaded\ncurl -fsSL -o CHECKSUMS \\\n  \"https://raw.githubusercontent.com/reolink/reolink-cli/main/checksums/$tag.sha256\"\nshasum -a 256 -c CHECKSUMS --ignore-missing    # sha256sum -c on Linux\n```\n\nUse that file, **not** the `SHA256SUMS` attached to the release. Anyone who can\nreplace a release asset can regenerate the checksum attached beside it in the\nsame API call, so a checksum from the release can only ever detect accidental\ncorruption. The committed file sits behind a reviewed pull request and permanent\nhistory.\n\n**What this does and does not prove.** It proves the archive is the one whose\nhash was committed. It does not prove who built it: the checksum is written by\nthe same release process that produces the archive, so an attacker who can\ncommit to the default branch can publish a matching pair. Closing that needs a\nsignature anchored outside the pipeline, which this project does not yet have —\ntracked in [SECURITY.md](SECURITY.md).\n\n`REOLINK_REPO` changes where the **archive** is downloaded from. It does not\nchange where the checksum comes from; that is pinned to `reolink/reolink-cli`,\nso a fork serving its own build fails verification rather than validating itself.\n\n## Trademarks\n\n\"Reolink\" and the Reolink logo are trademarks of Reolink Innovation Limited.\nThe Apache 2.0 licence covers the code and docs in this repository — it grants\nno rights to the Reolink name or logo. If you publish a fork, rename it and\nremove the marks; see [TRADEMARKS.md](TRADEMARKS.md).\n\n## License\n\n- **This repository** — the skill, plugin manifests, and docs (text) — is\n  licensed under the **[Apache License 2.0](LICENSE)** (see also [NOTICE](NOTICE)).\n- **The prebuilt `reolink-cli` binaries** on the\n  [Releases](https://github.com/reolink/reolink-cli/releases) page are\n  **proprietary**, governed by the EULA bundled in each release archive. The\n  underlying CLI source is not published here.\n- **Third-party open-source components** bundled in the binaries are listed in\n  `THIRD-PARTY-LICENSES.txt` inside each release archive.\n",
  "bytes": 21523,
  "sha": "2ab9d07d6267a17da0743ffe1c8b84870730a26839b9a2131bf304e6a9a6cb0f",
  "repo_slug": "reolink/reolink-cli",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_reolink_reolink_cli_c5cbd510/readme"
}