Skip to main content

image Give your AI agent hands.
One CLI to rule them all. Discover, configure, and control IoT devices across protocols.
Built for AI agents, loved by humans.

PyPI version Python versions CI Coverage License Privacy

Install • Quick Start • AI Integration • Protocols • Architecture


What is iotcli?

iotcli is a universal IoT device control CLI. It unifies smart-home devices behind a single, predictable interface — so you (or your AI agent) can control lights, AC units, feeders, and sensors without memorizing protocol quirks.

Key principles:

  • One command shape for every device — on, off, status, set
  • Protocol-agnostic — Tuya, miIO, MQTT, HTTP, LG ThinQ, and more
  • AI-native — JSON mode, skill files, and an MCP server for Claude Desktop / Cursor / Zed
  • Privacy-first — everything local, credentials encrypted, no telemetry

Install

# Global install via pipx (recommended — no venv needed)
pipx install git+https://github.com/iotviaai/iotcli.git

# Or with MCP support for Claude Desktop / Cursor
pipx install git+https://github.com/iotviaai/iotcli.git[mcp]

# From source
git clone https://github.com/iotviaai/iotcli.git
cd iotcli
pip install -e ".[dev]"

Requires Python 3.10+

Quick Start

# Interactive setup wizard (Rich TUI)
iotcli setup

# Discover devices on your network
iotcli discover --network 192.168.1.0/24

# Add a device
iotcli add --name living-room-light --protocol miio \
    --ip 192.168.1.100 --token <32chars>

# Control
iotcli control on living-room-light
iotcli control status living-room-light
iotcli control set living-room-light brightness=80

# AI agent mode (structured JSON)
iotcli --json list
iotcli --json control status living-room-light
iotcli --json status-all

Demo

$ iotcli list
╭─────────── Devices ───────────╮
│ Name              Protocol  IP            │
│ living-room-light miio      192.168.1.100 │
│ feeder            tuya      192.168.1.4   │
│ lg-ac             lgac      (cloud)       │
╰───────────────────────────────╯

$ iotcli control status lg-ac
╭─── lg-ac — online ───╮
│   power: POWER_OFF   │
│   mode: HEAT         │
│   fan_speed: HIGH    │
│   current_temp: 20.5 │
│   target_temp: 25    │
╰──────────────────────╯

$ iotcli --json control on feeder
{"success": true, "device": "feeder", "action": "on"}

Supported Protocols

Protocol Devices Connection
miio Xiaomi / Yeelight Local (UDP)
tuya Tuya-based (lights, plugs, etc.) Local (TCP)
mqtt Zigbee / Aqara via MQTT broker Local (TCP)
http ESPHome / Tasmota Local (HTTP)
lgac LG Air Conditioner (ThinQ) Cloud (HTTPS)

Tuya Profiles

Profile Devices Special Actions
generic Any Tuya device power on/off
light Smart bulbs brightness, color_temperature, color
switch Smart plugs power, countdown
petfeeder ROJECO / Tuya feeders portions, quick_feed, slow_feed, light
iotcli add --name feeder --protocol tuya --profile petfeeder \
    --ip 192.168.1.4 --device-id <id> --local-key <key> --version 3.4

AI Agent Integration

iotcli was built from the ground up for AI agents. Every command supports --json for structured, parseable output.

Skill Files

Generate per-device skill files so your agent knows exactly what each device can do:

iotcli skills generate

Files created in ~/.iotcli/skills/:

  • <device>/SKILL.md — per-device capability doc (OpenClaw-compatible)
  • iotcli.tools.json — OpenAI/Anthropic tool schema
  • iotcli.skill.yaml — legacy global skill spec
  • system_prompt.md — ready-to-use agent system prompt

MCP Server (Claude Desktop / Cursor / Zed)

Connect iotcli directly to your AI assistant via the Model Context Protocol:

# Install with MCP support
pip install iotcli[mcp]

# Start the server
iotcli serve mcp

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "iotcli": {
      "command": "iotcli",
      "args": ["serve", "mcp"]
    }
  }
}

Once connected, Claude can list devices, check status, turn them on/off, and set properties — all through structured tool calls with per-device enums and value validation. No copy-pasting commands.

Agent Workflow

# 1. Discover what's available
iotcli --json list

# 2. Check state before acting
iotcli --json control status "living-room-light"

# 3. Act
iotcli --json control on "living-room-light"
iotcli --json control set "living-room-light" "brightness=80"

Architecture

src/iotcli/
├── core/           # Device model, protocol registry, controller
├── protocols/      # Self-registering protocol handlers
├── config/         # YAML config + Fernet credential vault
├── discovery/      # Async multi-protocol network scanner
├── tui/            # Rich + InquirerPy interactive wizard
├── cli/            # Click commands (discover, control, device, config, skills)
├── skills/         # Jinja2-based AI agent skill generator
└── mcp/            # MCP server for Claude Desktop / Cursor / Zed

Design decisions:

  • Protocol registry (core/registry.py): Decorator-based self-registration. No hardcoded mappings.
  • Device model (core/device.py): Dataclass with slugify() for normalized names.
  • Credentials: Fernet-encrypted vault, never in devices.yaml. Key stored at 0600.
  • Extensible: Add a protocol by implementing BaseProtocol — the CLI, wizard, and skill generator pick it up automatically.

Security

  • Credentials are never stored in config files
  • Secrets encrypted with Fernet at ~/.iotcli/credentials/
  • Encryption key has 0600 permissions (owner-only)
  • No telemetry, no analytics, no cloud dependency
  • Fully open source — inspect exactly what runs on your machine

See PRIVACY.md for details.

Extending — Add a New Protocol

# src/iotcli/protocols/myproto.py

@register_protocol("myproto")
class MyProtocol(BaseProtocol):
    meta = ProtocolMeta(
        name="myproto",
        display_name="My Protocol",
        default_port=9999,
        required_credentials=["api_key"],
        ...
    )

    def connect(self) -> bool: ...
    def disconnect(self) -> None: ...
    def turn_on(self) -> bool: ...
    def turn_off(self) -> bool: ...
    def get_status(self) -> dict: ...
    def set_value(self, prop, value) -> bool: ...

Add one import in protocols/__init__.py — the CLI, wizard, and skill generator pick it up automatically.

License

MIT


Made with passion for AI agents and smart homes.

Metadata

Release files for iotcli 0.10.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for iotcli 0.10.1
File Size Uploaded Provenance Actions
iotcli-0.10.1.tar.gz 69.0 kB With provenance Details for iotcli-0.10.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for iotcli 0.10.1
File Interpreter ABI Platform Actions
iotcli-0.10.1-py3-none-any.whl Python 3 none any Details for iotcli-0.10.1-py3-none-any.whl

Total release size: 154.2 kB

Release files / iotcli-0.10.1.tar.gz

Download URL iotcli-0.10.1.tar.gz
Size 69.0 kB
Tags Source
SHA-256 checksum
How to use checksums
74f7121cc5213906f1ef02ece96158a766fe8f4a4f284ab56926848a71e4bc72
BLAKE2b-256 checksum
How to use checksums
14975f42f5b04a41aca90efdb668a6744de41764a1c7857469de6f72d5c8ab8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 22, 2026.

Transparency log

Release files / iotcli-0.10.1-py3-none-any.whl

Download URL iotcli-0.10.1-py3-none-any.whl
Size 85.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1edf8f6f8f032f30b662bcb73711dce5e3777f18d570296ebeceb91d02767643
BLAKE2b-256 checksum
How to use checksums
f67f4eb2cedb38e8a34d2981ef9db9e1a7a025e2e3ae12ebea9acf8acafdb604
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 22, 2026.

Transparency log

Security for iotcli 0.10.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for iotcli-0.10.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.10.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page