SwitchBot smart home CLI — control lights, locks, curtains, sensors, plugs, and IR appliances (TV/AC/fan) via the SwitchBot Cloud API v1.1. Run scenes, stream real-time events over MQTT, and plug AI agents into your home via the built-in MCP server — all from your terminal or shell scripts.
- npm package:
@switchbot/openapi-cli - Source code: github.com/OpenWonderLabs/switchbot-openapi-cli
- Releases / changelog: GitHub Releases
- Issues / feature requests: GitHub Issues
Looking for the conversational skill that drives this CLI from a chat agent? A companion skill for third-party agent hosts is maintained in a separate repository. See
docs/agent-guide.mdfor the authoritative surfaces (MCP,agent-bootstrap,schema export,capabilities --json) the skill consumes. Skill packaging + registry entry is tracked as Phase 3B — seedocs/design/roadmap.md.
Three entry points, same binary — pick the one that matches how you use it:
- Human: start with this README (Quick start).
You get colored tables, helpful error hints, shell completion, and
switchbot doctorself-check. - Script: start with Output modes and
Scripting examples.
You get
--json,--format=tsv/yaml/id,--fields, stable exit codes,history replay, and audit log support. - Agent: start with
docs/agent-guide.md. You getswitchbot mcp serve(stdio MCP server),schema export,plan run, and destructive-command guards.
Under the hood every surface shares the same catalog, cache, and HMAC client — switching between them costs nothing.
- Features · Requirements · Installation
- Quick start
- Credentials
- Policy · Rules engine
- Global options
- Commands: config · devices · scenes · webhook · events · status-sync · daemon · plan · mcp · doctor · health · upgrade-check · quota · history · catalog · schema · capabilities · cache · policy cmd · completion
- Output modes · Cache · Exit codes · Environment variables
- Scripting examples · Development · License
- 🔌 Complete API coverage — every
/v1.1endpoint (devices, scenes, webhooks) - 📚 Built-in catalog — offline reference for every device type's supported commands, parameter formats, and status fields (no API call needed)
- 🎨 Dual output modes — colorized tables by default;
--jsonpassthrough forjqand scripting - 🔐 Secure credentials — HMAC-SHA256 signed requests; config file written with
0600; env-var override for CI - 🔍 Dry-run mode — preview every mutating request before it hits the API
- 🧪 Fully tested — 2225 Vitest tests, mocked axios, zero network in CI
- ⚡ Shell completion — Bash / Zsh / Fish / PowerShell
- Node.js ≥ 18
- A SwitchBot account with Developer Options enabled (see Credentials)
npm install -g @switchbot/openapi-cliThis adds the switchbot binary to your $PATH.
git clone https://github.com/OpenWonderLabs/switchbot-openapi-cli.git
cd switchbot-openapi-cli
npm install
npm run build
npm link # optional — expose `switchbot` globallyVerify:
switchbot --version
switchbot --helpThe fast path (credentials + policy + skill link, with rollback on failure):
switchbot install --agent claude-code --skill-path ../switchbot-skill
# or preview first
switchbot install --dry-runPrefer the manual 4-step walk-through? Here it is:
# 1. Save your credentials (one-time)
switchbot config set-token <token> <secret>
# 2. List every device on your account
switchbot devices list
# 3. Control a device, writing a structured entry to the audit log
switchbot devices command <deviceId> turnOn --audit-log
# 4. Confirm everything is healthy — network, catalog, credentials, cache.
# Any non-"ok" check prints with a hint; fix those first.
switchbot doctor --json | jq '.checks[] | select(.status!="ok")'Adding an AI agent or declarative automation? A few more one-liners round out the first-day path:
# 5. Cold-start snapshot an LLM can read before its first tool call.
switchbot agent-bootstrap --compact | jq '.identity, .devices.total'
# 6. Scaffold a policy.yaml (aliases, quiet hours, confirmations) and
# validate it. Safe to run — defaults apply if you never edit it.
switchbot policy new
switchbot policy validate
# 7. Stream real-time device events over MQTT (events land as JSONL).
switchbot events mqtt-tail --max 3 --json
# 8. Run the OpenClaw status bridge in the background.
switchbot status-sync start --openclaw-model home-agentSee Policy for the authoring flow, Rules engine
for automations, and docs/agent-guide.md
for the agent surface.
The CLI reads credentials in this order (first match wins):
- Environment variables —
SWITCHBOT_TOKENandSWITCHBOT_SECRET - OS keychain — native keychain (macOS Keychain / Windows Credential Manager / libsecret on Linux) when populated via
switchbot auth keychain set - Config file —
~/.switchbot/config.json(written byconfig set-token, mode0600)
Obtain the token and secret from the SwitchBot mobile app: Profile → Preferences → Developer Options → Get Token.
# One-time setup (writes ~/.switchbot/config.json)
switchbot config set-token <token> <secret>
# Or export environment variables (e.g. in CI)
export SWITCHBOT_TOKEN=...
export SWITCHBOT_SECRET=...
# Confirm which source is active and see the masked secret
switchbot config showPrefer native OS storage over the 0600 JSON on disk:
# See which backend is active on this machine
switchbot auth keychain describe
# Move existing ~/.switchbot/config.json into the keychain.
# With --delete-file, the CLI deletes the source only when it contains
# nothing except token/secret; otherwise it scrubs those fields and keeps
# profile metadata such as labels and limits.
switchbot auth keychain migrate
# Or write credentials directly (TTY prompt or --stdin-file <path>)
switchbot auth keychain set
# Verify a profile has credentials without leaking the material
switchbot auth keychain getBackends: security(1) on macOS, libsecret / secret-tool on Linux,
Credential Manager (via PowerShell + Win32 CredReadW/CredWriteW) on
Windows. If no native backend is available, the file backend takes
over transparently so the CLI keeps working. switchbot doctor
surfaces which backend is active and warns when file-stored credentials
could be moved into a writable keychain.
policy.yaml is an optional per-user file that declares preferences
the CLI (and any connected AI agent) should honour: device aliases,
quiet-hours, confirmation overrides, audit-log location, and CLI
profile. The file lives at:
- Linux / macOS: default policy path resolved by the CLI
- Windows: default policy path resolved by the CLI
Everything in it is optional — if the file is missing, safe defaults apply. Scaffold, edit, and validate:
switchbot policy new # write a commented starter template
$EDITOR <policy-path>
switchbot policy validate # exit 0 if OK, otherwise line-accurate errorWhy most users want a policy file: it makes name resolution
deterministic. Without it, "turn on the bedroom light" falls through
the CLI's prefix/substring/fuzzy match strategies and can pick the
wrong device when two names collide. A one-line aliases entry
removes the ambiguity.
Schema version. The CLI requires policy v0.2. If you have an existing v0.1 file from an earlier release, migrate it first:
switchbot policy migrate # in-place upgrade, preserves commentsThe v0.2 schema adds a typed automation.rules[] block (triggers, conditions,
throttles, dry-run) used by the rules engine (see
Rules engine). Full field-by-field reference, validation flow,
and error catalogue: docs/policy-reference.md.
Five annotated starter files covering common setups live in
examples/policies/.
With a policy.yaml (v0.2) you can declare automations that the CLI
executes for you. Supported triggers: MQTT (device events),
cron (schedule-driven), and webhook (local HTTP POST).
Supported conditions: time_between (quiet hours), device_state
(live API check with per-tick dedup), and llm (AI decision — see
below). Every fire is recorded in ~/.switchbot/audit.log. rules run is long-running; use
daemon start / daemon reload for the managed background mode.
Actions — each rule's then array accepts two action types:
type: command(default, notypefield required) — sends a device command, e.g.devices command <id> turnOntype: notify— delivers a payload to an external channel after the rule fires:channel: webhook— HTTP POST to a URL (onlyhttp://andhttps://schemes are accepted;rules lintrejects others)channel: file— appends a JSONL line to a local file.tomust be an absolute path; relative or~-prefixed paths are rejected byrules lint(codenotify-relative-path) and at runtimechannel: openclaw— HTTP POST to an OpenClaw endpoint (same protocol restriction)- Optional
templatefield supports{{ rule.name }},{{ event.* }},{{ device.id }}placeholders. Nested fields use dot paths, e.g.{{ event.context.deviceMac }}; arrays index numerically, e.g.{{ event.list.0 }}
then:
- command: devices command AC_001 turnOn
- type: notify
channel: webhook
to: https://your.host/hook
template: '{"rule":"{{ rule.name }}","fired":"{{ rule.fired_at }}"}'LLM condition — add an AI judgement step before actions fire:
conditions:
- llm:
prompt: "Is the temperature above normal comfort range?"
provider: auto # auto | openai | anthropic
cache_ttl: 5m
budget:
max_calls_per_hour: 20
on_error: pass # fail | pass | skipSet OPENAI_API_KEY or ANTHROPIC_API_KEY. rules lint flags misconfigured LLM conditions.
Decision trace — set automation.audit.evaluate_trace: sampled (or full) in policy.yaml to record every evaluation decision.
switchbot rules lint # static check: exit 0 valid, 1 error
switchbot rules list --json | jq . # structured rule summary
switchbot rules explain "motion on" # trigger, conditions, actions, last fired
switchbot rules run --dry-run --max-firings 5 # run engine; --dry-run = audit only
switchbot daemon reload # hot-reload policy without restart
switchbot rules tail --follow # stream rule-* audit lines
switchbot rules replay --since 1h --json # per-rule fires/dries/throttled/errors
switchbot rules summary # aggregate fires/errors (24h)
switchbot rules conflicts # opposing actions, destructive cmds, quiet-hours gaps
switchbot rules doctor --json # lint + conflicts; exit 0 when clean
switchbot rules suggest --intent "turn off AC at 11pm"
switchbot rules suggest --intent "..." --llm auto # LLM-backed (OPENAI_API_KEY or ANTHROPIC_API_KEY)
switchbot rules trace-explain --rule "motion on" --last # why a rule fired/was blocked
switchbot rules simulate "motion on" --since 7d --json # replay without running the engineLLM-generated rules always have dry_run: true — flip it yourself after review. Notify URLs must be http:// or https://. See docs/design/phase4-rules.md for the full pipeline.
--json: Print the raw JSON response instead of a formatted table.--format <fmt>: Output format:tsv,yaml,jsonl,json,id.--fields <cols>: Comma-separated column names to include (for exampledeviceId,type).-v,--verbose: Log HTTP request/response details to stderr.--dry-run: Print mutating requests (POST/PUT/DELETE) without sending them.--timeout <ms>: HTTP request timeout in milliseconds (default30000).--config <path>: Override credential file location (default~/.switchbot/config.json).--profile <name>: Use a named credential profile (~/.switchbot/profiles/<name>.json).--cache <dur>: Set list and status cache TTL, for example5m,1h,off,auto(default).--cache-list <dur>: Set list-cache TTL independently (overrides--cache).--cache-status <dur>: Set status-cache TTL independently (default off; overrides--cache).--no-cache: Disable all cache reads for this invocation.--retry-on-429 <n>: Max 429 retry attempts (default3).--no-retry: Disable automatic 429 retries.--backoff <strategy>: Retry backoff:exponential(default) orlinear.--no-quota: Disable local request-quota tracking.--audit-log: Append mutating commands to a JSONL audit log (default path~/.switchbot/audit.log).--audit-log-path <path>: Custom audit log path; use together with--audit-log.-V,--version: Print the CLI version.-h,--help: Show help for any command or subcommand.
Every subcommand supports --help. Use --flag=value form when a flag takes a value and is followed by a subcommand (e.g. switchbot --profile=home devices list).
Intercepts every non-GET request: prints the URL/body it would have sent, then exits 0. GET requests still execute. Also validates command names against the device catalog (exit 2 on unknown commands or read-only sensors).
switchbot devices command ABC123 turnOn --dry-run
# [dry-run] Would POST https://api.switch-bot.com/v1.1/devices/ABC123/commands
# [dry-run] body: {"command":"turnOn","parameter":"default","commandType":"command"}switchbot config set-token <token> <secret> # Save to ~/.switchbot/config.json
switchbot config show # Print current source + masked secret
switchbot config list-profiles # List saved profiles
switchbot config agent-profile --write # write recommended AI-agent profile (mode 0600)# List all physical devices and IR remote devices
switchbot devices list # default 4 columns: deviceId, deviceName, type, category
switchbot devices list --wide # full 10-column operator view
switchbot devices list --json | jq '.deviceList[].deviceId'
switchbot devices list --format=tsv --fields=deviceId,type,category
# Filter by type / name / category / room
# Operators: = (substring; exact for category), ~ (substring), =/regex/; clauses AND-ed
switchbot devices list --filter 'type=Bot'
switchbot devices list --filter 'name~living,type=/Bulb|Strip/'
switchbot devices list --filter 'category=physical'
# Query real-time status
switchbot devices status <deviceId>
switchbot devices status --ids ABC,DEF,GHI # batch status
switchbot devices status --ids ABC,DEF --fields power,battery --format jsonl
# Resolve device by fuzzy name instead of ID (status, command, describe, expand, watch)
switchbot devices status --name "Living Room AC"
switchbot devices command --name "Office Light" turnOn
# Send a control command
switchbot devices command <deviceId> <cmd> [parameter] [--type command|customize]
# Offline reference (no API call)
switchbot devices types # all device types
switchbot devices commands <type> # commands, parameter formats, status fieldsParameters for setAll, setPosition, setMode, setBrightness, and setColor are validated client-side (exit 2 on bad input). setColor accepts R:G:B, #RRGGBB, #RGB, and CSS names — all normalize to R:G:B. Pass --skip-param-validation to bypass. Unknown deviceIds exit 2 by default; pass --allow-unknown-device for scripted pass-through.
For per-device command and parameter details: switchbot devices commands <type> or the SwitchBot API docs.
Some commands require a packed string like "26,2,2,on". devices expand builds it from readable flags:
# Air Conditioner — setAll
switchbot devices expand <acId> setAll --temp 26 --mode cool --fan low --power on
# Resolve by name
switchbot devices expand --name "Living Room AC" setAll --temp 26 --mode cool --fan low --power on
# Curtain / Roller Shade — setPosition
switchbot devices expand <curtainId> setPosition --position 50 --mode silent
# Blind Tilt — setPosition
switchbot devices expand <blindId> setPosition --direction up --angle 50
# Relay Switch — setMode
switchbot devices expand <relayId> setMode --channel 1 --mode edge
# Color Bulb / Strip Light / Floor Lamp / Ceiling Light — setBrightness / setColor / setColorTemperature
switchbot devices expand <bulbId> setBrightness --brightness 80
switchbot devices expand <bulbId> setColor --color "#FF0000"
switchbot devices expand <bulbId> setColorTemperature --color-temp 4000Run switchbot devices expand <id> <command> --help to see the available flags for any device command.
switchbot devices explain <deviceId> # metadata + commands + live status
switchbot devices explain <deviceId> --no-live # catalog-only, no API callswitchbot devices meta set <deviceId> --alias "Office Light"
switchbot devices meta set <deviceId> --hide # hide from `devices list`
switchbot devices meta get <deviceId>
switchbot devices meta list
switchbot devices meta clear <deviceId>Stores local annotations in ~/.switchbot/device-meta.json. --show-hidden on devices list reveals hidden devices.
# Same command to every matching device
switchbot devices batch turnOff --filter 'type=Bot'
switchbot devices batch setBrightness 50 --filter 'type~Light,family=Living'
switchbot devices batch turnOn --ids ID1,ID2,ID3
switchbot devices list --format=id --filter 'type=Bot' | switchbot devices batch toggle -
switchbot devices batch unlock --filter 'type=Smart Lock' --yes # destructive: requires --yesFilter keys: type, family, room, category. Skipped-offline devices appear under summary.skipped when --skip-offline is passed.
switchbot scenes list # Columns: sceneId, sceneName
switchbot scenes execute <sceneId>
# One-shot summary: risk profile, execution hint, estimated commands
switchbot scenes explain <sceneId>
switchbot scenes explain <sceneId> --json# Register a receiver URL for events from ALL devices
switchbot webhook setup https://your.host/hook
# Query what is currently configured
switchbot webhook query
switchbot webhook query --details https://your.host/hook
# Enable / disable / re-submit the registered URL
switchbot webhook update https://your.host/hook --enable
switchbot webhook update https://your.host/hook --disable
# Remove the configuration
switchbot webhook delete https://your.host/hookThe CLI validates that <url> is an absolute http:// or https:// URL before calling the API. --enable and --disable are mutually exclusive.
switchbot events tail # listen on port 3000
switchbot events tail --filter deviceId=ABC123 # filter to one device
switchbot events tail --filter 'type=WoMeter' --max 5 --for 10m
switchbot events tail --port 8080 --path /hook --jsonRun switchbot webhook setup https://your.host/hook first. events tail only runs the local receiver — tunnelling (ngrok/cloudflared) is up to you.
switchbot events mqtt-tail # stream all shadow events (Ctrl-C to stop)
switchbot events mqtt-tail --topic 'switchbot/#' # filter to topic subtree
switchbot events mqtt-tail --max 10 --for 30s --jsonCredentials are provisioned automatically from the REST API config. Use --sink to route events to external services (file, webhook, telegram, homeassistant, openclaw) — see switchbot events mqtt-tail --help for details.
Forwards SwitchBot MQTT shadow events into an OpenClaw gateway with stable lifecycle management.
switchbot status-sync run --openclaw-model home-agent # foreground (for supervisors)
switchbot status-sync start --openclaw-model home-agent # background
switchbot status-sync status --json
switchbot status-sync stopRequired: OPENCLAW_MODEL (or --openclaw-model) and OPENCLAW_TOKEN. Optional: OPENCLAW_URL, --topic, --state-dir. Background mode writes state.json, stdout.log, and stderr.log under the state directory.
Runs switchbot rules run as a detached background process. Tracks runtime
metadata in ~/.switchbot/daemon.state.json and can co-launch a health HTTP
server.
# Start the daemon (no-op if already running)
switchbot daemon start
switchbot daemon start --policy ./my-policy.yaml
switchbot daemon start --healthz-port 3100 # also launch health serve on port 3100
switchbot daemon start --force # restart even if already running
# Inspect daemon state (pid, log path, health server, last reload)
switchbot daemon status
switchbot daemon status --json
# Hot-reload policy without restarting (sends SIGHUP on Unix, writes sentinel on Windows)
switchbot daemon reload
# Stop the daemon and any co-launched health server
switchbot daemon stopStart prints the PID, log path, and state file location. If the process exits within 300 ms of launch, start fails immediately and includes the last 20 lines of the log in the error message for fast diagnosis.
# Bash: load on every new shell
echo 'source <(switchbot completion bash)' >> ~/.bashrc
# Zsh
echo 'source <(switchbot completion zsh)' >> ~/.zshrc
# Fish
switchbot completion fish > ~/.config/fish/completions/switchbot.fish
# PowerShell (profile)
switchbot completion powershell >> $PROFILESupported shells: bash, zsh, fish, powershell (pwsh is accepted as an alias).
# Print the plan JSON Schema (give to your agent framework)
switchbot plan schema
# Draft a candidate plan from natural language intent
switchbot plan suggest --intent "turn off all lights" --device <id1> --device <id2>
# Validate a plan file without running it
switchbot plan validate plan.json
# Preview — mutations skipped, GETs still execute
switchbot --dry-run plan run plan.json
# Save / review / approve / execute for destructive plans
switchbot plan save plan.json
switchbot plan review <planId>
switchbot plan approve <planId>
switchbot plan execute <planId>
switchbot plan run plan.json --continue-on-error
# Run with per-step TTY confirmation for destructive steps (human-in-the-loop)
switchbot plan run plan.json --require-approvalA plan file is a JSON document with version, description, and a steps array of command, scene, or wait steps. Steps execute sequentially; a failed step stops the run unless --continue-on-error is set. plan run is the preview/direct path, but destructive steps are blocked by default and should go through plan save → plan review → plan approve → plan execute. See docs/agent-guide.md for the full schema and agent integration patterns.
# Poll a device's status every 30 s until Ctrl-C
switchbot devices watch <deviceId>
# Custom interval; emit every tick even when nothing changed
switchbot devices watch <deviceId> --interval 10s --include-unchanged --json
# Time-bounded: stop after 5 minutes instead of a fixed tick count
switchbot devices watch <deviceId> --for 5mOutput is a JSONL stream of status-change events (with --json) or a refreshed table. Use --max <n> to stop after N ticks, or --for <duration> to stop after an elapsed wall-clock window (e.g. 30s, 1h, 2d). When both are set, whichever limit trips first wins.
# Start the stdio MCP server (connect via Claude, Cursor, etc.)
switchbot mcp serveExposes MCP tools (list_devices, describe_device, get_device_status,
get_device_history, query_device_history, aggregate_device_history,
send_command, list_scenes, run_scene, search_catalog,
account_overview, plan_suggest, plan_run, audit_query,
audit_stats, policy_diff, policy_validate, policy_new,
policy_migrate, policy_add_rule, rules_suggest, rule_notifications,
rules_explain, rules_simulate) plus a
switchbot://events resource for real-time shadow updates.
rules_suggest accepts an optional llm parameter (openai | anthropic | auto)
to generate YAML for complex intents via an LLM backend.
rule_notifications returns rule-notify audit entries, filterable by rule
name, time range, channel, and result.
rules_explain returns the decision trace for a specific evaluation (why a rule
fired or was blocked); rules_simulate replays historical events against a rule
and reports would-fire / blocked / throttled outcomes.
See docs/agent-guide.md for the full tool reference and safety rules (destructive-command guard).
switchbot doctor
switchbot doctor --jsonRuns local checks (Node version, credentials, profiles, catalog, catalog-schema, cache, quota, clock, MQTT, policy, MCP, keychain, path, inventory, audit, daemon, health, notify-connectivity, release-notes) and exits 1 if any check fails. warn results exit 0. The MQTT check reports ok when REST credentials are configured (auto-provisioned on first use). The notify-connectivity check probes webhook URLs declared in type: notify actions. Use this to diagnose connectivity or config issues before running automation.
--json output includes maturityScore (0–100) and maturityLabel (production-ready / mostly-ready / needs-work / not-ready) to give an at-a-glance readiness rating:
switchbot doctor --json | jq '{score: .data.maturityScore, label: .data.maturityLabel}'Pass --fix --yes to auto-apply safe fixes (e.g. clear stale cache entries) without a prompt.
# One-shot report: quota, audit error rate, circuit-breaker state
switchbot health check
switchbot health check --prometheus # Prometheus text format
switchbot health check --json
# Start a long-running HTTP server with /healthz and /metrics
switchbot health serve # default port 3100, bind 127.0.0.1
switchbot health serve --port 8080
switchbot health serve --json # print {"status":"listening",...} on start/healthz returns a JSON health report (HTTP 200 when ok/degraded, 503 when circuit is open).
/metrics returns Prometheus text metrics (switchbot_quota_used_total, switchbot_circuit_open, …).
Port conflicts are reported immediately with a clear hint to choose a different port via --port.
switchbot upgrade-check # exits 1 when update available
switchbot upgrade-check --json # {current, latest, upToDate, updateAvailable, breakingChange, installCommand}switchbot quota status # today's usage + last 7 days (10,000/day limit)
switchbot quota resetswitchbot history show --limit 20
switchbot history replay 7 # re-run entry #7
switchbot --json history show --limit 50 | jq '.entries[] | select(.result=="error")'switchbot catalog show # all built-in types
switchbot catalog show Bot # one type
switchbot catalog search Hub # fuzzy match
switchbot catalog diff # local overlay vs built-inCreate ~/.switchbot/catalog-overlay.json to extend or override type definitions without modifying the package.
switchbot schema export # all types
switchbot schema export --type 'Strip Light'
switchbot schema export --role sensorswitchbot capabilities --json
switchbot capabilities --used --json # only types seen in the local cachePrints a versioned manifest of surfaces, commands, and environment variables. Each command leaf includes {mutating, consumesQuota, agentSafetyTier, typicalLatencyMs}.
switchbot cache show # paths, age, entry counts
switchbot cache clear # clear everything
switchbot cache clear --key list # list cache only
switchbot cache clear --key status # status cache onlyswitchbot policy new # write a starter policy
switchbot policy validate # compiler-style errors (line:col + caret)
switchbot policy validate --json | jq '.data.errors'
switchbot policy migrate # upgrade v0.1 → v0.2 in-place
switchbot policy backup # timestamped backup
switchbot policy restore <backup-file>Path resolution: positional [path] > SWITCHBOT_POLICY_PATH > default. Exit codes: 0 valid / 1 invalid / 2 missing / 3 yaml-parse / 4 internal / 5 exists (use --force) / 6 unsupported version.
- Default — ANSI-colored tables for
list/status, key-value tables for details. --json— raw API payload passthrough. Errors are also JSON on stdout:{ "schemaVersion": "1.2", "error": { "code", "kind", "message", "hint?" } }.--format=json— projected row view;--fieldsapplies.--format=tsv|yaml|jsonl|id— tabular text formats.
switchbot devices list --json | jq '.deviceList[] | {id: .deviceId, name: .deviceName}'
switchbot devices list --format tsv --fields deviceId,deviceName,type,cloud
switchbot devices list --format id # one deviceId per lineTwo local disk caches under ~/.switchbot/:
| Cache | Default TTL | Purpose |
|---|---|---|
devices.json |
1 hour | device metadata; powers offline validation |
status.json |
off | per-device status; GC'd after 24h |
switchbot devices list --no-cache # bypass for one invocation
switchbot devices status <id> --cache 5m # set list + status TTL
switchbot devices status <id> --cache-list 2h --cache-status 30s0: Success (including--dry-runintercept when validation passes).1: Runtime error — API error, network failure, missing credentials.2: Usage error — bad flag, missing/invalid argument, unknown subcommand, unknown device type, invalid URL, conflicting flags.
Typical errors bubble up in the form Error: <message> on stderr. The
SwitchBot-specific error codes mapped to readable messages:
151: Device type error.152: Device not found.160: Command not supported by this device.161: Device offline (BLE devices need a Hub).171: Hub offline.190: Device internal error / server busy.401: Authentication failed (check token/secret).429: Request rate too high (10,000 req/day cap).
SWITCHBOT_TOKEN: API token — takes priority over the config file.SWITCHBOT_SECRET: API secret — takes priority over the config file.NO_COLOR: Disable ANSI colors in all output (automatically respected).
# Turn off every Bot device
switchbot devices list --json \
| jq -r '.deviceList[] | select(.deviceType == "Bot") | .deviceId' \
| while read id; do switchbot devices command "$id" turnOff; done
# Dump each scene as `<id> <name>`
switchbot scenes list --json | jq -r '.[] | "\(.sceneId) \(.sceneName)"'git clone https://github.com/OpenWonderLabs/switchbot-openapi-cli.git
cd switchbot-openapi-cli
npm install
npm run dev -- <args> # Run from TypeScript sources via tsx
npm run build # Compile to dist/
npm test # Run the Vitest suite (2225 tests)
npm run test:watch # Watch mode
npm run test:coverage # Coverage report (v8, HTML + text)Source layout: src/commands/ (one file per command group), src/devices/ (catalog + cache), src/rules/ (engine, matcher, throttle, audit), src/policy/ (validate, migrate, schema), src/llm/ (providers), src/utils/ (output, format, flags). Tests are in tests/ and mirror the src/ structure.
npm version patch # bump + create git tag
git push --follow-tags
# then: GitHub → Releases → Draft → PublishSee docs/release-pipeline.md for the full CI / publish verification flow.
MIT © chenliuyun
- SwitchBot API v1.1 documentation
- Base URL:
https://api.switch-bot.com - Rate limit: 10,000 requests/day per account