@oceanswave/openclaw-tescmd 0.3.1

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/skill.md ADDED
@@ -0,0 +1,737 @@
1
+ ---
2
+ name: openclaw-tescmd
3
+ version: 0.3.1
4
+ description: Agent handbook for Tesla vehicle control and telemetry via the tescmd node — covers 37 tools, 34 commands, 8 slash commands, and 14 telemetry event types.
5
+ homepage: https://github.com/oceanswave/openclaw-tescmd
6
+ metadata: {"category":"platform","platform":"tesla","node":"tescmd"}
7
+ ---
8
+
9
+ # OpenClaw Tesla (tescmd) — Agent Handbook
10
+
11
+ This plugin gives agents full control of a Tesla vehicle through the OpenClaw Gateway. It registers **37 agent-callable tools**, **34 whitelisted commands**, **8 slash commands**, and **14 telemetry event types** backed by real-time Fleet Telemetry streaming.
12
+
13
+ **Repositories:**
14
+ - Plugin (this repo): https://github.com/oceanswave/openclaw-tescmd
15
+ - tescmd node (Python CLI): https://github.com/oceanswave/tescmd
16
+
17
+ This document is an installation and configuration reference. Once installed, the plugin will automatically register tools, commands, and events.
18
+
19
+ ---
20
+
21
+ ## Architecture
22
+
23
+ ### System Layers
24
+
25
+ ```
26
+ Agent (you)
27
+ ↓ tool calls
28
+ OpenClaw Gateway
29
+ ↓ node.invoke.request
30
+ openclaw-tescmd Plugin
31
+ ├─ 37 Tools (schema + routing)
32
+ ├─ 34 Whitelisted Commands
33
+ ├─ 8 Slash Commands
34
+ └─ 14 Telemetry Event Types
35
+ ↓ WebSocket dispatch
36
+ tescmd Node (Python)
37
+ ├─ Tesla Fleet API (REST)
38
+ ├─ Vehicle Command Protocol (VCSEC — signed commands)
39
+ └─ Fleet Telemetry Stream (WebSocket)
40
+
41
+ Tesla Vehicle
42
+ ```
43
+
44
+ ### Three Operating Modes
45
+
46
+ | Mode | What It Does | Flag |
47
+ |------|-------------|------|
48
+ | **Full** (default) | MCP server + telemetry + OpenClaw bridge | `tescmd serve <VIN> --openclaw <url>` |
49
+ | **Bridge only** | Telemetry + OpenClaw, no MCP server | `--no-mcp` |
50
+ | **Dry run** | Log events as JSONL, no Gateway connection | `--dry-run` |
51
+
52
+ ### Data Flow
53
+
54
+ **Read path:** Agent calls read tool → Plugin routes to Gateway → Gateway dispatches `node.invoke.request` to tescmd node → Node checks in-memory telemetry store first (instant, free) → Falls back to Fleet API if telemetry unavailable (may need vehicle wake, slower).
55
+
56
+ **Write path:** Agent calls write tool → Plugin routes to Gateway → Gateway dispatches to node → Node sends command to vehicle via Fleet API or Vehicle Command Protocol (VCSEC for security commands) → Vehicle executes → Node returns result. Write commands auto-wake sleeping vehicles (billable API call).
57
+
58
+ **Telemetry path:** Vehicle → Tesla Fleet Telemetry stream → tescmd node filters/throttles → Node emits `req:agent` frames to Gateway → Gateway broadcasts to agents. Agents receive real-time events without polling.
59
+
60
+ ---
61
+
62
+ ## Setup
63
+
64
+ ### Step 1: Check Prerequisites
65
+
66
+ Before starting, verify the required tools are installed and authenticated.
67
+
68
+ #### Required: git
69
+
70
+ ```bash
71
+ git --version
72
+ ```
73
+
74
+ If missing, install it:
75
+ - macOS: `xcode-select --install`
76
+ - Linux: `sudo apt install git` or `sudo dnf install git`
77
+
78
+ #### Required: GitHub CLI (gh)
79
+
80
+ ```bash
81
+ gh --version
82
+ gh auth status
83
+ ```
84
+
85
+ If `gh` is not installed:
86
+ - macOS: `brew install gh`
87
+ - Linux: see https://github.com/cli/cli/blob/trunk/docs/install_linux.md
88
+
89
+ If not logged in:
90
+ ```bash
91
+ gh auth login
92
+ ```
93
+
94
+ **Tell the user:** "Please complete the GitHub CLI login in your terminal. Select your preferences when prompted and finish the browser-based auth flow."
95
+
96
+ Wait for the user to confirm they have completed the login before continuing.
97
+
98
+ #### Required: Python 3.11+
99
+
100
+ ```bash
101
+ python3 --version
102
+ ```
103
+
104
+ Must be 3.11 or higher. If not:
105
+ - macOS: `brew install python@3.12`
106
+ - Linux: `sudo apt install python3.12` or use pyenv
107
+
108
+ #### Recommended: Tailscale
109
+
110
+ Tailscale provides a public HTTPS endpoint for Tesla Fleet Telemetry streaming with zero infrastructure setup.
111
+
112
+ ```bash
113
+ tailscale version
114
+ tailscale status
115
+ ```
116
+
117
+ If not installed:
118
+ - macOS: `brew install tailscale` or download from https://tailscale.com/download
119
+ - Linux: `curl -fsSL https://tailscale.com/install.sh | sh`
120
+
121
+ If not logged in:
122
+ ```bash
123
+ sudo tailscale up
124
+ ```
125
+
126
+ **Tell the user:** "Please complete the Tailscale login in your browser if prompted."
127
+
128
+ Wait for the user to confirm before continuing.
129
+
130
+ ---
131
+
132
+ ### Step 2: Install the tescmd OpenClaw Plugin
133
+
134
+ #### Standard install:
135
+
136
+ ```bash
137
+ openclaw plugins install @oceanswave/openclaw-tescmd
138
+ ```
139
+
140
+ #### Development install (symlink, editable):
141
+
142
+ ```bash
143
+ git clone https://github.com/oceanswave/openclaw-tescmd.git
144
+ cd openclaw-tescmd && bun install && cd ..
145
+ openclaw plugins install -l ./openclaw-tescmd
146
+ ```
147
+
148
+ #### Verify installation:
149
+
150
+ ```bash
151
+ openclaw plugins list
152
+ openclaw tescmd status
153
+ ```
154
+
155
+ You should see the plugin listed and the status showing 34 whitelisted commands and 14 telemetry event types.
156
+
157
+ #### Plugin management commands:
158
+
159
+ | Command | Purpose |
160
+ |---------|---------|
161
+ | `openclaw plugins list` | List installed plugins |
162
+ | `openclaw plugins info openclaw-tescmd` | Plugin details |
163
+ | `openclaw plugins doctor` | Check plugin health |
164
+ | `openclaw plugins update openclaw-tescmd` | Update to latest |
165
+ | `openclaw plugins enable openclaw-tescmd` | Enable the plugin |
166
+ | `openclaw plugins disable openclaw-tescmd` | Disable without uninstalling |
167
+
168
+ ---
169
+
170
+ ### Step 3: Install the tescmd CLI
171
+
172
+ ```bash
173
+ pip install tescmd
174
+ ```
175
+
176
+ Verify:
177
+ ```bash
178
+ tescmd --version
179
+ ```
180
+
181
+ ---
182
+
183
+ ### Step 4: Run tescmd Setup
184
+
185
+ The tescmd setup wizard is **interactive** and requires the user to make choices and complete steps in their terminal and browser. You cannot complete this step autonomously.
186
+
187
+ ```bash
188
+ tescmd setup
189
+ ```
190
+
191
+ **Tell the user:** "I've started the tescmd setup wizard. This is an interactive process that will walk you through:"
192
+ 1. Creating a Tesla Developer application
193
+ 2. Generating your EC key pair
194
+ 3. Hosting your public key (via GitHub Pages or Tailscale Funnel)
195
+ 4. Registering with the Tesla Fleet API
196
+ 5. Completing OAuth2 login in your browser
197
+ 6. Pairing the key with your vehicle (requires physical presence at the vehicle)
198
+
199
+ "Please follow the prompts in your terminal and let me know when setup is complete."
200
+
201
+ **Wait for the user to confirm setup is finished before proceeding.**
202
+
203
+ #### Verify Setup
204
+
205
+ After the user confirms, check auth status:
206
+ ```bash
207
+ tescmd auth status
208
+ ```
209
+
210
+ This should show a valid token. If it shows expired or missing, the user needs to re-run:
211
+ ```bash
212
+ tescmd auth login
213
+ ```
214
+
215
+ ---
216
+
217
+ ### Step 5: Identify the Vehicle
218
+
219
+ List vehicles on the account to get the VIN:
220
+ ```bash
221
+ tescmd vehicle list
222
+ ```
223
+
224
+ Note the VIN — it is needed for the serve command.
225
+
226
+ ---
227
+
228
+ ### Step 6: Start the tescmd Node
229
+
230
+ The node bridges the Tesla Fleet API to the OpenClaw Gateway. It needs:
231
+ - The vehicle's VIN
232
+ - The Gateway's WebSocket URL
233
+ - A Gateway authentication token
234
+
235
+ #### Full mode (MCP server + telemetry + OpenClaw bridge):
236
+ ```bash
237
+ tescmd serve <VIN> --openclaw <gateway_ws_url> --openclaw-token <gateway_token>
238
+ ```
239
+
240
+ #### OpenClaw bridge only (no MCP server):
241
+ ```bash
242
+ tescmd serve <VIN> --no-mcp --openclaw <gateway_ws_url> --openclaw-token <gateway_token>
243
+ ```
244
+
245
+ #### With Tailscale (exposes MCP via Tailscale Funnel):
246
+ ```bash
247
+ tescmd serve <VIN> --tailscale --openclaw <gateway_ws_url> --openclaw-token <gateway_token>
248
+ ```
249
+
250
+ #### Key flags reference:
251
+ | Flag | Description |
252
+ |------|-------------|
253
+ | `<VIN>` | Vehicle Identification Number (positional) |
254
+ | `--openclaw <ws_url>` | Gateway WebSocket URL (e.g. `ws://host:18789`) |
255
+ | `--openclaw-token <token>` | Gateway authentication token |
256
+ | `--openclaw-config <path>` | Bridge config JSON (default: `~/.config/tescmd/bridge.json`) |
257
+ | `--transport <type>` | MCP transport: `streamable-http` (default) or `stdio` |
258
+ | `--port <num>` | MCP HTTP port (default: 8080) |
259
+ | `--host <addr>` | MCP bind address (default: 127.0.0.1) |
260
+ | `--telemetry-port <num>` | Telemetry WebSocket port (default: 4443) |
261
+ | `--fields <preset>` | Telemetry fields: `driving`, `charging`, or `all` |
262
+ | `--interval <sec>` | Telemetry polling interval in seconds |
263
+ | `--no-telemetry` | Disable telemetry streaming |
264
+ | `--no-mcp` | Disable MCP server |
265
+ | `--no-log` | Disable CSV telemetry logging |
266
+ | `--dry-run` | Log events as JSONL without connecting to Gateway |
267
+ | `--tailscale` | Expose MCP via Tailscale Funnel |
268
+ | `--client-id <id>` | MCP OAuth client ID |
269
+ | `--client-secret <secret>` | MCP OAuth client secret |
270
+
271
+ #### Environment variables (alternative to flags):
272
+ These can be set in `~/.config/tescmd/.env`:
273
+ ```bash
274
+ TESLA_CLIENT_ID=your-client-id
275
+ TESLA_CLIENT_SECRET=your-client-secret
276
+ TESLA_VIN=5YJ3E1EA1NF000000
277
+ TESLA_REGION=na # na, eu, or cn
278
+ OPENCLAW_GATEWAY_URL=ws://gateway.example.com:18789
279
+ OPENCLAW_GATEWAY_TOKEN=your-token
280
+ TESLA_COMMAND_PROTOCOL=auto # auto, signed, or unsigned
281
+ ```
282
+
283
+ ---
284
+
285
+ ### Step 7: Verify the Connection
286
+
287
+ Once the node is running, confirm it connected to the Gateway:
288
+ ```bash
289
+ openclaw tescmd status
290
+ ```
291
+
292
+ Or use the agent tool:
293
+ - Call `tescmd_node_status` to check connection status
294
+
295
+ If connected, you now have access to all 37 Tesla vehicle tools.
296
+
297
+ ---
298
+
299
+ ## Agent Behavior Guide
300
+
301
+ ### Session Start Protocol
302
+
303
+ **Always call `tescmd_node_status` first** before invoking any vehicle command in a new conversation. If the node is offline, all other vehicle tools will fail. Suggest starting one:
304
+ ```
305
+ tescmd serve <VIN> --openclaw <gateway_url> --openclaw-token <token>
306
+ ```
307
+
308
+ ### Read Before Write
309
+
310
+ Always check current state before sending write commands:
311
+ - Before `tescmd_start_charge` → call `tescmd_get_charge_state` (is cable connected?)
312
+ - Before `tescmd_climate_on` → call `tescmd_get_temperature` (what's the current temp?)
313
+ - Before `tescmd_sentry_on` → call `tescmd_get_battery` (is battery too low for sentry?)
314
+ - Before `tescmd_homelink` → call `tescmd_get_location` (need lat/lon for proximity check)
315
+ - Before `tescmd_nav_supercharger` → call `tescmd_get_battery` (does the user actually need to charge?)
316
+
317
+ ### Confirm Before Sensitive Actions
318
+
319
+ These actions require explicit user confirmation before executing:
320
+ - **`tescmd_unlock_doors`** — Grants physical access to the vehicle. Never unlock proactively.
321
+ - **`tescmd_open_frunk`** — Cannot be closed remotely; must be physically pushed down.
322
+ - **`tescmd_honk_horn`** — Audible alert in public; may disturb others.
323
+ - **Starting charge** when battery is above 90% — User may not want to charge to 100% daily.
324
+
325
+ ### Escalation Rules
326
+
327
+ Escalate to the user (ask, don't act) when:
328
+ - Any security-related action (unlock, sentry off) without explicit request
329
+ - Node is offline and cannot auto-recover
330
+ - Vehicle is asleep and the action would trigger a billable wake-up
331
+ - Rate limits are hit — suggest waiting rather than retrying
332
+ - Auth tokens are expired — user needs to re-authenticate manually
333
+
334
+ ### Proactive Monitoring via Triggers
335
+
336
+ When the user asks you to "keep an eye on" something, set up triggers instead of polling:
337
+ - "Watch my battery" → `tescmd_battery_trigger` with operator='lt', value=20
338
+ - "Alert if the cabin gets hot" → `tescmd_cabin_temp_trigger` with operator='gt', value=100
339
+ - "Tell me if the car moves" → `tescmd_location_trigger` with operator='leave'
340
+ - Then periodically call `tescmd_poll_triggers` to check for fired notifications.
341
+
342
+ ### Battery-Aware Decision Making
343
+
344
+ Before enabling battery-draining features:
345
+ 1. Check battery level with `tescmd_get_battery`
346
+ 2. If battery < 20%, warn the user before enabling Sentry Mode (~1-2%/hr drain)
347
+ 3. If battery < 10%, strongly advise against Sentry Mode and suggest charging
348
+ 4. Climate pre-conditioning uses battery too — mention this on low charge
349
+
350
+ ---
351
+
352
+ ## Tool Reference
353
+
354
+ ### System & Meta Tools
355
+
356
+ | Tool | Use When... | Parameters | Returns |
357
+ |------|------------|------------|---------|
358
+ | `tescmd_node_status` | **Session start**, diagnostics, before first command | _none_ | `{connected, node_id?, platform, commands_available?, last_seen?}` |
359
+ | `tescmd_help` | Need detailed workflow recipes, error handling reference, or tescmd CLI commands | `topic?` (tools, workflows, triggers, errors, telemetry, setup, cli, all) | Markdown reference text |
360
+ | `tescmd_run_command` | Need a command without a dedicated tool, or method name is dynamic | `method` (string), `params?` (object) | Varies by command |
361
+
362
+ ### Reading Vehicle State (no side effects, safe to call anytime)
363
+
364
+ | Tool | Use When... | Parameters | Returns |
365
+ |------|------------|------------|---------|
366
+ | `tescmd_get_location` | "Where is my car?", need GPS, proximity checks, before HomeLink | _none_ | `{latitude, longitude, heading, speed}` |
367
+ | `tescmd_get_battery` | Charge level, range, "do I need to charge?", trip planning | _none_ | `{battery_level, range_miles}` |
368
+ | `tescmd_get_speed` | "Is the car moving?", verify parked before commands | _none_ | `{speed_mph}` |
369
+ | `tescmd_get_charge_state` | "Is it charging?", before start/stop charge | _none_ | `{charge_state}` — Charging, Complete, Stopped, Disconnected |
370
+ | `tescmd_get_temperature` | "Is the car hot/cold?", before climate decisions | _none_ | `{inside_temp_c, outside_temp_c}` |
371
+ | `tescmd_get_security` | "Is my car locked?", sentry status, before lock/unlock | _none_ | `{locked, sentry_mode}` |
372
+
373
+ **Data source priority:** All reads check in-memory telemetry first (instant, zero cost when streaming). Falls back to Fleet API (may require vehicle wake, slower, cached 30s-1h TTL).
374
+
375
+ ### Vehicle Control (side effects — confirm intent when appropriate)
376
+
377
+ | Tool | Use When... | Parameters | Returns |
378
+ |------|------------|------------|---------|
379
+ | `tescmd_lock_doors` | User wants to lock; part of parking workflow | _none_ | `{result: true, reason: 'ok'}` |
380
+ | `tescmd_unlock_doors` | **User explicitly asks** — always confirm first | _none_ | `{result: true, reason: 'ok'}` |
381
+ | `tescmd_climate_on` | Precondition cabin, "warm up/cool down the car" | _none_ | `{result: true, reason: 'ok'}` |
382
+ | `tescmd_climate_off` | Stop climate, save battery | _none_ | `{result: true, reason: 'ok'}` |
383
+ | `tescmd_set_climate_temp` | "Set it to 72 degrees" — takes **Fahrenheit** | `temp` (number, °F) | `{result: true, reason: 'ok'}` |
384
+ | `tescmd_start_charge` | Start charging — verify cable connected first | _none_ | `{result: true, reason: 'ok'}` |
385
+ | `tescmd_stop_charge` | Stop an active charge session | _none_ | `{result: true, reason: 'ok'}` |
386
+ | `tescmd_set_charge_limit` | "Charge to 80%" — 50-100 range | `percent` (50-100) | `{result: true, reason: 'ok'}` |
387
+ | `tescmd_open_trunk` | Open/close rear trunk (toggles on power liftgate models) | _none_ | `{result: true, reason: 'ok'}` |
388
+ | `tescmd_open_frunk` | Open front trunk — **cannot close remotely** | _none_ | `{result: true, reason: 'ok'}` |
389
+ | `tescmd_flash_lights` | Locate vehicle, visual signal | _none_ | `{result: true, reason: 'ok'}` |
390
+ | `tescmd_honk_horn` | Locate vehicle, audible signal | _none_ | `{result: true, reason: 'ok'}` |
391
+ | `tescmd_sentry_on` | Camera monitoring — uses ~1-2% battery/hr | _none_ | `{result: true, reason: 'ok'}` |
392
+ | `tescmd_sentry_off` | Stop camera monitoring, reduce battery drain | _none_ | `{result: true, reason: 'ok'}` |
393
+
394
+ ### Navigation (send destinations to the vehicle)
395
+
396
+ | Tool | Use When... | Parameters | Returns |
397
+ |------|------------|------------|---------|
398
+ | `tescmd_nav_send` | "Navigate to [place]", send address/place name | `address` (string) | Destination sent |
399
+ | `tescmd_nav_gps` | Have exact lat/lon coordinates | `lat`, `lon`, `order?` (waypoint order) | Coordinates sent |
400
+ | `tescmd_nav_supercharger` | "Find a Supercharger", low battery | _none_ | Routing to nearest |
401
+ | `tescmd_nav_waypoints` | Multi-stop road trip with Google Place IDs | `waypoints` (comma-separated refIds) | Route sent |
402
+ | `tescmd_homelink` | "Open the garage" — needs vehicle GPS | `lat`, `lon` (from `tescmd_get_location`) | HomeLink triggered |
403
+
404
+ ### Triggers (telemetry subscriptions)
405
+
406
+ | Tool | Use When... | Parameters | Returns |
407
+ |------|------------|------------|---------|
408
+ | `tescmd_create_trigger` | Subscribe to any telemetry condition | `field`, `operator`, `value?`, `once?`, `cooldown_seconds?` | `{id, field, operator}` |
409
+ | `tescmd_battery_trigger` | Low battery alert shortcut | `operator`, `value?`, `once?`, `cooldown_seconds?` | `{id, field, operator}` |
410
+ | `tescmd_cabin_temp_trigger` | Hot/cold cabin alert shortcut | `operator`, `value?`, `once?`, `cooldown_seconds?` | `{id, field, operator}` |
411
+ | `tescmd_outside_temp_trigger` | Weather/freezing alert shortcut | `operator`, `value?`, `once?`, `cooldown_seconds?` | `{id, field, operator}` |
412
+ | `tescmd_location_trigger` | Geofence (enter/leave area) | `operator` (enter/leave), `lat?`, `lon?`, `radius?`, `value?`, `once?`, `cooldown_seconds?` | `{id, field, operator}` |
413
+ | `tescmd_list_triggers` | Check what triggers are active | _none_ | `{triggers: [{id, field, operator, value, once, cooldown_seconds}]}` |
414
+ | `tescmd_poll_triggers` | Check for fired trigger notifications | _none_ | `{notifications: [{trigger_id, field, value, fired_at}]}` |
415
+ | `tescmd_delete_trigger` | Remove a trigger no longer needed | `id` (string) | `{deleted, id}` |
416
+
417
+ **Trigger fields:** Soc, BatteryLevel, InsideTemp, OutsideTemp, VehicleSpeed, ChargeState, DetailedChargeState, Locked, SentryMode, Location, Gear, EstBatteryRange
418
+
419
+ **Trigger operators:** `lt`, `gt`, `lte`, `gte`, `eq`, `neq` (numeric); `changed` (any change); `enter`, `leave` (geofence)
420
+
421
+ ---
422
+
423
+ ## Workflows & Decision Trees
424
+
425
+ ### Intent-Based Routing
426
+
427
+ When the user mentions... → Start with:
428
+
429
+ | User Intent | First Tool | Then... |
430
+ |-------------|-----------|---------|
431
+ | Charging | `tescmd_get_charge_state` | Assess → start/stop/set limit |
432
+ | Temperature, comfort | `tescmd_get_temperature` | Assess → climate on/off/set temp |
433
+ | Security, locking | `tescmd_get_security` | Assess → lock/unlock/sentry |
434
+ | Location, directions | `tescmd_get_location` | Report or navigate |
435
+ | Battery, range | `tescmd_get_battery` | Report or suggest charging |
436
+ | "Watch the car" | `tescmd_lock_doors` | Then sentry + geofence trigger |
437
+ | "Status", "how's the car" | `tescmd_get_battery` | Then charge_state + temperature + security + location |
438
+
439
+ ### Workflow 1: "Is my car ready to go?"
440
+
441
+ 1. `tescmd_get_battery` → check charge level and range
442
+ 2. `tescmd_get_charge_state` → check if still charging
443
+ 3. `tescmd_get_temperature` → check cabin comfort
444
+ 4. `tescmd_get_security` → verify doors are locked
445
+ 5. Summarize: battery %, range, charging status, cabin temp, lock state
446
+
447
+ ### Workflow 2: "Precondition the cabin"
448
+
449
+ 1. `tescmd_get_temperature` → check current cabin temp
450
+ 2. `tescmd_climate_on` → start climate control
451
+ 3. Optionally: `tescmd_set_climate_temp` → set specific temperature
452
+ 4. Confirm: "Climate control is on, targeting X°F"
453
+
454
+ ### Workflow 3: "Set up for overnight charging"
455
+
456
+ **Pre-check:** Call `tescmd_get_charge_state` to verify cable is connected. If 'Disconnected', tell the user to plug in first.
457
+
458
+ 1. `tescmd_set_charge_limit` → set to user's desired limit (typically 80%)
459
+ 2. `tescmd_start_charge` → begin charging
460
+ 3. Optionally: `tescmd_battery_trigger` → alert when charge reaches target
461
+
462
+ ### Workflow 4: "Keep an eye on the car" (parking/security)
463
+
464
+ 1. `tescmd_lock_doors` → ensure locked
465
+ 2. `tescmd_sentry_on` → enable camera monitoring (warn about ~1-2%/hr battery drain)
466
+ 3. `tescmd_location_trigger` → geofence alert if car moves
467
+ 4. Confirm setup
468
+
469
+ ### Workflow 5: "Navigate somewhere"
470
+
471
+ 1. `tescmd_nav_send` → pass the address or place name
472
+ 2. Or: `tescmd_nav_gps` → if you have exact lat/lon coordinates
473
+ 3. For multi-stop: `tescmd_nav_waypoints` → comma-separated Place IDs
474
+
475
+ ### Workflow 6: "Open the garage"
476
+
477
+ 1. `tescmd_get_location` → get the vehicle's current GPS
478
+ 2. `tescmd_homelink` → pass lat/lon to trigger HomeLink
479
+
480
+ ### Workflow 7: "Find my car"
481
+
482
+ 1. `tescmd_get_location` → get GPS coordinates
483
+ 2. `tescmd_flash_lights` → visual signal
484
+ 3. Optionally: `tescmd_honk_horn` → audible signal
485
+
486
+ ### Workflow 8: "Hot car alert"
487
+
488
+ 1. `tescmd_cabin_temp_trigger` with operator='gt', value=100 → alert over 100°F
489
+ 2. When triggered: `tescmd_climate_on` → auto-start climate
490
+ 3. `tescmd_get_temperature` → verify cooling
491
+
492
+ ---
493
+
494
+ ## Error Handling & Recovery
495
+
496
+ ### Node Offline
497
+
498
+ If commands fail with "no node connected" or similar:
499
+ 1. Call `tescmd_node_status` to confirm the node is offline
500
+ 2. Tell the user: "No tescmd node is connected. Start one with:"
501
+ `tescmd serve <VIN> --openclaw <gateway_url> --openclaw-token <token>`
502
+ 3. Do not retry vehicle commands — they will all fail until the node reconnects
503
+
504
+ ### Vehicle Asleep
505
+
506
+ Write commands auto-wake the vehicle, but this is a **billable API call**.
507
+ - If a read returns `{pending: true}`, data is being fetched. Wait 3-5 seconds and retry.
508
+ - If wake fails (rare), suggest the user wake from the Tesla app (free).
509
+ - Avoid unnecessary write commands to sleeping vehicles — check state with reads first.
510
+ - Reads from telemetry are instant and don't require a wake.
511
+
512
+ ### Authentication Expired
513
+
514
+ If commands fail with auth/token errors:
515
+ - The tescmd node handles token refresh automatically.
516
+ - If refresh fails, the user needs to re-authenticate: `tescmd auth login`
517
+ - Check auth status: `tescmd auth status`
518
+ - If persistent, re-run: `tescmd setup`
519
+
520
+ ### Rate Limiting
521
+
522
+ Tesla's API has rate limits (429 responses). tescmd caches read responses to minimize API calls:
523
+ - Static data (specs, warranty): cached 1 hour
524
+ - Fleet lists: cached 5 minutes
525
+ - Standard queries: cached 1 minute
526
+ - Location/speed: cached 30 seconds
527
+ - If you get rate limit errors, **wait and avoid rapid repeated calls**. Do not retry immediately.
528
+
529
+ ### Command Failures
530
+
531
+ If a write command fails:
532
+ - Check if the vehicle is in a valid state (e.g., charge cable connected for `charge.start`)
533
+ - Check if the vehicle is online (call `tescmd_node_status`)
534
+ - Try `tescmd_run_command` as a fallback — it accepts both dot-notation and Fleet API names
535
+
536
+ ### Trigger Failures
537
+
538
+ If triggers aren't working:
539
+ - "Triggers not available" → Node started without telemetry. Restart with telemetry enabled (remove `--no-telemetry`).
540
+ - Triggers require the telemetry stream to be active to detect condition changes.
541
+ - Check `tescmd_list_triggers` to verify the trigger was created.
542
+
543
+ ### Common Error Pattern Table
544
+
545
+ | Error | Cause | Resolution |
546
+ |-------|-------|------------|
547
+ | "no node connected" | tescmd node is not running or disconnected | Start node: `tescmd serve <VIN> --openclaw <url> --openclaw-token <token>` |
548
+ | "no handler configured" | Node has no dispatcher registered | Restart node with full serve command |
549
+ | "unknown command: X" | Command not in the 34-command whitelist | Check tool reference or use `tescmd_run_command` |
550
+ | "handler timeout (30s)" | Vehicle/API unresponsive | Retry after brief wait; vehicle may be in a dead zone |
551
+ | `{pending: true}` | Data being fetched from API | Retry in 3-5 seconds — vehicle is waking or API is slow |
552
+ | "Triggers not available" | Node started without telemetry | Restart with `--fields all` or remove `--no-telemetry` |
553
+ | Auth/token errors | OAuth2 token expired and refresh failed | User runs `tescmd auth login` |
554
+ | 429 / rate limit | Too many API calls | Wait 30-60 seconds; reduce call frequency |
555
+ | "vehicle offline" | Vehicle has no cellular connectivity | User must move vehicle to an area with signal |
556
+ | "charge cable not connected" | Attempted `charge.start` without cable | Tell user to plug in the charge cable |
557
+ | "not signed in" | No Tesla account linked | User runs `tescmd setup` from scratch |
558
+ | "command protocol mismatch" | Signed command failed, unsigned fallback needed | Set `TESLA_COMMAND_PROTOCOL=unsigned` in `.env` or pass flag |
559
+
560
+ ---
561
+
562
+ ## Cost & Impact Awareness
563
+
564
+ ### Wake-Ups Are Billable
565
+
566
+ Every write command to a sleeping vehicle triggers a wake-up API call. Tesla counts these. Minimize unnecessary wake-ups by:
567
+ - Checking state with reads first (reads from telemetry don't wake)
568
+ - Batching multiple write commands in one session rather than waking for each
569
+ - Using triggers instead of polling for condition changes
570
+
571
+ ### Sentry Mode Drains Battery
572
+
573
+ Sentry Mode uses ~1-2% battery per hour. Before enabling:
574
+ 1. Check battery with `tescmd_get_battery`
575
+ 2. If below 20%, warn the user about the drain
576
+ 3. If below 10%, strongly advise against it
577
+
578
+ ### Telemetry Reads Are Free When Streaming
579
+
580
+ When the telemetry stream is active, all read tools pull from the node's in-memory store — no API calls, no wake-ups, instant response. This is the optimal operating mode.
581
+
582
+ When telemetry is offline (node started with `--no-telemetry`), reads fall back to the Fleet API which:
583
+ - May require waking the vehicle
584
+ - Are subject to rate limits
585
+ - Are cached (30s-1h TTL depending on data type)
586
+
587
+ ### Rate Limit Budget
588
+
589
+ Tesla's Fleet API rate limits apply per-vehicle. Approximate budget:
590
+ - ~200 requests/day for most endpoints
591
+ - Location/speed endpoints have tighter limits
592
+ - Cached reads don't count (served from node memory)
593
+ - Write commands always hit the API
594
+
595
+ ---
596
+
597
+ ## Anti-Patterns
598
+
599
+ | Don't Do This | Why | Do This Instead |
600
+ |---------------|-----|-----------------|
601
+ | Call `tescmd_start_charge` without checking charge state | Will fail if cable is not connected | Call `tescmd_get_charge_state` first |
602
+ | Call `tescmd_unlock_doors` without user confirmation | Grants physical access — security risk | Always confirm: "Do you want me to unlock the doors?" |
603
+ | Call `tescmd_open_frunk` without warning | Cannot be closed remotely | Warn: "The frunk can only be closed by hand. Open it?" |
604
+ | Enable Sentry Mode on low battery (<20%) | Sentry drains ~1-2%/hr — could kill the battery | Check battery first, warn about drain |
605
+ | Repeatedly wake a sleeping vehicle | Each wake is a billable API call | Batch commands, use telemetry for reads |
606
+ | Ignore `{pending: true}` responses | Data is still loading | Wait 3-5 seconds and retry once |
607
+ | Set temperature in Celsius | `tescmd_set_climate_temp` takes **Fahrenheit** | Convert to °F: `(C × 9/5) + 32` |
608
+ | Read temperature expecting Fahrenheit | `tescmd_get_temperature` returns **Celsius** | Convert to °F if user expects it |
609
+ | Poll in a loop instead of using triggers | Wastes API calls and may hit rate limits | Use `tescmd_create_trigger` + `tescmd_poll_triggers` |
610
+ | Send multiple nav destinations rapidly | Only the last one takes effect | Send one destination, confirm it appeared |
611
+ | Skip `tescmd_node_status` at session start | All commands will fail silently if node is offline | Always check connectivity first |
612
+ | Assume `tescmd_get_location` returns before `tescmd_homelink` | HomeLink needs lat/lon from location | Chain: get_location → extract lat/lon → homelink |
613
+
614
+ ---
615
+
616
+ ## Troubleshooting
617
+
618
+ | Problem | Solution |
619
+ |---------|----------|
620
+ | "no node connected" | Start the node: `tescmd serve <VIN> --openclaw <url> --openclaw-token <token>` |
621
+ | Auth/token errors | Re-authenticate: `tescmd auth login` |
622
+ | Vehicle asleep / pending responses | Write commands auto-wake. If wake fails, wake from Tesla app. Wait 3-5s and retry reads. |
623
+ | Rate limit (429) | Wait 30-60s and reduce call frequency. Reads are cached (30s-1h TTL). |
624
+ | "no handler configured" | Restart node with full `tescmd serve` command |
625
+ | Setup wizard issues | Re-run `tescmd setup` or check https://github.com/oceanswave/tescmd |
626
+ | Triggers not firing | Verify telemetry is enabled (no `--no-telemetry` flag). Check `tescmd_list_triggers`. |
627
+ | Triggers say "not available" | Restart node with telemetry: remove `--no-telemetry` or add `--fields all` |
628
+ | Commands return "unknown command" | Command not in whitelist. Use `tescmd_run_command` with the correct method name. |
629
+ | Temperature values seem wrong | Reads return °C, set_climate_temp takes °F. Convert as needed. |
630
+ | Frunk won't close | The frunk **cannot** be closed remotely. Must be physically pushed down. |
631
+ | HomeLink won't trigger | Vehicle must be near the programmed device. Get location first, pass lat/lon. |
632
+ | Plugin not loading | Run `openclaw plugins doctor`. Check `openclaw plugins list` for the plugin entry. |
633
+ | Node connects then disconnects | Check Gateway URL/token. Run `tescmd auth status` to verify Tesla auth. |
634
+
635
+ ---
636
+
637
+ ## Telemetry Events
638
+
639
+ The tescmd node streams these events to the Gateway via `req:agent` frames. Each event includes `event_type`, `source` (client_id), `vin`, `timestamp` (ISO 8601), and `data`.
640
+
641
+ ### Data Events (11)
642
+
643
+ | Event Type | Data Fields | Filter Threshold | Throttle |
644
+ |------------|------------|-----------------|----------|
645
+ | `location` | latitude, longitude, heading, speed | 50m movement | 1s |
646
+ | `battery` | battery_level, range_miles | Soc: 5% / BatteryLevel: 1% / EstBatteryRange: 5mi | 10s / 10s / 30s |
647
+ | `inside_temp` | inside_temp_f | 5°F change | 30s |
648
+ | `outside_temp` | outside_temp_f | 5°F change | 30s |
649
+ | `speed` | speed_mph | 5mph change | 2s |
650
+ | `charge_started` | state | Immediate | None |
651
+ | `charge_complete` | state | Immediate | None |
652
+ | `charge_stopped` | state | Immediate | None |
653
+ | `charge_state_changed` | state | Immediate | None |
654
+ | `security_changed` | field (locked/sentrymode), value | Immediate | None |
655
+ | `gear_changed` | gear (P/R/N/D) | Immediate | None |
656
+
657
+ ### Lifecycle Events (3)
658
+
659
+ | Event Type | Data Fields | When |
660
+ |------------|------------|------|
661
+ | `node.connected` | client_id | Node connects to Gateway |
662
+ | `node.disconnecting` | client_id | Node is shutting down |
663
+ | `trigger.fired` | trigger_id, field, value | A trigger condition was met |
664
+
665
+ ### Tesla Telemetry Field → Event Mapping
666
+
667
+ | Fleet Telemetry Field | OpenClaw Event |
668
+ |----------------------|----------------|
669
+ | Location | `location` |
670
+ | Soc | `battery` |
671
+ | BatteryLevel | `battery` |
672
+ | EstBatteryRange | `battery` |
673
+ | InsideTemp | `inside_temp` |
674
+ | OutsideTemp | `outside_temp` |
675
+ | VehicleSpeed | `speed` |
676
+ | ChargeState | `charge_started` / `charge_complete` / `charge_stopped` |
677
+ | DetailedChargeState | `charge_state_changed` |
678
+ | Locked | `security_changed` |
679
+ | SentryMode | `security_changed` |
680
+ | Gear | `gear_changed` |
681
+
682
+ ---
683
+
684
+ ## CLI Quick Reference
685
+
686
+ ### OpenClaw Plugin Commands
687
+
688
+ ```bash
689
+ openclaw tescmd status # Plugin and node status
690
+ openclaw tescmd commands # List all 34 whitelisted commands
691
+ openclaw tescmd events # List telemetry event types
692
+ ```
693
+
694
+ ### tescmd CLI Commands
695
+
696
+ ```bash
697
+ tescmd serve <VIN> --openclaw <url> --openclaw-token <token> # Start node
698
+ tescmd setup # Interactive setup wizard
699
+ tescmd auth status # Check auth token status
700
+ tescmd auth login # Re-authenticate with Tesla
701
+ tescmd vehicle list # List vehicles on account
702
+ tescmd vehicle info # Full vehicle data snapshot
703
+ tescmd vehicle location # Get GPS coordinates
704
+ tescmd charge status # Battery and charging state
705
+ tescmd charge start --wake # Start charging (wakes vehicle)
706
+ tescmd charge limit 80 # Set charge limit to 80%
707
+ tescmd climate on --wake # Turn on climate
708
+ tescmd climate set 72 --wake # Set temperature to 72°F
709
+ tescmd climate status # Check climate state
710
+ tescmd security lock --wake # Lock doors
711
+ tescmd security status # Check lock/sentry state
712
+ tescmd security flash --wake # Flash headlights
713
+ tescmd security honk --wake # Honk horn
714
+ tescmd security sentry on --wake # Enable Sentry Mode
715
+ tescmd trunk open --wake # Open rear trunk
716
+ tescmd trunk frunk --wake # Open frunk
717
+ tescmd cache status # Check cache stats
718
+ ```
719
+
720
+ All read commands are cached (tiered TTLs: 30s-1h). Write commands auto-invalidate the cache. The `--wake` flag is required for commands that need the vehicle awake. Use `--format json` for structured output.
721
+
722
+ ---
723
+
724
+ ## Slash Commands
725
+
726
+ Quick-action shortcuts users can type directly in chat. All require authentication.
727
+
728
+ | Command | Arguments | Description |
729
+ |---------|-----------|-------------|
730
+ | `/battery` | _none_ | Check battery level and range |
731
+ | `/charge` | `start`, `stop`, or a number (e.g. `80`) | Charge status, start/stop, or set limit |
732
+ | `/climate` | `on`, `off`, or a number (e.g. `72`) | Temperature check, HVAC on/off, or set °F |
733
+ | `/lock` | _none_ | Lock all doors |
734
+ | `/unlock` | _none_ | Unlock all doors |
735
+ | `/sentry` | `on` or `off` | Check or toggle Sentry Mode |
736
+ | `/location` | _none_ | Get GPS location |
737
+ | `/vehicle` | _none_ | Full status: battery + charge + temp + security + location |