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.
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 schemaiotcli.skill.yaml— legacy global skill specsystem_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 withslugify()for normalized names. - Credentials: Fernet-encrypted vault, never in
devices.yaml. Key stored at0600. - 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
0600permissions (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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.