@switchbot/openapi-cli 2.0.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +265 -39
- package/dist/commands/capabilities.js +37 -20
- package/dist/commands/devices.js +206 -66
- package/dist/commands/doctor.js +33 -0
- package/dist/commands/events.js +188 -1
- package/dist/commands/expand.js +20 -3
- package/dist/commands/mcp.js +59 -12
- package/dist/commands/plan.js +10 -2
- package/dist/commands/scenes.js +1 -1
- package/dist/commands/watch.js +13 -2
- package/dist/config.js +23 -0
- package/dist/index.js +5 -4
- package/dist/lib/devices.js +16 -1
- package/dist/mcp/device-history.js +66 -0
- package/dist/mcp/events-subscription.js +15 -12
- package/dist/mqtt/client.js +46 -50
- package/dist/mqtt/credential.js +29 -11
- package/dist/sinks/dispatcher.js +12 -0
- package/dist/sinks/file.js +19 -0
- package/dist/sinks/format.js +56 -0
- package/dist/sinks/homeassistant.js +44 -0
- package/dist/sinks/openclaw.js +33 -0
- package/dist/sinks/stdout.js +5 -0
- package/dist/sinks/telegram.js +28 -0
- package/dist/sinks/types.js +1 -0
- package/dist/sinks/webhook.js +22 -0
- package/dist/utils/flags.js +13 -12
- package/dist/utils/format.js +6 -5
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
[](https://github.com/OpenWonderLabs/switchbot-openapi-cli/actions/workflows/ci.yml)
|
|
8
8
|
|
|
9
9
|
Command-line interface for the [SwitchBot API v1.1](https://github.com/OpenWonderLabs/SwitchBotAPI).
|
|
10
|
-
List devices, query live status, send control commands, run scenes, and
|
|
10
|
+
List devices, query live status, send control commands, run scenes, receive real-time events, and connect AI agents via the built-in MCP server — all from your terminal or shell scripts.
|
|
11
11
|
|
|
12
12
|
- **npm package:** [`@switchbot/openapi-cli`](https://www.npmjs.com/package/@switchbot/openapi-cli)
|
|
13
13
|
- **Source code:** [github.com/OpenWonderLabs/switchbot-openapi-cli](https://github.com/OpenWonderLabs/switchbot-openapi-cli)
|
|
@@ -41,11 +41,19 @@ Under the hood every surface shares the same catalog, cache, and HMAC client —
|
|
|
41
41
|
- [Commands](#commands)
|
|
42
42
|
- [`config`](#config--credential-management)
|
|
43
43
|
- [`devices`](#devices--list-status-control)
|
|
44
|
+
- [`devices batch`](#devices-batch--bulk-commands)
|
|
45
|
+
- [`devices watch`](#devices-watch--poll-status)
|
|
44
46
|
- [`scenes`](#scenes--run-manual-scenes)
|
|
45
47
|
- [`webhook`](#webhook--receive-device-events-over-http)
|
|
46
|
-
- [`
|
|
47
|
-
- [`
|
|
48
|
+
- [`events`](#events--receive-device-events)
|
|
49
|
+
- [`plan`](#plan--declarative-batch-operations)
|
|
48
50
|
- [`mcp`](#mcp--model-context-protocol-server)
|
|
51
|
+
- [`doctor`](#doctor--self-check)
|
|
52
|
+
- [`quota`](#quota--api-request-counter)
|
|
53
|
+
- [`history`](#history--audit-log)
|
|
54
|
+
- [`catalog`](#catalog--device-type-catalog)
|
|
55
|
+
- [`schema`](#schema--export-catalog-as-json)
|
|
56
|
+
- [`capabilities`](#capabilities--cli-manifest)
|
|
49
57
|
- [`cache`](#cache--inspect-and-clear-local-cache)
|
|
50
58
|
- [`completion`](#completion--shell-tab-completion)
|
|
51
59
|
- [Output modes](#output-modes)
|
|
@@ -67,7 +75,7 @@ Under the hood every surface shares the same catalog, cache, and HMAC client —
|
|
|
67
75
|
- 🎨 **Dual output modes** — colorized tables by default; `--json` passthrough for `jq` and scripting
|
|
68
76
|
- 🔐 **Secure credentials** — HMAC-SHA256 signed requests; config file written with `0600`; env-var override for CI
|
|
69
77
|
- 🔍 **Dry-run mode** — preview every mutating request before it hits the API
|
|
70
|
-
- 🧪 **Fully tested** —
|
|
78
|
+
- 🧪 **Fully tested** — 692 Vitest tests, mocked axios, zero network in CI
|
|
71
79
|
- ⚡ **Shell completion** — Bash / Zsh / Fish / PowerShell
|
|
72
80
|
|
|
73
81
|
## Requirements
|
|
@@ -157,7 +165,8 @@ switchbot config show
|
|
|
157
165
|
| `--no-retry` | Disable automatic 429 retries |
|
|
158
166
|
| `--backoff <strategy>` | Retry backoff: `exponential` (default) or `linear` |
|
|
159
167
|
| `--no-quota` | Disable local request-quota tracking |
|
|
160
|
-
| `--audit-log
|
|
168
|
+
| `--audit-log` | Append mutating commands to a JSONL audit log (default path: `~/.switchbot/audit.log`) |
|
|
169
|
+
| `--audit-log-path <path>` | Custom audit log path; use together with `--audit-log` |
|
|
161
170
|
| `-V`, `--version` | Print the CLI version |
|
|
162
171
|
| `-h`, `--help` | Show help for any command or subcommand |
|
|
163
172
|
|
|
@@ -187,6 +196,7 @@ switchbot devices command ABC123 turnOn --dry-run
|
|
|
187
196
|
```bash
|
|
188
197
|
switchbot config set-token <token> <secret> # Save to ~/.switchbot/config.json
|
|
189
198
|
switchbot config show # Print current source + masked secret
|
|
199
|
+
switchbot config list-profiles # List saved profiles
|
|
190
200
|
```
|
|
191
201
|
|
|
192
202
|
### `devices` — list, status, control
|
|
@@ -203,6 +213,11 @@ switchbot devices list --json | jq '.deviceList[].deviceId'
|
|
|
203
213
|
# Physical: category = "physical"
|
|
204
214
|
switchbot devices list --format=tsv --fields=deviceId,type,category
|
|
205
215
|
|
|
216
|
+
# Filter devices by type / name / category / room (server-side filter keys)
|
|
217
|
+
switchbot devices list --filter category=physical
|
|
218
|
+
switchbot devices list --filter type=Bot
|
|
219
|
+
switchbot devices list --filter name=living,category=physical
|
|
220
|
+
|
|
206
221
|
# Filter by family / room (family & room info requires the 'src: OpenClaw'
|
|
207
222
|
# header, which this CLI sends on every request)
|
|
208
223
|
switchbot devices list --json | jq '.deviceList[] | select(.familyName == "Home")'
|
|
@@ -212,6 +227,16 @@ switchbot devices list --json | jq '[.deviceList[], .infraredRemoteList[]] | gro
|
|
|
212
227
|
switchbot devices status <deviceId>
|
|
213
228
|
switchbot devices status <deviceId> --json
|
|
214
229
|
|
|
230
|
+
# Resolve device by fuzzy name instead of ID (status, command, describe, expand, watch)
|
|
231
|
+
switchbot devices status --name "客厅空调"
|
|
232
|
+
switchbot devices command --name "Office Light" turnOn
|
|
233
|
+
switchbot devices describe --name "Kitchen Bot"
|
|
234
|
+
|
|
235
|
+
# Batch status across multiple devices
|
|
236
|
+
switchbot devices status --ids ABC,DEF,GHI
|
|
237
|
+
switchbot devices status --ids ABC,DEF --fields power,battery # only show specific fields
|
|
238
|
+
switchbot devices status --ids ABC,DEF --format jsonl # one JSON line per device
|
|
239
|
+
|
|
215
240
|
# Send a control command
|
|
216
241
|
switchbot devices command <deviceId> <cmd> [parameter] [--type command|customize]
|
|
217
242
|
|
|
@@ -220,7 +245,7 @@ switchbot devices describe <deviceId>
|
|
|
220
245
|
switchbot devices describe <deviceId> --json
|
|
221
246
|
|
|
222
247
|
# Discover what's supported (offline reference, no API call)
|
|
223
|
-
switchbot devices types # List all device types + IR remote types
|
|
248
|
+
switchbot devices types # List all device types + IR remote types (incl. role column)
|
|
224
249
|
switchbot devices commands <type> # Show commands, parameter formats, and status fields
|
|
225
250
|
switchbot devices commands Bot
|
|
226
251
|
switchbot devices commands "Smart Lock"
|
|
@@ -259,6 +284,8 @@ Some commands require a packed string like `"26,2,2,on"`. `devices expand` build
|
|
|
259
284
|
```bash
|
|
260
285
|
# Air Conditioner — setAll
|
|
261
286
|
switchbot devices expand <acId> setAll --temp 26 --mode cool --fan low --power on
|
|
287
|
+
# Resolve by name
|
|
288
|
+
switchbot devices expand --name "客厅空调" setAll --temp 26 --mode cool --fan low --power on
|
|
262
289
|
|
|
263
290
|
# Curtain / Roller Shade — setPosition
|
|
264
291
|
switchbot devices expand <curtainId> setPosition --position 50 --mode silent
|
|
@@ -272,13 +299,48 @@ switchbot devices expand <relayId> setMode --channel 1 --mode edge
|
|
|
272
299
|
|
|
273
300
|
Run `switchbot devices expand <id> <command> --help` to see the available flags for any device command.
|
|
274
301
|
|
|
275
|
-
#### `devices explain` —
|
|
302
|
+
#### `devices explain` — one-shot device summary
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
# Metadata + supported commands + live status in one call
|
|
306
|
+
switchbot devices explain <deviceId>
|
|
307
|
+
|
|
308
|
+
# Skip live status fetch (catalog-only output, no API call)
|
|
309
|
+
switchbot devices explain <deviceId> --no-live
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Returns a combined view: static catalog info (commands, parameters, status fields) merged with the current live status. For Hub devices, also lists connected child devices. Prefer this over separate `status` + `describe` calls.
|
|
313
|
+
|
|
314
|
+
#### `devices meta` — local device metadata
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
switchbot devices meta set <deviceId> --alias "Office Light"
|
|
318
|
+
switchbot devices meta set <deviceId> --hide # hide from `devices list`
|
|
319
|
+
switchbot devices meta get <deviceId>
|
|
320
|
+
switchbot devices meta list # show all saved metadata
|
|
321
|
+
switchbot devices meta clear <deviceId>
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
Stores local annotations (alias, hidden flag, notes) in `~/.switchbot/device-meta.json`. The alias is used as a display name; `--show-hidden` on `devices list` reveals hidden devices.
|
|
325
|
+
|
|
326
|
+
#### `devices batch` — bulk commands
|
|
276
327
|
|
|
277
328
|
```bash
|
|
278
|
-
|
|
329
|
+
# Send the same command to every device matching a filter
|
|
330
|
+
switchbot devices batch turnOff --filter 'type=Bot'
|
|
331
|
+
switchbot devices batch setBrightness 50 --filter 'type~=Light,family=Living'
|
|
332
|
+
|
|
333
|
+
# Explicit device IDs (comma-separated)
|
|
334
|
+
switchbot devices batch turnOn --ids ID1,ID2,ID3
|
|
335
|
+
|
|
336
|
+
# Pipe device IDs from `devices list`
|
|
337
|
+
switchbot devices list --format=id --filter 'type=Bot' | switchbot devices batch toggle -
|
|
338
|
+
|
|
339
|
+
# Destructive commands require --yes
|
|
340
|
+
switchbot devices batch unlock --filter 'type=Smart Lock' --yes
|
|
279
341
|
```
|
|
280
342
|
|
|
281
|
-
|
|
343
|
+
Sends the same command to many devices in one run. Uses the same `--filter` expressions as `devices list`. Destructive commands (Smart Lock unlock, Garage Door Opener, etc.) require `--yes` to prevent accidents.
|
|
282
344
|
|
|
283
345
|
### `scenes` — run manual scenes
|
|
284
346
|
|
|
@@ -307,6 +369,101 @@ switchbot webhook delete https://your.host/hook
|
|
|
307
369
|
|
|
308
370
|
The CLI validates that `<url>` is an absolute `http://` or `https://` URL before calling the API. `--enable` and `--disable` are mutually exclusive.
|
|
309
371
|
|
|
372
|
+
### `events` — receive device events
|
|
373
|
+
|
|
374
|
+
Two subcommands cover the two ways SwitchBot can push state changes to you.
|
|
375
|
+
|
|
376
|
+
#### `events tail` — local webhook receiver
|
|
377
|
+
|
|
378
|
+
```bash
|
|
379
|
+
# Listen on port 3000 and print every incoming webhook POST
|
|
380
|
+
switchbot events tail
|
|
381
|
+
|
|
382
|
+
# Filter to one device
|
|
383
|
+
switchbot events tail --filter deviceId=ABC123
|
|
384
|
+
|
|
385
|
+
# Stop after 5 matching events
|
|
386
|
+
switchbot events tail --filter 'type=WoMeter' --max 5
|
|
387
|
+
|
|
388
|
+
# Custom port / path
|
|
389
|
+
switchbot events tail --port 8080 --path /hook --json
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Run `switchbot webhook setup https://your.host/hook` first to tell SwitchBot where to send events, then expose the local port via ngrok/cloudflared and point the webhook URL at it. `events tail` only runs the local receiver — tunnelling is up to you.
|
|
393
|
+
|
|
394
|
+
Output (one JSON line per matched event):
|
|
395
|
+
```
|
|
396
|
+
{ "t": "2024-01-01T12:00:00.000Z", "remote": "1.2.3.4:54321", "path": "/", "body": {...}, "matched": true }
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Filter keys: `deviceId=<id>`, `type=<deviceType>` (comma-separated for AND logic).
|
|
400
|
+
|
|
401
|
+
#### `events mqtt-tail` — real-time MQTT stream
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
# Stream all shadow-update events (runs in foreground until Ctrl-C)
|
|
405
|
+
switchbot events mqtt-tail
|
|
406
|
+
|
|
407
|
+
# Filter to a topic subtree
|
|
408
|
+
switchbot events mqtt-tail --topic 'switchbot/#'
|
|
409
|
+
|
|
410
|
+
# Stop after 10 events
|
|
411
|
+
switchbot events mqtt-tail --max 10 --json
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Connects to the SwitchBot MQTT service automatically using the same credentials configured for the REST API (`SWITCHBOT_TOKEN` + `SWITCHBOT_SECRET`). No additional MQTT configuration is required — the client certificates are provisioned on first use.
|
|
415
|
+
|
|
416
|
+
Output (one JSON line per message):
|
|
417
|
+
```
|
|
418
|
+
{ "t": "2024-01-01T12:00:00.000Z", "topic": "switchbot/abc123/status", "payload": {...} }
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
This command runs in the foreground and streams events until you press Ctrl-C. To run it persistently in the background, use a process manager:
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
# pm2
|
|
425
|
+
pm2 start "switchbot events mqtt-tail --json" --name switchbot-events
|
|
426
|
+
|
|
427
|
+
# nohup
|
|
428
|
+
nohup switchbot events mqtt-tail --json >> ~/switchbot-events.log 2>&1 &
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
Run `switchbot doctor` to verify MQTT credentials are configured correctly before connecting.
|
|
432
|
+
|
|
433
|
+
#### `mqtt-tail` sinks — route events to external services
|
|
434
|
+
|
|
435
|
+
By default `mqtt-tail` prints JSONL to stdout. Use `--sink` (repeatable) to route events to one or more destinations instead:
|
|
436
|
+
|
|
437
|
+
| Sink | Required flags |
|
|
438
|
+
|---|---|
|
|
439
|
+
| `stdout` | (default when no `--sink` given) |
|
|
440
|
+
| `file` | `--sink-file <path>` — append JSONL |
|
|
441
|
+
| `webhook` | `--webhook-url <url>` — HTTP POST each event |
|
|
442
|
+
| `openclaw` | `--openclaw-url`, `--openclaw-token` (or `$OPENCLAW_TOKEN`), `--openclaw-model` |
|
|
443
|
+
| `telegram` | `--telegram-token` (or `$TELEGRAM_TOKEN`), `--telegram-chat <chatId>` |
|
|
444
|
+
| `homeassistant` | `--ha-url <url>` + `--ha-webhook-id` (no auth) or `--ha-token` (REST event API) |
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
# Push events to an OpenClaw agent (replaces the SwitchBot channel plugin)
|
|
448
|
+
switchbot events mqtt-tail \
|
|
449
|
+
--sink openclaw \
|
|
450
|
+
--openclaw-token <token> \
|
|
451
|
+
--openclaw-model my-home-agent
|
|
452
|
+
|
|
453
|
+
# Write to file + push to OpenClaw simultaneously
|
|
454
|
+
switchbot events mqtt-tail \
|
|
455
|
+
--sink file --sink-file ~/.switchbot/events.jsonl \
|
|
456
|
+
--sink openclaw --openclaw-token <token> --openclaw-model home
|
|
457
|
+
|
|
458
|
+
# Generic webhook (n8n, Make, etc.)
|
|
459
|
+
switchbot events mqtt-tail --sink webhook --webhook-url https://n8n.local/hook/abc
|
|
460
|
+
|
|
461
|
+
# Forward to Home Assistant via webhook trigger
|
|
462
|
+
switchbot events mqtt-tail --sink homeassistant --ha-url http://homeassistant.local:8123 --ha-webhook-id switchbot
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Device state is also persisted to `~/.switchbot/device-history/<deviceId>.json` (latest + 100-entry ring buffer) regardless of sink configuration. This enables the `get_device_history` MCP tool to answer state queries without an API call.
|
|
466
|
+
|
|
310
467
|
### `completion` — shell tab-completion
|
|
311
468
|
|
|
312
469
|
```bash
|
|
@@ -325,28 +482,36 @@ switchbot completion powershell >> $PROFILE
|
|
|
325
482
|
|
|
326
483
|
Supported shells: `bash`, `zsh`, `fish`, `powershell` (`pwsh` is accepted as an alias).
|
|
327
484
|
|
|
328
|
-
### `
|
|
485
|
+
### `plan` — declarative batch operations
|
|
329
486
|
|
|
330
487
|
```bash
|
|
331
|
-
#
|
|
332
|
-
switchbot
|
|
333
|
-
|
|
488
|
+
# Print the plan JSON Schema (give to your agent framework)
|
|
489
|
+
switchbot plan schema
|
|
490
|
+
|
|
491
|
+
# Validate a plan file without running it
|
|
492
|
+
switchbot plan validate plan.json
|
|
334
493
|
|
|
335
|
-
#
|
|
336
|
-
switchbot
|
|
494
|
+
# Preview — mutations skipped, GETs still execute
|
|
495
|
+
switchbot --dry-run plan run plan.json
|
|
496
|
+
|
|
497
|
+
# Run — pass --yes to allow destructive steps
|
|
498
|
+
switchbot plan run plan.json --yes
|
|
499
|
+
switchbot plan run plan.json --continue-on-error
|
|
337
500
|
```
|
|
338
501
|
|
|
339
|
-
A
|
|
502
|
+
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. See [`docs/agent-guide.md`](./docs/agent-guide.md) for the full schema and agent integration patterns.
|
|
340
503
|
|
|
341
|
-
### `watch` — poll
|
|
504
|
+
### `devices watch` — poll status
|
|
342
505
|
|
|
343
506
|
```bash
|
|
344
507
|
# Poll a device's status every 30 s until Ctrl-C
|
|
345
|
-
switchbot watch <deviceId>
|
|
346
|
-
|
|
508
|
+
switchbot devices watch <deviceId>
|
|
509
|
+
|
|
510
|
+
# Custom interval; emit every tick even when nothing changed
|
|
511
|
+
switchbot devices watch <deviceId> --interval 10s --include-unchanged --json
|
|
347
512
|
```
|
|
348
513
|
|
|
349
|
-
Output is a stream of
|
|
514
|
+
Output is a JSONL stream of status-change events (with `--json`) or a refreshed table. Use `--max <n>` to stop after N ticks.
|
|
350
515
|
|
|
351
516
|
### `mcp` — Model Context Protocol server
|
|
352
517
|
|
|
@@ -358,6 +523,65 @@ switchbot mcp serve
|
|
|
358
523
|
Exposes 8 MCP tools (`list_devices`, `describe_device`, `get_device_status`, `send_command`, `list_scenes`, `run_scene`, `search_catalog`, `account_overview`) plus a `switchbot://events` resource for real-time shadow updates.
|
|
359
524
|
See [`docs/agent-guide.md`](./docs/agent-guide.md) for the full tool reference and safety rules (destructive-command guard).
|
|
360
525
|
|
|
526
|
+
### `doctor` — self-check
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
switchbot doctor
|
|
530
|
+
switchbot doctor --json
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Runs 8 local checks (Node version, credentials, profiles, catalog, cache, quota file, clock, MQTT) 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). Use this to diagnose connectivity or config issues before running automation.
|
|
534
|
+
|
|
535
|
+
### `quota` — API request counter
|
|
536
|
+
|
|
537
|
+
```bash
|
|
538
|
+
switchbot quota status # today's usage + last 7 days
|
|
539
|
+
switchbot quota reset # delete the counter file
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Tracks daily API calls against the 10,000/day account limit. The counter is stored in `~/.switchbot/quota.json` and incremented on every mutating request. Pass `--no-quota` to skip tracking for a single run.
|
|
543
|
+
|
|
544
|
+
### `history` — audit log
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
switchbot history show # recent entries (newest first)
|
|
548
|
+
switchbot history show --limit 20 # last 20 entries
|
|
549
|
+
switchbot history replay 7 # re-run entry #7
|
|
550
|
+
switchbot --json history show --limit 50 | jq '.entries[] | select(.result=="error")'
|
|
551
|
+
```
|
|
552
|
+
|
|
553
|
+
Reads the JSONL audit log (`~/.switchbot/audit.log` by default; override with `--audit-log --audit-log-path <path>`). Each entry records the timestamp, command, device ID, result, and dry-run flag. `replay` re-runs the original command with the original arguments.
|
|
554
|
+
|
|
555
|
+
### `catalog` — device type catalog
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
switchbot catalog show # all 42 built-in types
|
|
559
|
+
switchbot catalog show Bot # one type
|
|
560
|
+
switchbot catalog diff # what a local overlay changes vs built-in
|
|
561
|
+
switchbot catalog path # location of the local overlay file
|
|
562
|
+
switchbot catalog refresh # reload local overlay (clears in-process cache)
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
The built-in catalog ships with the package. Create `~/.switchbot/catalog-overlay.json` to add, extend, or override type definitions without modifying the package.
|
|
566
|
+
|
|
567
|
+
### `schema` — export catalog as JSON
|
|
568
|
+
|
|
569
|
+
```bash
|
|
570
|
+
switchbot schema export # all types as structured JSON
|
|
571
|
+
switchbot schema export --type 'Strip Light' # one type
|
|
572
|
+
switchbot schema export --role sensor # filter by role
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
Exports the effective catalog in a machine-readable format. Pipe the output into an agent's system prompt or tool schema to give it a complete picture of controllable devices.
|
|
576
|
+
|
|
577
|
+
### `capabilities` — CLI manifest
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
switchbot capabilities --json
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
Prints a versioned JSON manifest describing available surfaces (CLI, MCP, MQTT, plan runner), commands, and environment variables. Designed for agents and tooling that need to discover the CLI's capabilities programmatically.
|
|
584
|
+
|
|
361
585
|
### `cache` — inspect and clear local cache
|
|
362
586
|
|
|
363
587
|
```bash
|
|
@@ -457,11 +681,11 @@ Typical errors bubble up in the form `Error: <message>` on stderr. The SwitchBot
|
|
|
457
681
|
|
|
458
682
|
## Environment variables
|
|
459
683
|
|
|
460
|
-
| Variable
|
|
461
|
-
|
|
|
462
|
-
| `SWITCHBOT_TOKEN`
|
|
463
|
-
| `SWITCHBOT_SECRET`
|
|
464
|
-
| `NO_COLOR`
|
|
684
|
+
| Variable | Description |
|
|
685
|
+
| --------------------------- | ------------------------------------------------------------------ |
|
|
686
|
+
| `SWITCHBOT_TOKEN` | API token — takes priority over the config file |
|
|
687
|
+
| `SWITCHBOT_SECRET` | API secret — takes priority over the config file |
|
|
688
|
+
| `NO_COLOR` | Disable ANSI colors in all output (automatically respected) |
|
|
465
689
|
|
|
466
690
|
## Scripting examples
|
|
467
691
|
|
|
@@ -484,7 +708,7 @@ npm install
|
|
|
484
708
|
|
|
485
709
|
npm run dev -- <args> # Run from TypeScript sources via tsx
|
|
486
710
|
npm run build # Compile to dist/
|
|
487
|
-
npm test # Run the Vitest suite (
|
|
711
|
+
npm test # Run the Vitest suite (692 tests)
|
|
488
712
|
npm run test:watch # Watch mode
|
|
489
713
|
npm run test:coverage # Coverage report (v8, HTML + text)
|
|
490
714
|
```
|
|
@@ -506,21 +730,23 @@ src/
|
|
|
506
730
|
├── commands/
|
|
507
731
|
│ ├── config.ts
|
|
508
732
|
│ ├── devices.ts
|
|
733
|
+
│ ├── expand.ts # `devices expand` — semantic flag builder
|
|
734
|
+
│ ├── explain.ts # `devices explain` — one-shot device summary
|
|
735
|
+
│ ├── device-meta.ts # `devices meta` — local aliases / hide flags
|
|
509
736
|
│ ├── scenes.ts
|
|
510
737
|
│ ├── webhook.ts
|
|
511
|
-
│ ├──
|
|
512
|
-
│ ├──
|
|
513
|
-
│ ├── mcp.ts # `
|
|
514
|
-
│ ├──
|
|
515
|
-
│ ├──
|
|
516
|
-
│ ├──
|
|
517
|
-
│ ├── quota.ts # `
|
|
518
|
-
│ ├──
|
|
519
|
-
│ ├──
|
|
520
|
-
│ ├── doctor.ts # `
|
|
521
|
-
│ ├──
|
|
522
|
-
│
|
|
523
|
-
│ └── completion.ts # `switchbot completion bash|zsh|fish|powershell`
|
|
738
|
+
│ ├── watch.ts # `devices watch <deviceId>`
|
|
739
|
+
│ ├── events.ts # `events tail` / `events mqtt-tail`
|
|
740
|
+
│ ├── mcp.ts # `mcp serve` (MCP stdio/HTTP server)
|
|
741
|
+
│ ├── plan.ts # `plan run/validate`
|
|
742
|
+
│ ├── cache.ts # `cache show/clear`
|
|
743
|
+
│ ├── history.ts # `history show/replay`
|
|
744
|
+
│ ├── quota.ts # `quota status/reset`
|
|
745
|
+
│ ├── catalog.ts # `catalog show/diff/path`
|
|
746
|
+
│ ├── schema.ts # `schema export`
|
|
747
|
+
│ ├── doctor.ts # `doctor`
|
|
748
|
+
│ ├── capabilities.ts # `capabilities`
|
|
749
|
+
│ └── completion.ts # `completion bash|zsh|fish|powershell`
|
|
524
750
|
└── utils/
|
|
525
751
|
├── flags.ts # Global flag readers (isVerbose / isDryRun / getCacheMode / …)
|
|
526
752
|
├── output.ts # printTable / printKeyValue / printJson / handleError / buildErrorPayload
|
|
@@ -26,32 +26,42 @@ const MCP_TOOLS = [
|
|
|
26
26
|
'run_scene',
|
|
27
27
|
'search_catalog',
|
|
28
28
|
'account_overview',
|
|
29
|
+
'get_device_history',
|
|
29
30
|
];
|
|
30
31
|
export function registerCapabilitiesCommand(program) {
|
|
31
32
|
program
|
|
32
33
|
.command('capabilities')
|
|
33
34
|
.description('Print a machine-readable manifest of CLI capabilities (for agent bootstrap)')
|
|
34
|
-
.
|
|
35
|
+
.option('--minimal', 'Omit per-subcommand flag details to reduce output size')
|
|
36
|
+
.action((opts) => {
|
|
35
37
|
const catalog = getEffectiveCatalog();
|
|
36
|
-
const
|
|
37
|
-
.
|
|
38
|
-
|
|
39
|
-
name:
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
38
|
+
const allCommands = [
|
|
39
|
+
...program.commands,
|
|
40
|
+
// Commander adds 'help' implicitly; include it explicitly so it appears in the manifest
|
|
41
|
+
{ name: () => 'help', description: () => 'Display help for a command', commands: [], options: [], registeredArguments: [] },
|
|
42
|
+
];
|
|
43
|
+
const commands = allCommands.map((c) => {
|
|
44
|
+
const entry = {
|
|
45
|
+
name: c.name(),
|
|
46
|
+
description: c.description(),
|
|
47
|
+
};
|
|
48
|
+
if (!opts.minimal) {
|
|
49
|
+
entry.subcommands = c.commands.map((s) => ({
|
|
50
|
+
name: s.name(),
|
|
51
|
+
description: s.description(),
|
|
52
|
+
args: s.registeredArguments.map((a) => ({
|
|
53
|
+
name: a.name(),
|
|
54
|
+
required: a.required,
|
|
55
|
+
variadic: a.variadic,
|
|
56
|
+
})),
|
|
57
|
+
flags: s.options.map((o) => ({
|
|
58
|
+
flags: o.flags,
|
|
59
|
+
description: o.description,
|
|
60
|
+
})),
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
return entry;
|
|
64
|
+
});
|
|
55
65
|
const globalFlags = program.options.map((opt) => ({
|
|
56
66
|
flags: opt.flags,
|
|
57
67
|
description: opt.description,
|
|
@@ -68,6 +78,13 @@ export function registerCapabilitiesCommand(program) {
|
|
|
68
78
|
tools: MCP_TOOLS,
|
|
69
79
|
resources: ['switchbot://events'],
|
|
70
80
|
},
|
|
81
|
+
mqtt: {
|
|
82
|
+
mode: 'consumer',
|
|
83
|
+
authSource: 'SWITCHBOT_TOKEN + SWITCHBOT_SECRET (auto-provisioned via POST /v1.1/iot/credential)',
|
|
84
|
+
cliCmd: 'events mqtt-tail',
|
|
85
|
+
mcpResource: 'switchbot://events',
|
|
86
|
+
protocol: 'MQTTS with TLS client certificates (AWS IoT)',
|
|
87
|
+
},
|
|
71
88
|
plan: {
|
|
72
89
|
schemaCmd: 'plan schema',
|
|
73
90
|
validateCmd: 'plan validate -',
|