The only standalone CLI for Dreo smart-home devices — bulk control, live sensor streams, and a local history every other Dreo tool throws away.
Every existing Dreo client is bundled inside Home Assistant or Homebridge; this is the first general-purpose CLI. It speaks the same WebSocket control protocol the reverse-engineered clients use, plus it keeps a local SQLite cache so bulk fan-out, cross-device sensor snapshots, sensor history, scenes, and alerts work even when the cloud is slow.
Created by @tmchow (Trevin Chow).
The recommended path installs both the dreo-pp-cli binary and the pp-dreo agent skill (Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, and other agents supported by the upstream skills CLI) in one shot:
npx -y @mvanhorn/printing-press-library install dreoFor CLI only (no skill):
npx -y @mvanhorn/printing-press-library install dreo --cli-onlyFor skill only — installs the skill into the same agents as the default command above, but skips the CLI binary (use this to update or reinstall just the skill):
npx -y @mvanhorn/printing-press-library install dreo --skill-onlyTo constrain the skill install to one or more specific agents (repeatable — agent names match the skills CLI):
npx -y @mvanhorn/printing-press-library install dreo --agent claude-code
npx -y @mvanhorn/printing-press-library install dreo --agent claude-code --agent codexIf npx isn't available (no Node, offline), install the CLI directly via Go (requires Go 1.26.3 or newer):
go install github.com/mvanhorn/printing-press-library/library/devices/dreo/cmd/dreo-pp-cli@latestThis installs the CLI only — no skill.
Download a pre-built binary for your platform from the latest release. On macOS, clear the Gatekeeper quarantine: xattr -d com.apple.quarantine <binary>. On Unix, mark it executable: chmod +x <binary>.
Install the CLI binary first. The installer writes binaries to a per-user managed bin directory by default: $HOME/.local/bin on macOS/Linux and %LOCALAPPDATA%\Programs\PrintingPress\bin on Windows.
npx -y @mvanhorn/printing-press-library install dreo --cli-onlyThen install the focused Hermes skill.
From the Hermes CLI:
hermes skills install mvanhorn/printing-press-library/cli-skills/pp-dreo --forceInside a Hermes chat session:
/skills install mvanhorn/printing-press-library/cli-skills/pp-dreo --forceRestart the Hermes session or gateway if the newly installed skill is not visible immediately.
Install both the CLI binary and the focused OpenClaw skill. The installer defaults binaries to a per-user bin directory ($HOME/.local/bin on macOS/Linux, %LOCALAPPDATA%\Programs\PrintingPress\bin on Windows):
npx -y @mvanhorn/printing-press-library install dreo --agent openclawRestart the OpenClaw session or gateway if the newly installed skill is not visible immediately.
This 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. - Fill in
DREO_USERNAMEwhen Claude Desktop prompts you.
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": {
"dreo": {
"command": "dreo-pp-mcp",
"env": {
"DREO_USERNAME": "<your-dreo-email>",
"DREO_PASSWORD": "<your-dreo-password>"
}
}
}
}Dreo has no public developer API. Authentication uses your Dreo account email and password against the same OAuth endpoint the Dreo iOS app calls — the password is MD5-hashed before the wire, and the bearer token returned is cached locally.
Set these two env vars:
export DREO_USERNAME='your-dreo-account-email'
export DREO_PASSWORD='your-dreo-password'Then run any command. The CLI exchanges credentials for an access token on first use, caches both the credentials and the bearer to ~/.config/dreo-pp-cli/config.toml at mode 0600, and reuses them. When the bearer expires it transparently re-logs in using the cached credentials — Dreo's OAuth flow has no refresh token, so caching the credentials is what lets cron jobs and unattended runs survive token expiry without re-exporting env vars every session. Region discovery (us/eu) happens automatically on first login; pin it with DREO_REGION=us to skip the round-trip.
Three ways to supply credentials:
- Env vars (recommended): Set
DREO_USERNAMEandDREO_PASSWORDand rundreo-pp-cli auth login. --password-stdin(scriptable, no leak): Pipe the password from a secret manager — Docker-style:op read 'op://Personal/Dreo/password' | dreo-pp-cli auth login --username me@example.com --password-stdin pass dreo/password | dreo-pp-cli auth login --username me@example.com --password-stdin
--password <value>flag (insecure, warns): Supported for ergonomics, butauth loginprints a stderr warning every time because the plaintext lands in/proc/<pid>/cmdline,ps aux, audit logs, and shell history. Use only when you understand the trade-off.
What's cached on disk. ~/.config/dreo-pp-cli/config.toml (mode 0600, in your home directory) contains:
usernameandpassword— the credentials you supplied via env vars (in plaintext, mirroring AWS CLI's~/.aws/credentialsand Stripe CLI's config conventions)access_token— the OAuth bearerregion,token_expiry, timestamps — non-sensitive metadata
Treat the file as sensitive: don't commit it to a public repo, don't share it, and don't sync it to cloud-storage providers without encryption. Mode 0600 keeps it readable only by your user account. To wipe everything (credentials and token): dreo-pp-cli auth logout.
Useful commands:
dreo-pp-cli auth login— explicit login (also runs lazily on first authenticated command, and automatically on 401)dreo-pp-cli auth status— current authentication state (doesn't reveal the token or password)dreo-pp-cli auth logout— wipe cached token and persisted credentialsdreo-pp-cli doctor— verify everything end-to-end
# Verify credentials and login round-trip against the live API
dreo-pp-cli doctor
# See every device on your Dreo account with model, room, and online status
dreo-pp-cli devices list
# Whole-house temperature, humidity, and PM2.5 in one shot
dreo-pp-cli sensors --json
# Turn off every tower fan in one command — the bedtime ritual
dreo-pp-cli bulk --action off --type tower-fan
# Live WebSocket state stream as JSON lines — the realtime debug surface no other Dreo tool exposes
dreo-pp-cli watch --all
These capabilities aren't available in any other tool for this API.
-
bulk— Power, mode, or speed across every device matching a type/room filter in one command.Replaces the #1 user pain — tapping each device in the Dreo app at bedtime — with one cron-callable line.
dreo-pp-cli bulk --action off --type tower-fan --dry-run
-
scene save— Capture the current state across selected devices as a named scene and replay it later as parallel WebSocket frames.Sam's nightly bedtime routine becomes one command; survives app updates.
dreo-pp-cli scene save bedtime --all && dreo-pp-cli scene apply bedtime --dry-run
-
sensors— Aggregated temperature, humidity, and PM2.5 across every sensor-bearing device in one ranked table.Answers the agent question 'what's the air quality across my house?' in one tool call.
dreo-pp-cli sensors --json
-
sensors record— Persist WebSocket state events to a local sensor_readings table and query temperature/humidity/PM2.5 over arbitrary time windows.Answers 'when did the bedroom fan last go to sleep mode' and similar historical questions agents and users actually ask.
dreo-pp-cli sensors query --metric temperature --since 1h --json
-
alerts— Report devices with low filter life, empty water tank, offline heartbeat, or sensor readings past a threshold.Surfaces actionable problems (filter, water, dead devices) without manually inspecting each device.
dreo-pp-cli alerts --pm25-above 50 --json
-
rooms— Group devices by room with on-count, average temperature, and average humidity per room.Answers 'what's happening in my bedroom right now' in one query.
dreo-pp-cli rooms --json
-
devices search— Full-text search over cached device name, room, model, and serial.Fast device lookup for scripts and agents without round-tripping the cloud.
dreo-pp-cli devices search Fan
-
watch— Tail-f for Dreo device state — every WebSocket update as a JSON line on stdout.Enables automation debugging without running Home Assistant, and feeds agent stream-processing pipelines.
dreo-pp-cli watch --all --json
Run dreo-pp-cli --help for the full command reference and flag list.
Discover and inspect Dreo devices on your account
dreo-pp-cli devices list- List every Dreo device on your accountdreo-pp-cli devices state- Read the current state snapshot for one device
Read firmware metadata and check for updates
dreo-pp-cli firmware- Check whether a firmware update is available for a device
Read and write persistent per-device settings
dreo-pp-cli settings get- Get persistent settings for a devicedreo-pp-cli settings update- Update persistent settings for a device
# Human-readable table (default in terminal, JSON when piped)
dreo-pp-cli devices list
# JSON for scripting and agents
dreo-pp-cli devices list --json
# Filter to specific fields
dreo-pp-cli devices list --json --select id,name,status
# Dry run — show the request without sending
dreo-pp-cli devices list --dry-run
# Agent mode — JSON + compact + no prompts in one flag
dreo-pp-cli devices 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 - Agent-safe by default - no colors or formatting unless
--human-friendlyis set
Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.
dreo-pp-cli doctorVerifies configuration, credentials, and connectivity to the API.
Config file: ~/.config/dreo-pp-cli/config.toml
Static request headers can be configured under headers; per-command header overrides take precedence.
Environment variables:
| Name | Kind | Required | Description |
|---|---|---|---|
DREO_USERNAME |
per_call | Yes | Set to your API credential. |
DREO_PASSWORD |
per_call | Yes | Set to your API credential. |
Authentication errors (exit code 4)
- Run
dreo-pp-cli doctorto check credentials - Verify the environment variable is set:
echo $DREO_USERNAMENot found errors (exit code 3) - Check the resource ID is correct
- Run the
listcommand to see available items
- doctor reports auth failure — Verify DREO_USERNAME and DREO_PASSWORD are exported; if you changed your password in the Dreo app, run dreo-pp-cli auth login again
- Empty device list — Run dreo-pp-cli devices list --live to bypass the local cache and fetch fresh from the cloud
- Commands return but device state does not change — Add --wait to the set/bulk command so the CLI confirms the WebSocket state echo before exiting
- Wrong region — Set DREO_REGION=eu (or us) to skip the region-discovery round-trip; the CLI auto-detects on first login
This CLI was built by studying these projects and resources:
- hass-dreo — Python (200 stars)
- homebridge-dreo — TypeScript (80 stars)
- hass-dreoverse — Python (30 stars)
- pydreo-client — Python (20 stars)
Generated by CLI Printing Press