@switchbot/openapi-cli 2.6.4 → 3.0.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 +385 -103
- package/dist/api/client.js +13 -12
- package/dist/commands/agent-bootstrap.js +67 -16
- package/dist/commands/auth.js +354 -0
- package/dist/commands/batch.js +26 -21
- package/dist/commands/capabilities.js +29 -21
- package/dist/commands/catalog.js +4 -3
- package/dist/commands/config.js +57 -37
- package/dist/commands/devices.js +63 -37
- package/dist/commands/doctor.js +539 -26
- package/dist/commands/events.js +115 -26
- package/dist/commands/expand.js +7 -15
- package/dist/commands/explain.js +10 -7
- package/dist/commands/history.js +12 -18
- package/dist/commands/identity.js +59 -0
- package/dist/commands/install.js +246 -0
- package/dist/commands/mcp.js +895 -15
- package/dist/commands/plan.js +111 -15
- package/dist/commands/policy.js +469 -0
- package/dist/commands/rules.js +657 -0
- package/dist/commands/schema.js +20 -12
- package/dist/commands/status-sync.js +131 -0
- package/dist/commands/uninstall.js +237 -0
- package/dist/commands/watch.js +15 -2
- package/dist/config.js +14 -0
- package/dist/credentials/backends/file.js +101 -0
- package/dist/credentials/backends/linux.js +129 -0
- package/dist/credentials/backends/macos.js +129 -0
- package/dist/credentials/backends/windows.js +215 -0
- package/dist/credentials/keychain.js +88 -0
- package/dist/credentials/prime.js +52 -0
- package/dist/devices/catalog.js +118 -11
- package/dist/devices/resources.js +270 -0
- package/dist/index.js +39 -4
- package/dist/install/default-steps.js +257 -0
- package/dist/install/preflight.js +212 -0
- package/dist/install/steps.js +67 -0
- package/dist/lib/command-keywords.js +17 -0
- package/dist/lib/devices.js +15 -5
- package/dist/policy/add-rule.js +124 -0
- package/dist/policy/diff.js +91 -0
- package/dist/policy/examples/policy.example.yaml +99 -0
- package/dist/policy/format.js +57 -0
- package/dist/policy/load.js +61 -0
- package/dist/policy/migrate.js +67 -0
- package/dist/policy/schema/v0.2.json +302 -0
- package/dist/policy/schema.js +18 -0
- package/dist/policy/validate.js +262 -0
- package/dist/rules/action.js +205 -0
- package/dist/rules/audit-query.js +89 -0
- package/dist/rules/cron-scheduler.js +186 -0
- package/dist/rules/destructive.js +52 -0
- package/dist/rules/engine.js +567 -0
- package/dist/rules/matcher.js +230 -0
- package/dist/rules/pid-file.js +95 -0
- package/dist/rules/quiet-hours.js +45 -0
- package/dist/rules/suggest.js +95 -0
- package/dist/rules/throttle.js +78 -0
- package/dist/rules/types.js +34 -0
- package/dist/rules/webhook-listener.js +223 -0
- package/dist/rules/webhook-token.js +90 -0
- package/dist/schema/field-aliases.js +95 -0
- package/dist/status-sync/manager.js +268 -0
- package/dist/utils/audit.js +12 -2
- package/dist/utils/help-json.js +54 -0
- package/dist/utils/output.js +17 -0
- package/package.json +12 -4
package/README.md
CHANGED
|
@@ -6,25 +6,38 @@
|
|
|
6
6
|
[](https://nodejs.org)
|
|
7
7
|
[](https://github.com/OpenWonderLabs/switchbot-openapi-cli/actions/workflows/ci.yml)
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
**SwitchBot** smart home CLI — control lights, locks, curtains, sensors, plugs, and IR appliances (TV/AC/fan) via the [SwitchBot Cloud API v1.1](https://github.com/OpenWonderLabs/SwitchBotAPI).
|
|
10
|
+
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.
|
|
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)
|
|
14
14
|
- **Releases / changelog:** [GitHub Releases](https://github.com/OpenWonderLabs/switchbot-openapi-cli/releases)
|
|
15
15
|
- **Issues / feature requests:** [GitHub Issues](https://github.com/OpenWonderLabs/switchbot-openapi-cli/issues)
|
|
16
16
|
|
|
17
|
+
> Looking for the **conversational skill** that drives this CLI from a chat
|
|
18
|
+
> agent? A companion skill for third-party agent hosts is maintained in a
|
|
19
|
+
> separate repository.
|
|
20
|
+
> See [`docs/agent-guide.md`](./docs/agent-guide.md) for the authoritative
|
|
21
|
+
> surfaces (MCP, `agent-bootstrap`, `schema export`, `capabilities --json`)
|
|
22
|
+
> the skill consumes. Skill packaging + registry entry is tracked
|
|
23
|
+
> as Phase 3B — see [`docs/design/roadmap.md`](./docs/design/roadmap.md).
|
|
24
|
+
|
|
17
25
|
---
|
|
18
26
|
|
|
19
27
|
## Who is this for?
|
|
20
28
|
|
|
21
29
|
Three entry points, same binary — pick the one that matches how you use it:
|
|
22
30
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
- **Human**: start with this README ([Quick start](#quick-start)).
|
|
32
|
+
You get colored tables, helpful error hints, shell completion, and
|
|
33
|
+
`switchbot doctor` self-check.
|
|
34
|
+
- **Script**: start with [Output modes](#output-modes) and
|
|
35
|
+
[Scripting examples](#scripting-examples).
|
|
36
|
+
You get `--json`, `--format=tsv/yaml/id`, `--fields`, stable exit codes,
|
|
37
|
+
`history replay`, and audit log support.
|
|
38
|
+
- **Agent**: start with [`docs/agent-guide.md`](./docs/agent-guide.md).
|
|
39
|
+
You get `switchbot mcp serve` (stdio MCP server), `schema export`,
|
|
40
|
+
`plan run`, and destructive-command guards.
|
|
28
41
|
|
|
29
42
|
Under the hood every surface shares the same catalog, cache, and HMAC client — switching between them costs nothing.
|
|
30
43
|
|
|
@@ -37,6 +50,7 @@ Under the hood every surface shares the same catalog, cache, and HMAC client —
|
|
|
37
50
|
- [Installation](#installation)
|
|
38
51
|
- [Quick start](#quick-start)
|
|
39
52
|
- [Credentials](#credentials)
|
|
53
|
+
- [Policy](#policy)
|
|
40
54
|
- [Global options](#global-options)
|
|
41
55
|
- [Commands](#commands)
|
|
42
56
|
- [`config`](#config--credential-management)
|
|
@@ -46,6 +60,7 @@ Under the hood every surface shares the same catalog, cache, and HMAC client —
|
|
|
46
60
|
- [`scenes`](#scenes--run-manual-scenes)
|
|
47
61
|
- [`webhook`](#webhook--receive-device-events-over-http)
|
|
48
62
|
- [`events`](#events--receive-device-events)
|
|
63
|
+
- [`status-sync`](#status-sync--mqttopenclaw-bridge)
|
|
49
64
|
- [`plan`](#plan--declarative-batch-operations)
|
|
50
65
|
- [`mcp`](#mcp--model-context-protocol-server)
|
|
51
66
|
- [`doctor`](#doctor--self-check)
|
|
@@ -55,9 +70,10 @@ Under the hood every surface shares the same catalog, cache, and HMAC client —
|
|
|
55
70
|
- [`schema`](#schema--export-catalog-as-json)
|
|
56
71
|
- [`capabilities`](#capabilities--cli-manifest)
|
|
57
72
|
- [`cache`](#cache--inspect-and-clear-local-cache)
|
|
73
|
+
- [`policy`](#policy--validate-scaffold-and-migrate-policyyaml)
|
|
58
74
|
- [`completion`](#completion--shell-tab-completion)
|
|
59
75
|
- [Output modes](#output-modes)
|
|
60
|
-
- [Cache](#cache
|
|
76
|
+
- [Cache](#cache)
|
|
61
77
|
- [Exit codes & error codes](#exit-codes--error-codes)
|
|
62
78
|
- [Environment variables](#environment-variables)
|
|
63
79
|
- [Scripting examples](#scripting-examples)
|
|
@@ -76,7 +92,7 @@ Under the hood every surface shares the same catalog, cache, and HMAC client —
|
|
|
76
92
|
- 🎨 **Dual output modes** — colorized tables by default; `--json` passthrough for `jq` and scripting
|
|
77
93
|
- 🔐 **Secure credentials** — HMAC-SHA256 signed requests; config file written with `0600`; env-var override for CI
|
|
78
94
|
- 🔍 **Dry-run mode** — preview every mutating request before it hits the API
|
|
79
|
-
- 🧪 **Fully tested** —
|
|
95
|
+
- 🧪 **Fully tested** — 1765 Vitest tests, mocked axios, zero network in CI
|
|
80
96
|
- ⚡ **Shell completion** — Bash / Zsh / Fish / PowerShell
|
|
81
97
|
|
|
82
98
|
## Requirements
|
|
@@ -113,6 +129,16 @@ switchbot --help
|
|
|
113
129
|
|
|
114
130
|
## Quick start
|
|
115
131
|
|
|
132
|
+
The fast path (credentials + policy + skill link, with rollback on failure):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
switchbot install --agent claude-code --skill-path ../switchbot-skill
|
|
136
|
+
# or preview first
|
|
137
|
+
switchbot install --dry-run
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Prefer the manual 4-step walk-through? Here it is:
|
|
141
|
+
|
|
116
142
|
```bash
|
|
117
143
|
# 1. Save your credentials (one-time)
|
|
118
144
|
switchbot config set-token <token> <secret>
|
|
@@ -120,16 +146,44 @@ switchbot config set-token <token> <secret>
|
|
|
120
146
|
# 2. List every device on your account
|
|
121
147
|
switchbot devices list
|
|
122
148
|
|
|
123
|
-
# 3. Control a device
|
|
124
|
-
switchbot devices command <deviceId> turnOn
|
|
149
|
+
# 3. Control a device, writing a structured entry to the audit log
|
|
150
|
+
switchbot devices command <deviceId> turnOn --audit-log
|
|
151
|
+
|
|
152
|
+
# 4. Confirm everything is healthy — network, catalog, credentials, cache.
|
|
153
|
+
# Any non-"ok" check prints with a hint; fix those first.
|
|
154
|
+
switchbot doctor --json | jq '.checks[] | select(.status!="ok")'
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Adding an AI agent or declarative automation? A few more one-liners
|
|
158
|
+
round out the first-day path:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# 5. Cold-start snapshot an LLM can read before its first tool call.
|
|
162
|
+
switchbot agent-bootstrap --compact | jq '.identity, .devices.total'
|
|
163
|
+
|
|
164
|
+
# 6. Scaffold a policy.yaml (aliases, quiet hours, confirmations) and
|
|
165
|
+
# validate it. Safe to run — defaults apply if you never edit it.
|
|
166
|
+
switchbot policy new
|
|
167
|
+
switchbot policy validate
|
|
168
|
+
|
|
169
|
+
# 7. Stream real-time device events over MQTT (events land as JSONL).
|
|
170
|
+
switchbot events mqtt-tail --max 3 --json
|
|
171
|
+
|
|
172
|
+
# 8. Run the OpenClaw status bridge in the background.
|
|
173
|
+
switchbot status-sync start --openclaw-model home-agent
|
|
125
174
|
```
|
|
126
175
|
|
|
176
|
+
See [Policy](#policy) for the authoring flow, [Rules engine](#rules-engine)
|
|
177
|
+
for automations, and [`docs/agent-guide.md`](./docs/agent-guide.md)
|
|
178
|
+
for the agent surface.
|
|
179
|
+
|
|
127
180
|
## Credentials
|
|
128
181
|
|
|
129
182
|
The CLI reads credentials in this order (first match wins):
|
|
130
183
|
|
|
131
184
|
1. **Environment variables** — `SWITCHBOT_TOKEN` and `SWITCHBOT_SECRET`
|
|
132
|
-
2. **
|
|
185
|
+
2. **OS keychain** — native keychain (macOS Keychain / Windows Credential Manager / libsecret on Linux) when populated via `switchbot auth keychain set`
|
|
186
|
+
3. **Config file** — `~/.switchbot/config.json` (written by `config set-token`, mode `0600`)
|
|
133
187
|
|
|
134
188
|
Obtain the token and secret from the SwitchBot mobile app:
|
|
135
189
|
**Profile → Preferences → Developer Options → Get Token**.
|
|
@@ -146,30 +200,129 @@ export SWITCHBOT_SECRET=...
|
|
|
146
200
|
switchbot config show
|
|
147
201
|
```
|
|
148
202
|
|
|
203
|
+
### OS keychain
|
|
204
|
+
|
|
205
|
+
Prefer native OS storage over the `0600` JSON on disk:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# See which backend is active on this machine
|
|
209
|
+
switchbot auth keychain describe
|
|
210
|
+
|
|
211
|
+
# Move existing ~/.switchbot/config.json into the keychain.
|
|
212
|
+
# With --delete-file, the CLI deletes the source only when it contains
|
|
213
|
+
# nothing except token/secret; otherwise it scrubs those fields and keeps
|
|
214
|
+
# profile metadata such as labels and limits.
|
|
215
|
+
switchbot auth keychain migrate
|
|
216
|
+
|
|
217
|
+
# Or write credentials directly (TTY prompt or --stdin-file <path>)
|
|
218
|
+
switchbot auth keychain set
|
|
219
|
+
|
|
220
|
+
# Verify a profile has credentials without leaking the material
|
|
221
|
+
switchbot auth keychain get
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Backends: `security(1)` on macOS, `libsecret` / `secret-tool` on Linux,
|
|
225
|
+
Credential Manager (via PowerShell + Win32 `CredReadW`/`CredWriteW`) on
|
|
226
|
+
Windows. If no native backend is available, the file backend takes
|
|
227
|
+
over transparently so the CLI keeps working. `switchbot doctor`
|
|
228
|
+
surfaces which backend is active and warns when file-stored credentials
|
|
229
|
+
could be moved into a writable keychain.
|
|
230
|
+
|
|
231
|
+
## Policy
|
|
232
|
+
|
|
233
|
+
`policy.yaml` is an optional per-user file that declares preferences
|
|
234
|
+
the CLI (and any connected AI agent) should honour: device aliases,
|
|
235
|
+
quiet-hours, confirmation overrides, audit-log location, and CLI
|
|
236
|
+
profile. The file lives at:
|
|
237
|
+
|
|
238
|
+
- Linux / macOS: default policy path resolved by the CLI
|
|
239
|
+
- Windows: default policy path resolved by the CLI
|
|
240
|
+
|
|
241
|
+
Everything in it is optional — if the file is missing, safe defaults
|
|
242
|
+
apply. Scaffold, edit, and validate:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
switchbot policy new # write a commented starter template
|
|
246
|
+
$EDITOR <policy-path>
|
|
247
|
+
switchbot policy validate # exit 0 if OK, otherwise line-accurate error
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Why most users want a policy file: it makes name resolution
|
|
251
|
+
deterministic. Without it, "turn on the bedroom light" falls through
|
|
252
|
+
the CLI's prefix/substring/fuzzy match strategies and can pick the
|
|
253
|
+
wrong device when two names collide. A one-line `aliases` entry
|
|
254
|
+
removes the ambiguity.
|
|
255
|
+
|
|
256
|
+
**Schema version.** The CLI requires **policy v0.2**. If you have an existing
|
|
257
|
+
v0.1 file from an earlier release, migrate it first:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
switchbot policy migrate # in-place upgrade, preserves comments
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The v0.2 schema adds a typed `automation.rules[]` block (triggers, conditions,
|
|
264
|
+
throttles, dry-run) used by the rules engine (see
|
|
265
|
+
[Rules engine](#rules-engine)). Full field-by-field reference, validation flow,
|
|
266
|
+
and error catalogue: [`docs/policy-reference.md`](./docs/policy-reference.md).
|
|
267
|
+
Five annotated starter files covering common setups live in
|
|
268
|
+
[`examples/policies/`](./examples/policies/).
|
|
269
|
+
|
|
270
|
+
### Rules engine
|
|
271
|
+
|
|
272
|
+
With a policy.yaml (v0.2) you can declare automations that the CLI
|
|
273
|
+
executes for you. Supported triggers: **MQTT** (device events),
|
|
274
|
+
**cron** (schedule-driven), and **webhook** (local HTTP POST).
|
|
275
|
+
Supported conditions: `time_between` (quiet hours) and `device_state`
|
|
276
|
+
(live API check with per-tick dedup). Every fire is recorded in
|
|
277
|
+
`~/.switchbot/audit.log`. `rules run` is long-running; use
|
|
278
|
+
`rules reload` to hot-reload policy without dropping listeners.
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
# 1. Author rules under `automation.rules`. See examples/policies/automation.yaml
|
|
282
|
+
# for a walkthrough covering the three trigger sources.
|
|
283
|
+
|
|
284
|
+
# 2. Static-check before running.
|
|
285
|
+
switchbot rules lint # exit 0 valid, 1 error
|
|
286
|
+
switchbot rules list --json | jq . # structured summary
|
|
287
|
+
|
|
288
|
+
# 3. Run the engine. --dry-run overrides every rule into audit-only mode;
|
|
289
|
+
# --max-firings bounds a demo session.
|
|
290
|
+
switchbot rules run --dry-run --max-firings 5
|
|
291
|
+
|
|
292
|
+
# 4. Edit policy.yaml in another shell, then hot-reload without restart.
|
|
293
|
+
switchbot rules reload # SIGHUP on Unix, sentinel file on Windows
|
|
294
|
+
|
|
295
|
+
# 5. Review recorded fires.
|
|
296
|
+
switchbot rules tail --follow # stream rule-* audit lines
|
|
297
|
+
switchbot rules replay --since 1h --json # per-rule fires/dries/throttled/errors
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
See [`docs/design/phase4-rules.md`](./docs/design/phase4-rules.md) for
|
|
301
|
+
the engine's pipeline (subscribe → classify → match → conditions →
|
|
302
|
+
throttle → action → audit).
|
|
303
|
+
|
|
149
304
|
## Global options
|
|
150
305
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
| `-V`, `--version` | Print the CLI version |
|
|
172
|
-
| `-h`, `--help` | Show help for any command or subcommand |
|
|
306
|
+
- `--json`: Print the raw JSON response instead of a formatted table.
|
|
307
|
+
- `--format <fmt>`: Output format: `tsv`, `yaml`, `jsonl`, `json`, `id`.
|
|
308
|
+
- `--fields <cols>`: Comma-separated column names to include (for example `deviceId,type`).
|
|
309
|
+
- `-v`, `--verbose`: Log HTTP request/response details to stderr.
|
|
310
|
+
- `--dry-run`: Print mutating requests (POST/PUT/DELETE) without sending them.
|
|
311
|
+
- `--timeout <ms>`: HTTP request timeout in milliseconds (default `30000`).
|
|
312
|
+
- `--config <path>`: Override credential file location (default `~/.switchbot/config.json`).
|
|
313
|
+
- `--profile <name>`: Use a named credential profile (`~/.switchbot/profiles/<name>.json`).
|
|
314
|
+
- `--cache <dur>`: Set list and status cache TTL, for example `5m`, `1h`, `off`, `auto` (default).
|
|
315
|
+
- `--cache-list <dur>`: Set list-cache TTL independently (overrides `--cache`).
|
|
316
|
+
- `--cache-status <dur>`: Set status-cache TTL independently (default off; overrides `--cache`).
|
|
317
|
+
- `--no-cache`: Disable all cache reads for this invocation.
|
|
318
|
+
- `--retry-on-429 <n>`: Max 429 retry attempts (default `3`).
|
|
319
|
+
- `--no-retry`: Disable automatic 429 retries.
|
|
320
|
+
- `--backoff <strategy>`: Retry backoff: `exponential` (default) or `linear`.
|
|
321
|
+
- `--no-quota`: Disable local request-quota tracking.
|
|
322
|
+
- `--audit-log`: Append mutating commands to a JSONL audit log (default path `~/.switchbot/audit.log`).
|
|
323
|
+
- `--audit-log-path <path>`: Custom audit log path; use together with `--audit-log`.
|
|
324
|
+
- `-V`, `--version`: Print the CLI version.
|
|
325
|
+
- `-h`, `--help`: Show help for any command or subcommand.
|
|
173
326
|
|
|
174
327
|
Every subcommand supports `--help`, and most include a parameter-format reference and examples.
|
|
175
328
|
|
|
@@ -231,7 +384,7 @@ switchbot devices list --filter 'name~living'
|
|
|
231
384
|
switchbot devices list --filter 'type=/Hub.*/'
|
|
232
385
|
switchbot devices list --filter 'name~office,type=/Bulb|Strip/'
|
|
233
386
|
|
|
234
|
-
# Filter by family / room (family & room info requires the
|
|
387
|
+
# Filter by family / room (family & room info requires the platform source
|
|
235
388
|
# header, which this CLI sends on every request)
|
|
236
389
|
switchbot devices list --json | jq '.deviceList[] | select(.familyName == "Home")'
|
|
237
390
|
switchbot devices list --json | jq '[.deviceList[], .infraredRemoteList[]] | group_by(.familyName)'
|
|
@@ -270,11 +423,16 @@ switchbot devices commands curtain # Case-insensitive, substring match
|
|
|
270
423
|
Three commands accept `--filter`. They share one four-operator grammar,
|
|
271
424
|
but each exposes its own key set:
|
|
272
425
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
426
|
+
- `devices list`
|
|
427
|
+
Operators: `=` (substring; **exact** for `category`), `!=` (negated),
|
|
428
|
+
`~` (substring), `=/regex/` (case-insensitive regex).
|
|
429
|
+
Keys: `type`, `name`, `category`, `room`.
|
|
430
|
+
- `devices batch`
|
|
431
|
+
Operators: same as `devices list`.
|
|
432
|
+
Keys: `type`, `family`, `room`, `category`.
|
|
433
|
+
- `events tail` / `events mqtt-tail`
|
|
434
|
+
Operators: same (tail only; mqtt-tail uses `--topic` instead).
|
|
435
|
+
Keys: `deviceId`, `type`.
|
|
278
436
|
|
|
279
437
|
Clauses are comma-separated and AND-ed. No OR across clauses — use regex
|
|
280
438
|
alternation (`=/A|B/`) for that. `category` is the one key that stays exact
|
|
@@ -441,7 +599,8 @@ switchbot events tail --port 8080 --path /hook --json
|
|
|
441
599
|
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.
|
|
442
600
|
|
|
443
601
|
Output (one JSON line per matched event):
|
|
444
|
-
|
|
602
|
+
|
|
603
|
+
```json
|
|
445
604
|
{ "t": "2024-01-01T12:00:00.000Z", "remote": "1.2.3.4:54321", "path": "/", "body": {...}, "matched": true }
|
|
446
605
|
```
|
|
447
606
|
|
|
@@ -466,7 +625,8 @@ switchbot events mqtt-tail --for 30s --json
|
|
|
466
625
|
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.
|
|
467
626
|
|
|
468
627
|
Output (one JSON line per message):
|
|
469
|
-
|
|
628
|
+
|
|
629
|
+
```json
|
|
470
630
|
{ "t": "2024-01-01T12:00:00.000Z", "topic": "switchbot/abc123/status", "payload": {...} }
|
|
471
631
|
```
|
|
472
632
|
|
|
@@ -482,31 +642,65 @@ nohup switchbot events mqtt-tail --json >> ~/switchbot-events.log 2>&1 &
|
|
|
482
642
|
|
|
483
643
|
Run `switchbot doctor` to verify MQTT credentials are configured correctly before connecting.
|
|
484
644
|
|
|
645
|
+
### `status-sync` — MQTT/OpenClaw bridge
|
|
646
|
+
|
|
647
|
+
Use this command family when you want the CLI itself to own the lifecycle of a
|
|
648
|
+
long-running bridge that forwards SwitchBot MQTT shadow events into an OpenClaw
|
|
649
|
+
gateway. Internally it reuses `events mqtt-tail --sink openclaw`, but adds a
|
|
650
|
+
stable command surface for foreground execution, background startup, status
|
|
651
|
+
inspection, and shutdown.
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
# Foreground mode for supervisors / containers
|
|
655
|
+
switchbot status-sync run --openclaw-model home-agent
|
|
656
|
+
|
|
657
|
+
# Background mode for a normal shell session
|
|
658
|
+
switchbot status-sync start --openclaw-model home-agent
|
|
659
|
+
|
|
660
|
+
# Inspect the current bridge
|
|
661
|
+
switchbot status-sync status --json
|
|
662
|
+
|
|
663
|
+
# Stop the running bridge
|
|
664
|
+
switchbot status-sync stop
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
Required input:
|
|
668
|
+
|
|
669
|
+
- `OPENCLAW_MODEL` or `--openclaw-model <id>`
|
|
670
|
+
- `OPENCLAW_TOKEN` or `--openclaw-token <token>`
|
|
671
|
+
|
|
672
|
+
Optional input:
|
|
673
|
+
|
|
674
|
+
- `OPENCLAW_URL` or `--openclaw-url <url>`
|
|
675
|
+
- `--topic <pattern>` to narrow the MQTT subscription
|
|
676
|
+
- `SWITCHBOT_STATUS_SYNC_HOME` or `--state-dir <path>` for custom runtime state
|
|
677
|
+
|
|
678
|
+
Background mode writes these files under the state directory:
|
|
679
|
+
|
|
680
|
+
- `state.json` — current pid, start time, effective command
|
|
681
|
+
- `stdout.log` — child stdout
|
|
682
|
+
- `stderr.log` — child stderr
|
|
683
|
+
|
|
684
|
+
Foreground vs background:
|
|
685
|
+
|
|
686
|
+
- `status-sync run` keeps the bridge attached to the current terminal
|
|
687
|
+
- `status-sync start` detaches the bridge and returns immediately
|
|
688
|
+
- `status-sync status` reports whether the bridge is alive plus paths/logs
|
|
689
|
+
- `status-sync stop` terminates the managed bridge process tree
|
|
690
|
+
|
|
485
691
|
#### `mqtt-tail` sinks — route events to external services
|
|
486
692
|
|
|
487
693
|
By default `mqtt-tail` prints JSONL to stdout. Use `--sink` (repeatable) to route events to one or more destinations instead:
|
|
488
694
|
|
|
489
695
|
| Sink | Required flags |
|
|
490
|
-
|
|
696
|
+
| --- | --- |
|
|
491
697
|
| `stdout` | (default when no `--sink` given) |
|
|
492
698
|
| `file` | `--sink-file <path>` — append JSONL |
|
|
493
699
|
| `webhook` | `--webhook-url <url>` — HTTP POST each event |
|
|
494
|
-
| `openclaw` | `--openclaw-url`, `--openclaw-token` (or `$OPENCLAW_TOKEN`), `--openclaw-model` |
|
|
495
700
|
| `telegram` | `--telegram-token` (or `$TELEGRAM_TOKEN`), `--telegram-chat <chatId>` |
|
|
496
701
|
| `homeassistant` | `--ha-url <url>` + `--ha-webhook-id` (no auth) or `--ha-token` (REST event API) |
|
|
497
702
|
|
|
498
703
|
```bash
|
|
499
|
-
# Push events to an OpenClaw agent (replaces the SwitchBot channel plugin)
|
|
500
|
-
switchbot events mqtt-tail \
|
|
501
|
-
--sink openclaw \
|
|
502
|
-
--openclaw-token <token> \
|
|
503
|
-
--openclaw-model my-home-agent
|
|
504
|
-
|
|
505
|
-
# Write to file + push to OpenClaw simultaneously
|
|
506
|
-
switchbot events mqtt-tail \
|
|
507
|
-
--sink file --sink-file ~/.switchbot/events.jsonl \
|
|
508
|
-
--sink openclaw --openclaw-token <token> --openclaw-model home
|
|
509
|
-
|
|
510
704
|
# Generic webhook (n8n, Make, etc.)
|
|
511
705
|
switchbot events mqtt-tail --sink webhook --webhook-url https://n8n.local/hook/abc
|
|
512
706
|
|
|
@@ -540,6 +734,9 @@ Supported shells: `bash`, `zsh`, `fish`, `powershell` (`pwsh` is accepted as an
|
|
|
540
734
|
# Print the plan JSON Schema (give to your agent framework)
|
|
541
735
|
switchbot plan schema
|
|
542
736
|
|
|
737
|
+
# Draft a candidate plan from natural language intent
|
|
738
|
+
switchbot plan suggest --intent "turn off all lights" --device <id1> --device <id2>
|
|
739
|
+
|
|
543
740
|
# Validate a plan file without running it
|
|
544
741
|
switchbot plan validate plan.json
|
|
545
742
|
|
|
@@ -549,9 +746,12 @@ switchbot --dry-run plan run plan.json
|
|
|
549
746
|
# Run — pass --yes to allow destructive steps
|
|
550
747
|
switchbot plan run plan.json --yes
|
|
551
748
|
switchbot plan run plan.json --continue-on-error
|
|
749
|
+
|
|
750
|
+
# Run with per-step TTY confirmation for destructive steps (human-in-the-loop)
|
|
751
|
+
switchbot plan run plan.json --require-approval
|
|
552
752
|
```
|
|
553
753
|
|
|
554
|
-
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.
|
|
754
|
+
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. `--require-approval` prompts for each destructive step individually, letting you approve or reject without re-running the whole plan. See [`docs/agent-guide.md`](./docs/agent-guide.md) for the full schema and agent integration patterns.
|
|
555
755
|
|
|
556
756
|
### `devices watch` — poll status
|
|
557
757
|
|
|
@@ -575,7 +775,12 @@ Output is a JSONL stream of status-change events (with `--json`) or a refreshed
|
|
|
575
775
|
switchbot mcp serve
|
|
576
776
|
```
|
|
577
777
|
|
|
578
|
-
Exposes
|
|
778
|
+
Exposes MCP tools (`list_devices`, `describe_device`, `get_device_status`,
|
|
779
|
+
`send_command`, `list_scenes`, `run_scene`, `search_catalog`,
|
|
780
|
+
`account_overview`, `plan_suggest`, `plan_run`, `audit_query`,
|
|
781
|
+
`audit_stats`, `policy_diff`, `policy_validate`, `policy_new`,
|
|
782
|
+
`policy_migrate`) plus a `switchbot://events` resource for real-time
|
|
783
|
+
shadow updates.
|
|
579
784
|
See [`docs/agent-guide.md`](./docs/agent-guide.md) for the full tool reference and safety rules (destructive-command guard).
|
|
580
785
|
|
|
581
786
|
### `doctor` — self-check
|
|
@@ -585,7 +790,7 @@ switchbot doctor
|
|
|
585
790
|
switchbot doctor --json
|
|
586
791
|
```
|
|
587
792
|
|
|
588
|
-
Runs
|
|
793
|
+
Runs local checks (Node version, credentials, profiles, catalog, cache, quota, clock, MQTT, policy, MCP) 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.
|
|
589
794
|
|
|
590
795
|
### `quota` — API request counter
|
|
591
796
|
|
|
@@ -654,7 +859,45 @@ switchbot cache clear --key list
|
|
|
654
859
|
switchbot cache clear --key status
|
|
655
860
|
```
|
|
656
861
|
|
|
862
|
+
### `policy` — validate, scaffold, and migrate policy.yaml
|
|
863
|
+
|
|
864
|
+
Companion to the separate SwitchBot skill repository for third-party agent hosts. The skill reads behaviour (aliases, confirmations, quiet hours, audit path) from `policy.yaml`. This command group checks that file before the skill ever sees it, turning what used to be silent failures into line-accurate errors.
|
|
865
|
+
|
|
866
|
+
```bash
|
|
867
|
+
# Write a starter policy at the default location
|
|
868
|
+
switchbot policy new # writes to the resolved default policy path
|
|
869
|
+
switchbot policy new ./custom/policy.yaml --force
|
|
870
|
+
|
|
871
|
+
# Validate (compiler-style errors with line:col + caret + hints)
|
|
872
|
+
switchbot policy validate
|
|
873
|
+
switchbot policy validate ./custom/policy.yaml
|
|
874
|
+
switchbot policy validate --json | jq '.data.errors'
|
|
875
|
+
switchbot policy validate --no-snippet # plain error list, no source preview
|
|
876
|
+
|
|
877
|
+
# Report the schema version the file declares
|
|
878
|
+
switchbot policy migrate
|
|
879
|
+
```
|
|
657
880
|
|
|
881
|
+
Path resolution order: positional `[path]` > `SWITCHBOT_POLICY_PATH` env var > default policy path.
|
|
882
|
+
|
|
883
|
+
**Exit codes:** `0` valid / `1` invalid / `2` file-not-found / `3` yaml-parse / `4` internal / `5` file already exists (on `new`, overridden with `--force`) / `6` unsupported schema version (on `migrate`).
|
|
884
|
+
|
|
885
|
+
Example — editing an alias without quoting the deviceId:
|
|
886
|
+
|
|
887
|
+
```console
|
|
888
|
+
$ switchbot policy validate
|
|
889
|
+
<policy-path>:14:11
|
|
890
|
+
14 | bedroom light: 01-abc-12345
|
|
891
|
+
^^^^^^^^^^^^^
|
|
892
|
+
error: /aliases/bedroom light does not match pattern ^[A-Z0-9]{2,}-[A-Z0-9-]+$
|
|
893
|
+
hint: paste the deviceId from `switchbot devices list --format=tsv`, e.g. 01-202407090924-26354212
|
|
894
|
+
|
|
895
|
+
✗ 1 error in <policy-path> (schema v0.1)
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
The default policy schema shipped with the CLI (`src/policy/schema/v0.2.json`) is mirrored as `examples/policy.schema.json` in the companion skill repo; a CI job on every push diffs the two to prevent drift.
|
|
899
|
+
|
|
900
|
+
## Output modes
|
|
658
901
|
|
|
659
902
|
- **Default** — ANSI-colored tables for `list`/`status`, key-value tables for details.
|
|
660
903
|
- **`--json`** — raw API payload passthrough. Output is the exact JSON the SwitchBot API returned, ideal for `jq` and scripting. Errors are also JSON on stderr: `{ "error": { "code", "kind", "message", "hint?" } }`.
|
|
@@ -675,10 +918,10 @@ switchbot devices status <id> --format yaml
|
|
|
675
918
|
|
|
676
919
|
The CLI maintains two local disk caches under `~/.switchbot/`:
|
|
677
920
|
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
921
|
+
- `devices.json`: Device metadata (id, name, type, category, hub, room…).
|
|
922
|
+
Default TTL: 1 hour.
|
|
923
|
+
- `status.json`: Per-device status bodies.
|
|
924
|
+
Default TTL: off (0).
|
|
682
925
|
|
|
683
926
|
The device-list cache powers offline validation (command name checks, destructive-command guard) and the MCP server's `send_command` tool. It is refreshed automatically on every `devices list` call.
|
|
684
927
|
|
|
@@ -718,32 +961,28 @@ switchbot cache clear --key status
|
|
|
718
961
|
|
|
719
962
|
## Exit codes & error codes
|
|
720
963
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
| 401 | Authentication failed (check token/secret) |
|
|
738
|
-
| 429 | Request rate too high (10,000 req/day cap) |
|
|
964
|
+
- `0`: Success (including `--dry-run` intercept when validation passes).
|
|
965
|
+
- `1`: Runtime error — API error, network failure, missing credentials.
|
|
966
|
+
- `2`: Usage error — bad flag, missing/invalid argument, unknown subcommand,
|
|
967
|
+
unknown device type, invalid URL, conflicting flags.
|
|
968
|
+
|
|
969
|
+
Typical errors bubble up in the form `Error: <message>` on stderr. The
|
|
970
|
+
SwitchBot-specific error codes mapped to readable messages:
|
|
971
|
+
|
|
972
|
+
- `151`: Device type error.
|
|
973
|
+
- `152`: Device not found.
|
|
974
|
+
- `160`: Command not supported by this device.
|
|
975
|
+
- `161`: Device offline (BLE devices need a Hub).
|
|
976
|
+
- `171`: Hub offline.
|
|
977
|
+
- `190`: Device internal error / server busy.
|
|
978
|
+
- `401`: Authentication failed (check token/secret).
|
|
979
|
+
- `429`: Request rate too high (10,000 req/day cap).
|
|
739
980
|
|
|
740
981
|
## Environment variables
|
|
741
982
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
| `SWITCHBOT_SECRET` | API secret — takes priority over the config file |
|
|
746
|
-
| `NO_COLOR` | Disable ANSI colors in all output (automatically respected) |
|
|
983
|
+
- `SWITCHBOT_TOKEN`: API token — takes priority over the config file.
|
|
984
|
+
- `SWITCHBOT_SECRET`: API secret — takes priority over the config file.
|
|
985
|
+
- `NO_COLOR`: Disable ANSI colors in all output (automatically respected).
|
|
747
986
|
|
|
748
987
|
## Scripting examples
|
|
749
988
|
|
|
@@ -766,37 +1005,69 @@ npm install
|
|
|
766
1005
|
|
|
767
1006
|
npm run dev -- <args> # Run from TypeScript sources via tsx
|
|
768
1007
|
npm run build # Compile to dist/
|
|
769
|
-
npm test # Run the Vitest suite (
|
|
1008
|
+
npm test # Run the Vitest suite (1765 tests)
|
|
770
1009
|
npm run test:watch # Watch mode
|
|
771
1010
|
npm run test:coverage # Coverage report (v8, HTML + text)
|
|
772
1011
|
```
|
|
773
1012
|
|
|
774
1013
|
### Project layout
|
|
775
1014
|
|
|
776
|
-
```
|
|
1015
|
+
```text
|
|
777
1016
|
src/
|
|
778
1017
|
├── index.ts # Commander entry; mounts all subcommands; global flags
|
|
779
1018
|
├── auth.ts # HMAC-SHA256 signature (token + t + nonce → sign)
|
|
780
|
-
├── config.ts # Credential load/save; env > file priority
|
|
1019
|
+
├── config.ts # Credential load/save; env > keychain > file priority
|
|
781
1020
|
├── api/client.ts # axios instance + request/response interceptors;
|
|
782
1021
|
│ # --verbose / --dry-run / --timeout wiring
|
|
1022
|
+
├── credentials/
|
|
1023
|
+
│ ├── keychain.ts # Credential store interface + OS backend selection
|
|
1024
|
+
│ └── backends/ # macos.ts / linux.ts / windows.ts / file.ts
|
|
783
1025
|
├── devices/
|
|
784
1026
|
│ ├── catalog.ts # Static device catalog (commands, params, status fields)
|
|
785
1027
|
│ └── cache.ts # Disk + in-memory cache for device list and status
|
|
1028
|
+
├── install/
|
|
1029
|
+
│ ├── steps.ts # Generic step runner with rollback support
|
|
1030
|
+
│ ├── preflight.ts # Pre-flight checks (Node, npm, network, agent)
|
|
1031
|
+
│ └── default-steps.ts # Concrete steps: credentials, keychain, policy, skill, doctor
|
|
1032
|
+
├── policy/
|
|
1033
|
+
│ ├── validate.ts # Schema version dispatch + JSON Schema validation
|
|
1034
|
+
│ ├── migrate.ts # v0.1 → v0.2 migration
|
|
1035
|
+
│ ├── load.ts # YAML file loading + error handling
|
|
1036
|
+
│ ├── add-rule.ts # Rule injection into automation.rules[]
|
|
1037
|
+
│ ├── diff.ts # Structural + line diff
|
|
1038
|
+
│ └── schema/v0.2.json # Authoritative v0.2 JSON Schema
|
|
1039
|
+
├── rules/
|
|
1040
|
+
│ ├── engine.ts # Main orchestrator (MQTT + cron + webhook)
|
|
1041
|
+
│ ├── matcher.ts # Trigger + condition matchers
|
|
1042
|
+
│ ├── action.ts # Command renderer + executor
|
|
1043
|
+
│ ├── throttle.ts # Per-rule throttle gate
|
|
1044
|
+
│ ├── cron-scheduler.ts # 5-field cron + days filter
|
|
1045
|
+
│ ├── webhook-listener.ts # HTTP listener (bearer token, localhost-only)
|
|
1046
|
+
│ ├── pid-file.ts # Hot-reload via SIGHUP or sentinel file
|
|
1047
|
+
│ ├── audit-query.ts # Audit log filtering + aggregation
|
|
1048
|
+
│ ├── suggest.ts # Heuristic-based rule YAML generation
|
|
1049
|
+
│ └── types.ts # Shared rule/trigger/condition/action types
|
|
1050
|
+
├── status-sync/
|
|
1051
|
+
│ └── manager.ts # Spawn/stop logic, state file, OpenClaw bridge
|
|
786
1052
|
├── lib/
|
|
787
1053
|
│ └── devices.ts # Shared logic: listDevices, describeDevice, isDestructiveCommand
|
|
788
1054
|
├── commands/
|
|
1055
|
+
│ ├── auth.ts # `auth keychain` subcommand group
|
|
789
1056
|
│ ├── config.ts
|
|
790
1057
|
│ ├── devices.ts
|
|
791
1058
|
│ ├── expand.ts # `devices expand` — semantic flag builder
|
|
792
1059
|
│ ├── explain.ts # `devices explain` — one-shot device summary
|
|
793
1060
|
│ ├── device-meta.ts # `devices meta` — local aliases / hide flags
|
|
1061
|
+
│ ├── install.ts # `switchbot install` / `uninstall`
|
|
1062
|
+
│ ├── policy.ts # `policy validate/new/migrate/diff/add-rule`
|
|
1063
|
+
│ ├── rules.ts # `rules suggest/lint/list/run/reload/tail/replay`
|
|
794
1064
|
│ ├── scenes.ts
|
|
1065
|
+
│ ├── status-sync.ts # `status-sync run/start/stop/status`
|
|
795
1066
|
│ ├── webhook.ts
|
|
796
1067
|
│ ├── watch.ts # `devices watch <deviceId>`
|
|
797
1068
|
│ ├── events.ts # `events tail` / `events mqtt-tail`
|
|
798
1069
|
│ ├── mcp.ts # `mcp serve` (MCP stdio/HTTP server)
|
|
799
|
-
│ ├── plan.ts # `plan run/validate`
|
|
1070
|
+
│ ├── plan.ts # `plan run/validate/suggest`
|
|
800
1071
|
│ ├── cache.ts # `cache show/clear`
|
|
801
1072
|
│ ├── history.ts # `history show/replay`
|
|
802
1073
|
│ ├── quota.ts # `quota status/reset`
|
|
@@ -807,11 +1078,11 @@ src/
|
|
|
807
1078
|
│ └── completion.ts # `completion bash|zsh|fish|powershell`
|
|
808
1079
|
└── utils/
|
|
809
1080
|
├── flags.ts # Global flag readers (isVerbose / isDryRun / getCacheMode / …)
|
|
810
|
-
├── output.ts # printTable / printKeyValue / printJson / handleError
|
|
1081
|
+
├── output.ts # printTable / printKeyValue / printJson / handleError
|
|
811
1082
|
├── format.ts # renderRows / filterFields / output-format dispatch
|
|
812
1083
|
├── audit.ts # JSONL audit log writer
|
|
813
1084
|
└── quota.ts # Local daily-quota counter
|
|
814
|
-
tests/ # Vitest suite (
|
|
1085
|
+
tests/ # Vitest suite (1765 tests, mocked axios, no network)
|
|
815
1086
|
```
|
|
816
1087
|
|
|
817
1088
|
### Release flow
|
|
@@ -836,18 +1107,29 @@ Bug reports, feature requests, and PRs are welcome.
|
|
|
836
1107
|
|
|
837
1108
|
## Roadmap
|
|
838
1109
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
-
|
|
848
|
-
|
|
849
|
-
- **
|
|
850
|
-
|
|
1110
|
+
Phase 1 through Phase 4 are shipped. The authoritative phase/track table
|
|
1111
|
+
(including skill-side `autonomyLevel` L1/L2/L3 mapping) lives in
|
|
1112
|
+
[`docs/design/roadmap.md`](./docs/design/roadmap.md).
|
|
1113
|
+
|
|
1114
|
+
Shipped tracks summary:
|
|
1115
|
+
|
|
1116
|
+
- **Track β**: one-command install/uninstall surface (`switchbot install` / `switchbot uninstall`).
|
|
1117
|
+
- **Track γ**: rules v0.2 runtime increment (`days` + `all`/`any`/`not`).
|
|
1118
|
+
- **Track δ (L2)**: plan authoring + guarded execution (`plan suggest`, `plan run --require-approval`) and MCP review/execute tools (`plan_suggest`, `plan_run`, `audit_query`, `audit_stats`, `policy_diff`).
|
|
1119
|
+
- **Track ζ (L3)**: autonomous rule authoring (`rules suggest`, `policy add-rule`) with MCP parity (`rules_suggest`, `policy_add_rule`).
|
|
1120
|
+
- **Track ε**: cross-OS keychain CI matrix (macOS + Linux libsecret + Windows Credential Manager).
|
|
1121
|
+
|
|
1122
|
+
Backlog tracks still open:
|
|
1123
|
+
|
|
1124
|
+
1. **Daemon mode** — long-running local process with Unix/named-pipe
|
|
1125
|
+
transport so repeated MCP or plan invocations avoid fresh-process
|
|
1126
|
+
startup cost.
|
|
1127
|
+
2. **`npx @switchbot/mcp-server`** — split the MCP server into a tiny
|
|
1128
|
+
package so non-CLI users can run it directly with `npx`.
|
|
1129
|
+
3. **`switchbot self-test`** — scripted end-to-end go/no-go checks for
|
|
1130
|
+
token/secret validity plus representative device control.
|
|
1131
|
+
4. **Record / replay** — capture request/response fixtures and replay
|
|
1132
|
+
offline for deterministic integration tests and CI.
|
|
851
1133
|
|
|
852
1134
|
## License
|
|
853
1135
|
|