SwitchBot skill
Drive the user's SwitchBot smart home through the switchbot CLI. Always query the CLI for ground truth — never guess commands, deviceIds, or parameter values.
Authority chain
| Question | Authoritative command |
|---|---|
| What can I do (cold start)? | switchbot agent-bootstrap --compact --json |
| What commands exist? | switchbot capabilities --json |
| What flags does this command take? | switchbot <cmd> --help --json |
| What devices does the user have? | switchbot devices list --json |
| What's this device doing right now? | switchbot devices status <id> --json |
| What can I do with this specific device type? | switchbot devices describe <id> --json |
| What scenes are configured? | switchbot scenes list --json |
| What's on the user's AI MindClip (recordings, todos, daily/weekly summaries)? | mindclip_recordings (action: list/get/summary), mindclip_list_todos, mindclip_recall (period: daily/weekly/urgent_todos) MCP tools |
What's in the user's policy.yaml? |
cat ~/.config/openclaw/switchbot/policy.yaml |
| Is my quota OK? | switchbot quota status --json |
| Is the setup healthy? | switchbot doctor --json |
| What automation rules are configured? | switchbot rules list --json |
| Are the rules valid? | switchbot rules lint |
| Draft an execution plan from intent | switchbot plan suggest --intent "..." --device <id> |
| Run a plan with per-step approval | switchbot plan run <file> --require-approval |
| Draft an automation rule from intent | switchbot rules suggest --intent "..." --device <id> |
| Inject a rule into policy.yaml | switchbot policy add-rule [--dry-run] [--enable] (reads YAML from stdin) |
Network requirements
Claude Code registers the SwitchBot MCP server via claude mcp add switchbot -- switchbot mcp serve — or via .mcp.json in managed environments. The default profile exposes 17 tools (read + action); add --tools all to also expose admin tools (policy, audit, rules — 28 total, including 25 canonical tools + 3 deprecated device_history aliases). No manual setup is required once the MCP server is registered. The MCP server needs outbound HTTPS to api.switch-bot.com. If connection errors appear, see references/claude-code-network.md.
Bootstrap (cold start)
On skill load, silently call the account_overview MCP tool. This returns device inventory, scene list, quota status, and MQTT connection state in one call — zero quota cost for cached data, no bash required, not blocked by auto-mode classifiers.
account_overview → devices[], scenes[], quota, mqttConnected
If account_overview returns stale devices (user just added one), call list_devices MCP tool to refresh.
Only fall back to bash when MCP tools are unavailable:
switchbot agent-bootstrap --compact --json
The response contains: cliVersion, safetyTiers, nameStrategies, profile, quota, devices[] (cached, with deviceId/type/name/category/roomName), catalog, and hints[].
Then read the user's policy:
cat ~/.config/openclaw/switchbot/policy.yaml 2>/dev/null
If the file doesn't exist, proceed with default safety tiers and tell the user once they can create one with switchbot policy new.
Resolving a name to a device
When the user says "bedroom light", resolve in this order:
- alias —
policy.yamlalias map →<deviceId>. Most reliable. - exact — device
name == "bedroom light"(case-insensitive). - prefix — name starts with the phrase.
- substring — name contains the phrase.
- fuzzy — Levenshtein distance ≤ 2.
- require-unique — multiple matches at same tier → stop and ask. Never pick silently.
Safety gates
| Tier | Examples | Behaviour |
|---|---|---|
read |
status, list, quota | Run freely. |
ir-fire-forget |
IR power/AC/TV via Hub | Run; warn there is no device-side confirmation. |
mutation |
turnOn/Off, setBrightness, setColor | Run. Append to audit log. |
destructive |
lock, unlock, delete scenes/webhooks | Refuse by default. Confirm explicitly; prefer --dry-run first. |
maintenance |
(reserved) | Always confirm. |
Policy overrides: confirmations.always_confirm forces confirmation; confirmations.never_confirm pre-approves (never add destructive actions). quiet_hours requires confirmation even for mutation.
Policy compliance
- Call
policy_validate(withlive: true) once per device-control session. - Honour
quiet_hours,always_confirm, andnever_confirmfrom the validated policy. - No policy file → proceed with default tiers.
Never write to policy.yaml without showing a diff and getting explicit approval.
Audit logging
Use audit_query and audit_stats MCP tools to review past activity. For a full audit trail with CLI, use switchbot --audit-log devices command <id> <cmd>.
Output modes
Always use --json when parsing output. Use --format=markdown for user-facing summaries. Never parse markdown or human tables programmatically — re-run with --json.
Credentials
First-time login: switchbot auth login (opens browser). Headless: add --no-open. Inspect the active keychain backend: switchbot auth keychain describe --json. Reset cache without touching credentials: switchbot reset [--all]. Never run auth login or auth keychain set on the user's behalf.
Declarative automations (CLI ≥ 3.7.1)
When the user wants "when X, do Y", author a rule in policy.yaml instead of a shell loop. Check schema version first (head -1 policy.yaml, must be "0.2"; if "0.1" run switchbot policy migrate).
Start with dry_run: true:
automation:
enabled: true
rules:
- name: "hallway motion at night"
when: { source: mqtt, event: motion.detected, device: "hallway sensor" }
conditions:
- time_between: ["22:00", "07:00"]
then:
- { command: "devices command <id> turnOn", device: "hallway lamp" }
throttle: { max_per: "10m" }
dry_run: true
Trigger kinds: source: mqtt (shadow events), source: cron (schedule + optional days:), source: webhook (bearer-token HTTP). Conditions: time_between, {device, field, op, value}, all:, any:, not:.
The validator rejects any rule with a destructive action in then[]. Always start dry, confirm firings via switchbot rules tail --follow, then remove dry_run.
switchbot policy validate
switchbot rules lint && switchbot rules reload
Semi-autonomous workflow — plan suggest + --require-approval
switchbot plan suggest --intent "turn off all lights" --device <id1> --device <id2>
# Review/edit the generated JSON
switchbot plan run plan.json --require-approval
Non-destructive steps run automatically; destructive steps prompt once. Via MCP: call plan_suggest, then have the user run --require-approval in a TTY session.
Common pitfalls
- Don't parse help text. Always
--help --json. - Don't rely on
--namepicking one hit. Resolve the name yourself; passdeviceIddirectly. - Check
commands[]before calling a command.switchbot devices describe <id> --json— not every device supports every command. - Quota counts attempts, not successes. Above 80%, slow down and batch.
--jsonenvelope — every response is{"schemaVersion":"1.1","data":...}or{"error":{...}}. Read.data, check.errorfirst. Parsers that read top-level fields silently getundefined.
Error handling
{ "error": { "kind": "usage|auth|quota|network|upstream|internal", "message": "...", "hint": "..." } }
usage→ you called something wrong; re-read help and retry.auth→ runswitchbot doctor --section credentials.quota→ stop; resets at midnight UTC.network→ retry once, then surface.upstream→ relay verbatim.internal→ ask user to runswitchbot doctor --jsonand file an issue.
Never retry destructive actions automatically. For mutation retries, use a local fingerprint {deviceId, command, args, minute-bucket} as an idempotency gate.
Things to never do
- Ask the user for their SwitchBot token or secret.
- Suggest flags that bypass safety tiers (
--skip-confirmation,--force) unless the user named them explicitly. - Claim IR actions "succeeded" — IR is open-loop; say the signal was sent.
- Write to
policy.yamlwithout showing a diff and getting explicit approval. - Generate a rule with a destructive command in
then[]. - Arm a rule (
dry_run: false) on first author without the user confirming firings. - Set
automation.enabled: truewithout explicitly informing the user. - Run
switchbot doctor --fix --yeswithout the user asking.
Version
Targets @switchbot/openapi-cli ≥ 3.7.1. If switchbot --version is older: npm update -g @switchbot/openapi-cli.
Source: OpenWonderLabs/switchbot-openapi-cli — distributed by TomeVault.