Skip to content

Releases: OpenWonderLabs/switchbot-openapi-cli

3.0.0

24 Apr 07:38
d5c04a6

Choose a tag to compare

Major release — breaking changes, full feature parity across all branches.

Includes all features shipped in v2.10.0–v2.15.0: one-command install/uninstall, L3 autonomous rule authoring, plan suggest + --require-approval, MCP policy tools, and rules engine enhancements.

Breaking changes

  • Remove destructive: boolean field from all CLI/MCP output (schema export, devices describe, agent-bootstrap, explain, MCP catalog_search). Use safetyTier === 'destructive' instead.
  • Drop policy schema v0.1 support. Files with version: "0.1" are rejected with a migration hint. Run switchbot policy migrate on CLI ≤2.15 before upgrading.
  • buildStatusSyncChildArgs no longer accepts openclawToken; pass via env OPENCLAW_TOKEN.

What's new

  • switchbot install / uninstall — one-command setup with preflight, rollback, and 4-backend keychain (macOS / Linux / Windows / file)
  • switchbot auth keychain — describe, get, set, delete, migrate credentials in native OS keychain
  • switchbot policy — validate, new, migrate, diff, add-rule; v0.2 schema with typed automation.rules[]
  • switchbot rules — suggest, lint, list, run, reload, tail, replay, webhook-rotate-token; MQTT + cron + webhook triggers; time_between / device_state / all/any/not conditions; per-rule throttle + dry-run; SIGHUP hot-reload
  • switchbot status-sync — run, start, stop, status; background OpenClaw MQTT bridge
  • MCP: plan_suggest, plan_run, audit_query, audit_stats, policy_diff, policy_validate, policy_new, policy_migrate
  • doctor: policy check, MCP check, keychain backend detection, quota + catalog-schema parity checks
  • 1765 tests (up from 1624)

Migration

- if (spec.destructive) { ... }
+ if (spec.safetyTier === 'destructive') { ... }

Policy v0.1 → v0.2 (run on CLI ≤2.15 before upgrading):

switchbot policy migrate

v2.7.2 — AI-first maturity release (bundles 2.7.0 + 2.7.1 + 2.7.2)

21 Apr 16:21
62f3ad7

Choose a tag to compare

Consolidated v2.7 release. This single tag bundles three semver-logical cuts that were developed and merged together (PR #28). Neither v2.7.0 nor v2.7.1 were ever published as standalone tags — the CI size-budget fix (v2.7.2) was folded in before release.

v2.7.2 — CI size-budget fix

  • schema export --compact — dropped the resources block from compact output. In v2.7.0 the resources catalog (~12 KB) was added to the schema payload unconditionally, which pushed schema export --compact --used past the 15 KB agent-prompt budget enforced by CI. The resources block is still emitted under the full (non---compact) output, and remains available via capabilities --json, which is the canonical source for CLI resource metadata. No behaviour change for capabilities --json consumers.

v2.7.1 — help identity / AI discoverability

Top-level --help / --help --json and every subcommand description now lead with the SwitchBot product category (smart home: lights, locks, curtains, sensors, plugs, IR appliances) so AI agents reading help text can identify scope without parsing the catalog.

  • New src/commands/identity.ts — single source of truth (IDENTITY + PRODUCT_TAGLINE); replaces duplicated constants in capabilities.ts and agent-bootstrap.ts
  • Top-level switchbot --help — rewritten from "Command-line tool for SwitchBot API v1.1" to "SwitchBot smart home CLI — control lights, locks, curtains, sensors, plugs, and IR appliances (TV/AC/fan) via Cloud API v1.1; run scenes, stream real-time events, and integrate AI agents via MCP."
  • Root --help --json — carries product / domain / vendor / apiVersion / apiDocs / productCategories[8] at top level; subcommand help-json unchanged (root-only to keep per-command payloads tight)
  • Subcommand descriptionscatalog / schema / history / plan / doctor / capabilities now self-identify with "SwitchBot"
  • README intro — leads with product category, not the API version
  • agent-bootstrap --json — additive identity fields: apiDocs, deviceCategories, productCategories, agentGuide

No "BLE" in tagline/README/CHANGELOG by design: the CLI only talks to the SwitchBot Cloud API over HTTPS. BLE-only devices are reached through a SwitchBot Hub, which the Cloud API handles transparently.

v2.7.0 — AI-first maturity (headline release)

Broader field-alias coverage, richer capability metadata, agent-discoverable resource surfaces.

Added

  • Field aliases — registry expanded from ~10 to ~51 canonical keys (~98% coverage of catalog statusFields + webhook payload fields)
  • safetyTier enum (5 tiers)read | mutation | ir-fire-forget | destructive | maintenance; replaces legacy destructive: boolean flag
  • DeviceCatalogEntry.statusQueries — read-tier catalog entries exposing queryable status fields; powers safetyTier: 'read' and capabilities.catalog.readOnlyQueryCount
  • capabilities.resources — new top-level resources block exposing scenes (list/execute/describe), webhooks (4 endpoints + 15 event specs + constraints), and keypad keys (4 types). Each endpoint/event declares its safety tier
  • Multi-format output--format=yaml and --format=tsv for all non-streaming commands
  • doctor upgrades--section / --list / --fix / --yes / --probe flags; new checks catalog-schema, audit, mcp (dry-run); live MQTT probe (5 s timeout under --probe)
  • Streaming JSON contract — every streaming command emits a { schemaVersion, stream: true, eventKind, cadence } header as its first NDJSON line (docs/json-contract.md)
  • Events envelope — unified { schemaVersion, t, source, deviceId, topic, type, payload } across events tail and events mqtt-tail
  • MCP tool schema completeness — every tool input schema now carries .describe() annotations
  • Help-JSON contract test — table-driven coverage for all 16 top-level commands
  • batch --emit-plan — canonical alias for deprecated --plan

Changed

  • Error envelope — all error paths route through exitWithError() / handleError()
  • Quota accounting — records on attempt (request interceptor) instead of on success, so timeouts / 4xx / 5xx count against daily quota

Deprecated (all removed in v3.0)

  • destructive: boolean on catalog entries — derived from safetyTier === 'destructive'
  • DeviceCatalogEntry.statusFields — superseded by statusQueries
  • batch --plan — renamed to --emit-plan; old flag prints deprecation warning
  • events tail legacy body / remote fields — superseded by unified envelope

Fixed

  • Quota counter no longer under-counts requests that fail at the transport or server layer

Install: npm install -g @switchbot/openapi-cli

Full changelog: CHANGELOG.md

Compare: v2.6.4...v2.7.2

2.6.4

21 Apr 09:58
c4e869e

Choose a tag to compare

Added

  • devices describe now shows a tip for device types that support devices expand (Air Conditioner, Curtain, Curtain 3, Blind Tilt, Relay Switch 2PM); --json output includes an expandHint field with command, flags, and a ready-to-run example string

Fixed

  • --filter controlType=X now works correctly; controlType was documented as a filterable key but was missing from the canonical key registry
  • field-aliases.ts: removed category from the controlType alias list to prevent collision with the physical/IR category filter key
  • MCP stdio path now handles SIGTERM and SIGINT with the same graceful shutdown as the HTTP path (30 s force-exit timeout, isShuttingDown guard)

Changed

  • Extracted exitWithError() helper in output.ts; deduplicated isJsonMode() across index.ts and config.ts

v2.6.3

21 Apr 04:22
b01f8b4

Choose a tag to compare

Fixed

  • MCP send_command dry-run now strictly rejects unknown command names when catalog has a definitive match (#55)
  • MCP send_command dry-run rejects commands sent to read-only sensors (e.g. Meter)
  • Previous v2.6.2 fix used lenient validateCommand which silently passed when catalog lookup was ambiguous

2.6.2

21 Apr 03:46
3d55373

Choose a tag to compare

Fixed

  • scenes execute --dry-run now outputs structured result on stdout (#54)
  • MCP send_command dry-run validates command name against catalog (#55)
  • MCP run_scene dry-run validates sceneId against scene list (#56)

v2.6.1

21 Apr 01:26
683cbef

Choose a tag to compare

See CHANGELOG for the full list of changes.

v2.6.0

21 Apr 00:40
6c6addf

Choose a tag to compare

See CHANGELOG.md for the full list of changes.

v2.5.1

20 Apr 15:58
58a6005

Choose a tag to compare

Round-2 + Round-3 smoke-test response — 24 bugs closed in one patch.

Breaking: --filter grammar unified across devices list, devices batch, events tail / mqtt-tail. devices batch and events tail = is now substring (was exact); ~= spelling removed (use ~). See CHANGELOG §Changed (BREAKING) for migration.

Full notes: CHANGELOG.md

v2.5.0 — history aggregate + v2.4.0 report bug fixes

20 Apr 10:22
2a537ff

Choose a tag to compare

[2.5.0] - 2026-04-20

Added

  • history aggregate <deviceId> — on-demand bucketed statistics
    (count / min / max / avg / sum / p50 / p95) over the append-only JSONL
    device history. Flags: --since / --from / --to, repeatable
    --metric, --agg <csv>, --bucket <dur>,
    --max-bucket-samples <n>. Non-numeric samples are skipped; empty
    metrics are omitted from their bucket.
  • MCP aggregate_device_history — same contract as the CLI, exposed
    as a read-tier tool (_meta.agentSafetyTier: "read") with a strict
    Zod input schema (unknown keys reject with JSON-RPC -32602).
  • Capabilities manifest — new history aggregate entry in
    COMMAND_META; new aggregate_device_history entry in
    surfaces.mcp.tools.
  • scenes describe <sceneId> — returns {sceneId, sceneName, stepCount:null, note}; SwitchBot API v1.1 does not expose scene
    steps. Unknown sceneId returns structured scene_not_found with a
    candidate list. (bug #17)
  • --no-color flag + NO_COLOR env var — honors the standard
    https://no-color.org/ contract; disables chalk colors globally before
    any subcommand runs. (bug #12)
  • --format markdown — accepted as an alias for --format table
    with --table-style markdown forced at render time, independent of
    the user's --table-style flag. (bug #8)
  • cache status — alias for cache show, matching the quota
    subcommand's status/show parity. (bug #9)

Fixed (security & correctness — v2.4.0 report)

  • MCP strict input schemas on all 11 tools — unknown keys now
    reject with JSON-RPC -32602. Fixes the v2.4.0 hole where
    send_command {dryRun:true} silently fired the command anyway —
    particularly dangerous for Smart Lock / Garage. (bug #4)
  • MCP dryRun on mutating toolssend_command and run_scene
    accept dryRun:true; when set, no API call is made and the response
    is {ok:true, dryRun:true, wouldSend:{...}}. (bug #4)
  • MCP serverInfo.version — wired to package.json#version; was
    hardcoded "2.0.0" despite the CLI reporting the real version
    everywhere else. (bug #5)
  • MCP _meta.agentSafetyTier — every tool now emits its tier
    (read / action / destructive). Release notes already claimed
    this but no tool was actually emitting it. (bug #6)
  • --name require-unique + exact-match — exact-name short-circuit
    in name-resolver was returning the exact hit even when substring
    matches existed, defeating the write-path require-unique default.
    Exact hits now enter the candidate list under require-unique and
    go through the ambiguity check like any other match. (bug #1)
  • history verify on missing audit.log — exits 0 with status:"warn"
    and fileMissing:true rather than exit 1. Malformed/unversioned
    content still exits 1 as before. (bug #11)
  • events mqtt-tail control events__connect / __reconnect /
    __disconnect / __heartbeat now append to
    ~/.switchbot/device-history/__control.jsonl alongside per-device
    files, honoring the v2.4.0 "every event is persisted" claim. (bug #10)

Changed (docs)

  • --idempotency-key help text on devices command, devices batch,
    plan run, history replay now explicitly mentions the process-local
    60s scope — independent CLI invocations do NOT share the cache. (bug #14)
  • mcp --help now says "eleven tools" and lists all 11 names. (bug #15)
  • New docs/verbose-redaction.md — documents the nine masked headers
    (authorization, token, sign, nonce, x-api-key, cookie,
    set-cookie, x-auth-token, t) and the --trace-unsafe opt-out. (bug #16)
  • plan schema now includes agentNotes.deviceNameStrategy declaring
    that plan steps using deviceName resolve with require-unique. (bug #18)
  • agent-bootstrap hints field carries JSDoc + schema export
    declares it in cliAddedFields — empty array means "no hints",
    never null. (bug #13)

Notes

  • Storage format unchanged. Aggregation streams the existing JSONL
    rotation files via readline — zero memory blow-up for large
    windows, with a hard ceiling of --max-bucket-samples × 8 bytes per
    (bucket × metric) for quantile computation.
  • Quantiles use nearest-rank on sorted per-bucket samples; if the cap
    is reached the result carries partial: true and a per-bucket
    notes[] entry. count / min / max / avg / sum remain exact.
  • All bug-fix items bundled into 2.5.0 rather than shipping a separate
    2.4.1. Source of bug numbers: the v2.4.0 smoke-test report at
    D:/servicdata/openclaw/workspace/switchbot-cli-v2.4.0-report.md.

Not included (deferred)

  • Cross-device aggregation (agents merge locally).
  • Trend / rate-of-change helpers (derivable from bucket series).
  • --fill-empty for missing buckets.
  • Disk-persisted idempotency cache for cross-invocation replay
    (report bug #2). Process-local is the documented 2.4.0 contract;
    the --help text now states this plainly — no code change. Revisit
    only if a concrete use case forces it.
  • capabilities --types / --fields / --used (report bug #7).
    schema export already offers these for the agent bootstrap path;
    capabilities --compact --surface <s> covers the payload-size story.

v2.4.0 — Agent-experience overhaul + device history

20 Apr 05:53
7af8ef5

Choose a tag to compare

Highlights

2.4.0 bundles 19 OpenClaw/Claude integration feedback items (P0–P3) plus a new device-history query subsystem into a single minor release. All schema changes are additive-only — existing MCP and CLI integrations keep working unchanged and pick up the new fields on upgrade.

P0 — Correctness & security

  • IR command verifiabilitydevices command responses for IR devices now carry verification: { verifiable: false, reason, suggestedFollowup }; MCP send_command mirrors the field. Agents no longer treat one-way IR transmissions as verified success.
  • config set-token secret scrubbing — positional invocations have their token/secret replaced in process.argv before any hook, audit log, or verbose trace can observe them. Interactive hidden-echo readline is now the primary path.

P1 — Agent hardening

  • devices status / devices command accept --name directly on the subcommand (previously root-only).
  • New src/devices/resolve-name.ts with six strategies (exact | prefix | substring | fuzzy | first | require-unique). Reads default to fuzzy; writes default to require-unique and fail with exit code 2 + error: "ambiguous_name_match" and a candidate list when multiple devices match. Global filters --type, --room, --category, --name-strategy compose with --name.
  • schema export / capabilities gained --compact, --types <csv>, --used, --fields <csv>, --surface cli|mcp|plan. Banners/tips/progress messages go to stderr; stdout is exactly one JSON document; non-TTY no longer emits ANSI.
  • Every leaf command in capabilities carries { mutating, consumesQuota, idempotencySupported, agentSafetyTier: "read"|"action"|"destructive", verifiability, typicalLatencyMs }. MCP tools mirror the tier in meta.agentSafetyTier.

Device history — new subsystem

  • JSONL storage — every events mqtt-tail event / MCP status refresh is appended to ~/.switchbot/device-history/<deviceId>.jsonl. Files rotate at 50 MB (.jsonl.1 → .2 → .3, oldest discarded). Writes are best-effort with 0o600 perms.
  • history range <deviceId> — time-windowed query with --since 7d / --from <iso> / --to <iso>, payload-field projection via repeatable --field <name>, --limit <n> (default 1000). Uses streaming readline — even 50 MB files never load into memory.
  • history stats <deviceId> — reports file count, total bytes, record count, earliest/latest timestamp.
  • MCP query_device_history — same contract as the CLI, exposed as an agent tool with a 1000-record default safety cap.

P2 — DX & stability

  • doctor --json stable contract — locked shape { ok, generatedAt, checks[], summary }; each check is { name, status: ok|warn|fail, detail }. The clock check now probes the real API once and reports skewMs.
  • events mqtt-tail control events — synthesized JSONL records of __connect / __reconnect / __disconnect / __heartbeat. Every real event gets a UUIDv4 eventId when the broker doesn't supply one.
  • devices batch --stagger <ms> / --max-concurrent <n> / --plan — throttled concurrent execution with per-step startedAt / finishedAt / durationMs / replayed telemetry and a planner that prints the plan JSON without executing.
  • Idempotency contract + replayed flag — cache hits return replayed: true. A reused key with a different (command, parameter) shape within the 60 s window exits 2 with error: "idempotency_conflict" and the old/new shape in the payload. The cache is process-local in-memory (SHA-256 fingerprints on the heap; raw key never stored, no disk persistence) — replay + conflict apply within a single long-lived process (MCP session, devices batch, plan run, history replay) and do not carry across independent CLI invocations.
  • Profile label / description / daily cap / default flagsconfig set-token gained --label, --description, --daily-cap <N>, --default-flags "<csv>". The daily cap is enforced before any request leaves the CLI (pre-flight refusal, exit 2).
  • --verbose header redactionAuthorization, token, sign, t, nonce, cookies are mid-masked in verbose output. --trace-unsafe opts into raw output with a prominent one-time warning.

P3 — Polish

  • quota show alias for quota status.
  • showSuggestionAfterError across the full subcommand tree — typos like devices lst now suggest devices list.
  • schema export declares cliAddedFields_fetchedAt, replayed, verification — so agents can distinguish CLI-synthesized data from upstream API fields.
  • switchbot agent-bootstrap [--compact] — single-command aggregate (identity, cached devices, catalog, quota, profile, safety tiers, quick reference) that stays under 20 KB in --compact mode. Offline-safe; no API calls.
  • --table-style <unicode|ascii|simple|markdown> and --format markdown — non-TTY defaults to ascii; markdown emits fenced |col|col| tables for agent UI embedding.
  • Audit log versioning — every line carries "auditVersion": 1. New docs/audit-log.md documents the format, crash-safety, and rotation guidance. New switchbot history verify reports parsed / malformed / version counts and exits non-zero on malformed content.

Continuous integration

  • offline-smoke CI job — seeds a fixture device cache and asserts agent-bootstrap --compact < 20 KB and schema export --compact --used < 15 KB on every push / PR.
  • Smoke (real device) workflowworkflow_dispatch-only job that validates IR verification, --idempotency-key acceptance, and history range end-to-end against a live account.

Migration notes

Fully backwards compatible. No fields changed or were removed; only added. Existing MCP and CLI integrations continue to work. Agents that want the richer context can refresh their prompts by running switchbot agent-bootstrap --compact once per session instead of combining doctor + capabilities + schema + devices list.

See the full CHANGELOG for the complete list.