
Security News
/Research
Popular node-ipc npm Package Infected with Credential Stealer
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.
@switchbot/openapi-cli
Advanced tools
SwitchBot smart home CLI โ control devices, run scenes, stream real-time events, and integrate AI agents via MCP. Full API v1.1 coverage.
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.
@switchbot/openapi-cliLooking 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:
switchbot doctor self-check.--json, --format=tsv/yaml/id, --fields, stable exit codes,
history replay, and audit log support.docs/agent-guide.md.
You get switchbot 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.
/v1.1 endpoint (devices, scenes, webhooks)--json passthrough for jq and scripting0600; env-var override for CInpm install -g @switchbot/openapi-cli
This 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` globally
Verify:
switchbot --version
switchbot --help
The 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-run
Prefer 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-agent
See 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):
SWITCHBOT_TOKEN and SWITCHBOT_SECRETswitchbot auth keychain set~/.switchbot/config.json (written by config set-token, mode 0600)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 show
Prefer 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 get
Backends: 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:
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 error
Why 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 comments
The 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), event_count (rolling-window
counts over per-device history), 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, no type field 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 (only http:// and https:// schemes are accepted; rules lint rejects others)channel: file โ appends a JSONL line to a local file. to must be an absolute path; relative or ~-prefixed paths are rejected by rules lint (code notify-relative-path) and at runtimechannel: openclaw โ HTTP POST to an OpenClaw endpoint (same protocol restriction)template field 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 | local
cache_ttl: 5m
budget:
max_calls_per_hour: 20
max_tokens_per_hour: 100000 # optional rolling 1h token cap
max_cost_per_day_usd: 1.00 # optional rolling 24h USD cap
on_error: pass # fail | pass | skip
Set OPENAI_API_KEY or ANTHROPIC_API_KEY for the cloud providers.
For provider: local, point SWITCHBOT_LOCAL_LLM_URL at any
OpenAI-compatible /v1/chat/completions endpoint (Ollama, llama.cpp,
vLLM, LM Studio); SWITCHBOT_LOCAL_LLM_MODEL picks the model and
SWITCHBOT_LOCAL_LLM_TOOL_USE=1 opts into native tool-use when the
endpoint supports it (otherwise a structured-output fallback is used).
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 engine
LLM-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 example deviceId,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 (default 30000).--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 example 5m, 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 (default 3).--no-retry: Disable automatic 429 retries.--backoff <strategy>: Retry backoff: exponential (default) or linear.--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).
--dry-runIntercepts 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"}
config โ credential managementswitchbot 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)
devices โ list, status, control# 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 fields
Parameters 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.
devices expand โ named flags for packed parametersSome 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 4000
Run switchbot devices expand <id> <command> --help to see the available flags for any device command.
devices explain โ one-shot device summaryswitchbot devices explain <deviceId> # metadata + commands + live status
switchbot devices explain <deviceId> --no-live # catalog-only, no API call
devices meta โ local device metadataswitchbot 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.
devices batch โ bulk commands# 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 --yes
Filter keys: type, family, room, category. Skipped-offline devices appear under summary.skipped when --skip-offline is passed.
scenes โ run manual scenesswitchbot 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
webhook โ receive device events over HTTP# 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/hook
The CLI validates that <url> is an absolute http:// or https:// URL before calling the API. --enable and --disable are mutually exclusive.
events โ receive device eventsevents tail โ local webhook receiverswitchbot 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 --json
Run switchbot webhook setup https://your.host/hook first. events tail only runs the local receiver โ tunnelling (ngrok/cloudflared) is up to you.
events mqtt-tail โ real-time MQTT streamswitchbot 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 --json
Credentials 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.
status-sync โ MQTT/OpenClaw bridgeForwards 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 stop
Required: 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.
daemon โ background rules-engine processRuns 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 stop
Start 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.
completion โ shell tab-completion# 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 >> $PROFILE
Supported shells: bash, zsh, fish, powershell (pwsh is accepted as an alias).
plan โ declarative batch operations# 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-approval
A 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.
devices watch โ poll status# 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 5m
Output 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.
mcp โ Model Context Protocol server# Start the stdio MCP server (connect via Claude, Cursor, etc.)
switchbot mcp serve
Exposes 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).
doctor โ self-checkswitchbot doctor
switchbot doctor --json
Runs local checks (Node version, credentials, profiles, catalog, catalog-schema, catalog-coverage, cache, quota, clock, MQTT, policy, MCP, keychain, path, inventory, audit, daemon, daemon-ipc, health, notify-connectivity, local-llm-reachable, 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. daemon-ipc round-trips the JSON-RPC socket when the daemon is running (silently skipped otherwise); local-llm-reachable only fires when policy uses provider: local. 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.
health โ runtime health report# 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.
upgrade-check โ version checkswitchbot upgrade-check # exits 1 when update available
switchbot upgrade-check --json # {current, latest, upToDate, updateAvailable, breakingChange, installCommand}
quota โ API request counterswitchbot quota status # today's usage + last 7 days (10,000/day limit)
switchbot quota reset
history โ audit logswitchbot history show --limit 20
switchbot history replay 7 # re-run entry #7
switchbot --json history show --limit 50 | jq '.entries[] | select(.result=="error")'
catalog โ device type catalogswitchbot 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-in
Create ~/.switchbot/catalog-overlay.json to extend or override type definitions without modifying the package.
schema โ export catalog as JSONswitchbot schema export # all types
switchbot schema export --type 'Strip Light'
switchbot schema export --role sensor
capabilities โ CLI manifestswitchbot capabilities --json
switchbot capabilities --used --json # only types seen in the local cache
Prints a versioned manifest of surfaces, commands, and environment variables. Each command leaf includes {mutating, consumesQuota, agentSafetyTier, typicalLatencyMs}.
cache โ inspect and clear local cacheswitchbot 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 only
policy โ validate, scaffold, and migrate policy.yamlswitchbot 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.
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; --fields applies.--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 line
Two 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 30s
0: Success (including --dry-run intercept 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 (2465 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 โ Publish
See docs/release-pipeline.md for the full CI / publish verification flow.
MIT ยฉ chenliuyun
https://api.switch-bot.comFAQs
SwitchBot smart home CLI โ control devices, run scenes, stream real-time events, and integrate AI agents via MCP. Full API v1.1 coverage.
The npm package @switchbot/openapi-cli receives a total of 851 weekly downloads. As such, @switchbot/openapi-cli popularity was classified as not popular.
We found that @switchbot/openapi-cli demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.ย It has 4 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.

Security News
TeamPCP and BreachForums are promoting a Shai-Hulud supply chain attack contest with a $1,000 prize for the biggest package compromise.

Security News
Packagist urges PHP projects to update Composer after a GitHub token format change exposed some GitHub Actions tokens in CI logs.