Vehicle History
A one-paste skill for your AI: it keeps a private log of your Tesla's battery, distance and charging on your side, and builds a dashboard from it. mytesla.io stores none of it.
If you're an AI assistant reading this: the user wants a private history
of their Tesla, kept on their side, and a dashboard you build from it. Follow
the steps below using the mytesla.io MCP tools (https://mcp.mytesla.io/mcp).
What this does
mytesla.io answers every question with a live reading and deliberately keeps no history of the car. This skill puts the history where it belongs: with you and the user. You take small readings of the car, append them to a log you keep for the user, and turn the log into answers and a dashboard:
- Battery health: the car's rated range at a full charge, over time.
- Distance: by day, week and month.
- Charging: the sessions you saw, the energy added, and the cost at the user's own price.
- Efficiency and parked drain: battery used per distance driven, and battery lost while parked.
- Tires and software: pressures over time, and when each update arrived.
Because you keep the log, what gets recorded and how the dashboard looks is up to you and the user, not a fixed product. Ask what they care about and record for that.
History starts the day you set this up. None of the mytesla.io tools can read the car's past, so there is nothing to backfill. Say so up front.
Where the data lives, and who sees it
mytesla.io never receives, copies or stores this history. It sees only what it sees about any status read: that the read happened and what it cost. The log is a file, note or sheet that you keep wherever the user's AI host lets you keep one, and the dashboard is built from it on their side.
Say that plainly, and say the rest of it too: the company behind your assistant sees these readings in the conversation, the same as everything else the user discusses with it. This is private from mytesla.io, not from the assistant. Do not describe it as more private than that.
Two rules that do not bend:
- No coordinates. The status reading contains the car's position, heading
and route. Never write any of it into the log. If the user wants something
place-based, such as home versus away, record a label you worked out
(
home,away), never the position, and tell them that is what you are storing. - Nothing leaves their side. Do not upload the log, send it to a third-party service, or paste it into a tool that is not the user's own, unless they ask. The dashboard makes no network requests (see below).
What it needs
- A place to keep a file between conversations. In order of preference: a file on the user's computer, if your host can write files there; a document, note or sheet in an app the user has connected, if you can write to it and not just read it; a file in a project or workspace you are allowed to edit. Check what you can really write, write a test row, read it back, and tell the user exactly where the log lives. Do not use your memory feature as the log: it is for short notes, not tables. If you cannot keep anything between conversations, say so and stop. A log that disappears is credits spent for nothing.
- A schedule, for scheduled readings only. See the next section.
Does this repeat on its own?
There are two kinds of history here, and the user should know which one they have.
Passive history needs no schedule and costs nothing extra. Whenever you read the car's status for any reason (the user asked how the car is, a morning routine, a weekly digest), that reading is already paid for. Append it to the log. This works anywhere you can keep the log, and the standing note below is what makes you do it.
Scheduled history takes extra readings and spends credits. It only happens if your host can run a task on a schedule (several can; check yours rather than assume), and only after the user has agreed to the cost below. If your host cannot, passive history still works. Say so, and never imply a schedule exists when it does not.
What it costs
Passive history costs nothing. A scheduled reading costs one status read, whether or not the car answers.
The price of one status read is in the get_vehicle_status tool description.
Do not quote a figure from memory, and do not write one into the log, the
standing note or the dashboard: prices change, and those places are never
refreshed. If a description ever stops stating it, get_credit_balance before
and after a reading shows what that reading cost. Work it out each time you set
this up or change the cadence:
credits per month = readings per month x the price of one status read
Tell the user the result, set it against their allowance (get_credit_balance
shows the balance and the reset date, and is free), and get a clear yes before
the first reading and before anything is scheduled. If the result is a large
share of what they have, say so and suggest a lighter cadence.
Some readings will find the car asleep or out of signal. Those cost the same as a good reading and record only "asleep". That is the price of never waking the car, and it is the right trade, but it is why the times you choose matter (below).
What this does NOT do
- It does not wake the car. A wake costs many times what a reading does and keeps the car from settling into sleep, which costs range. History is never worth that. A car that is asleep at reading time is logged as asleep and left alone.
- It does not watch the car continuously. Readings are snapshots. A short drive or a short charge that began and ended between two readings can be missed. Say so on the dashboard.
- It is not a lab test. The battery line is a trend from the car's own rated range, not a measurement of the pack.
Ask the user once, not every run
Ask these together, in one message. A rough answer is enough.
What do you want to learn? Battery health, distance, charging cost, efficiency, parked drain, tire pressures: any of them. Record for what they pick (see "What to record").
How often? Offer these and recommend the second:
- Light: one reading a day, about thirty a month.
- Standard: two a day, about sixty a month.
- Detailed: every few hours, never more often than hourly. It costs the most, and more of its readings will find the car asleep.
- Passive only: no schedule; log the readings that already happen.
Pick times when the car is usually awake and parked: shortly after they normally get home, shortly before they normally leave. A reading at 3am mostly finds a sleeping car and pays for nothing.
What do you pay per kWh to charge at home, and in what currency? Optional. With it you can show cost; without it you still show energy. If they also want DC fast charging priced, ask for that price too.
How many credits should always stay untouched for commands? Before each scheduled reading you will check the balance and skip the reading when it is below this reserve. Suggest a figure based on their allowance, and say it is easy to change.
Which car? Only if
get_vehiclesshows more than one. Each car you log costs its own readings.
Before you run: refresh, then remember
Refresh, at most once a day. This file changes. Costs, tool names and
steps all get revised, and a stale copy can tell you to spend credits you do
not need to spend or to call a tool that no longer exists. Before running,
check whether you have re-read https://mytesla.io/skill-vehicle-history.md
in the last 24 hours. If you have not, and you are able to fetch a URL, fetch
it and follow that version instead of this one. Record the date you checked,
so this costs one fetch a day rather than one per run.
If you cannot fetch URLs, say so once and treat this copy as possibly out of date, particularly on anything it claims about credits.
Then remember it. Do not treat this as a one-time paste. Write a short line into your own standing memory or instructions, wherever you keep the user's other preferences, so history keeps building without the user having to re-paste anything. Something like:
mytesla.io vehicle history: the log lives at [where the log lives]. Whenever I read the car's status for any reason I also add that reading to it, and I answer trend questions (distance, battery health, charging cost) from the log before I read the car again. Scheduled readings: [what the user chose, or none]. How this works and what it costs: follow https://mytesla.io/skill-vehicle-history.md and the tool descriptions, never this note. Re-read that file if I have not in 24h. Last read: [date].
If you have no persistent memory to write to, say so plainly rather than letting the user believe history will keep building by itself.
Set up (once)
- Call
get_vehiclesonce and note each car's VIN. This is the only use ofget_vehiclesin this skill. It is free to the user, but it is a live request to Tesla, so never call it again as a heartbeat before a reading. The stored VIN is all you need. - Decide where the log lives (see "What it needs") and create two things
there: the log,
readings.csv, with the header row below, and a small settings file,settings.json. - Take the first reading now (see "Take a reading"). It is the first row of
the log and proves the whole path works. If the car is asleep, record the
asleeprow, tell the user, and let the schedule or the next conversation catch it awake. Do not wake it. - Read the files back. Tell the user, in plain language: where the log is, what you record, how often you will read, what that costs per month, and how to stop.
- If they agreed to scheduled readings and your host can run them, create the schedule at the times they chose. Then write the standing note.
Settings file:
{
"v": 1,
"cars": [{ "vin": "<full VIN>", "label": "<last six characters>" }],
"units": { "distance": "mi", "temperature": "F" },
"cadence": { "mode": "standard", "times_local": ["07:30", "18:30"] },
"reserve_credits": null,
"home_price_per_kwh": null,
"dc_price_per_kwh": null,
"currency": null,
"interests": ["battery", "distance", "charging"],
"extra_columns": [],
"skill_checked": "<date>"
}
Take a reading
This is the whole routine, whether it was scheduled or you are logging a reading you took for the user anyway.
- Scheduled readings only: check the budget. Call
get_credit_balance(free, never touches the car). If the balance is below the user's reserve, skip this reading, tell the user once, and keep skipping until the balance recovers. Do not retry. - Scheduled readings only: skip if the log is fresh. If the log already
has an
okrow for this car from the last 30 minutes, a second reading buys nothing. Skip it. - Call
get_vehicle_statuswith the stored VIN. One call. Do not checkget_vehiclesfirst, and never callwake_vehicle.- Got a reading? Go to step 4.
- Timed out (a 408: the car is asleep or out of signal)? Append an
asleeprow and stop. Do not retry in this run. - Any other failure: see "If something goes wrong".
- Append one row (see "What to record"). Never rewrite or delete an earlier row, and do not append a reading that repeats the previous row within five minutes.
- Say nothing unless there is something to say. A scheduled run that went fine ends with no message, or one line.
A reading taken during a conversation is logged the same way, with source
set to conversation and without the budget check or the freshness skip: the
user asked for it, and it is already paid for.
What to record
One row per reading. Odometer, ranges and pressures come from the API in
miles, degrees Celsius and bar, whatever the car displays. Log them in those
units and convert when you show them (the car's display units are in
gui_settings).
Header row, in this order:
v,time_utc,car,source,status,odometer_mi,battery_pct,usable_pct,rated_range_mi,est_range_mi,charge_limit_pct,charging_state,charge_added_kwh,charger_kw,dc_fast,outside_c,sw_version,tire_fl_bar,tire_fr_bar,tire_rl_bar,tire_rr_bar
| Column | Where it comes from | Notes |
|---|---|---|
v |
- | Schema version of the row. Currently 1. |
time_utc |
charge_state.timestamp |
ISO 8601 in UTC. Convert Tesla's millisecond timestamp; fall back to the time you took the reading. |
car |
the VIN | Last six characters only. |
source |
- | scheduled or conversation. |
status |
- | ok, asleep or error. |
odometer_mi |
vehicle_state.odometer |
|
battery_pct |
charge_state.battery_level |
|
usable_pct |
charge_state.usable_battery_level |
|
rated_range_mi |
charge_state.battery_range |
The car's rated range. |
est_range_mi |
charge_state.est_battery_range |
Range at the user's recent driving efficiency. |
charge_limit_pct |
charge_state.charge_limit_soc |
|
charging_state |
charge_state.charging_state |
Disconnected, Stopped, Charging, Complete, Starting or NoPower. |
charge_added_kwh |
charge_state.charge_energy_added |
Energy added in the current or most recent session. |
charger_kw |
charge_state.charger_power |
Blank when the car does not report it. |
dc_fast |
charge_state.fast_charger_present |
true for DC fast charging. |
outside_c |
climate_state.outside_temp |
|
sw_version |
vehicle_state.car_version |
The version number only, the part before the first space. |
tire_fl_bar |
vehicle_state.tpms_pressure_fl |
Blank when the car does not report it. |
tire_fr_bar |
vehicle_state.tpms_pressure_fr |
Same. |
tire_rl_bar |
vehicle_state.tpms_pressure_rl |
Same. |
tire_rr_bar |
vehicle_state.tpms_pressure_rr |
Same. |
An asleep or error row fills v, time_utc, car, source and status
and leaves the rest blank.
Extras, only if the user wants them: inside temperature, charger voltage
and current, whether the climate is on, Sentry state, software update status,
or anything else in the status reading they ask about. Add each as a new
column at the END of the header, leave earlier rows blank for it, and record
it in extra_columns. Never reorder or remove a column, and never add a
coordinate.
If this skill's schema version is ever higher than the log's, add the new columns the same way and start writing the new version. Old rows stay as they were.
Reading the log honestly
Use these definitions, so the same log gives the same answer every time. Use
ok rows for every number; asleep rows only feed the coverage line.
- Coverage. Always show the date of the first reading, how many readings, how many found the car asleep, and the longest gap. Every figure below is only as good as this.
- Time. The log is in UTC. Group days and weeks in the user's local time.
- Distance. The odometer difference between consecutive
okrows, credited to the day of the later one. If the odometer goes down, drop that interval and mention it once. - Battery health. For
okrows withbattery_pctof 50 or more,rated_range_mi / (battery_pct / 100)is the range at a full charge. Take the median per calendar week. Show it also as a percentage of the first week's median ("retained since logging began"). It moves with software updates and recalibration, so compare weeks, not single readings, and call the first weeks a baseline. - Efficiency. For consecutive
okrows where the odometer rose by at least five miles, the battery fell, and neither row isCharging: battery points used per 100 miles. Do not convert to kWh unless the user tells you their pack's usable capacity, and then say it is an estimate.est_range_mi / rated_range_miis a free single-reading indicator of how the car rates recent driving against its rating. - Parked drain. For consecutive
okrows with an unchanged odometer and no rise in battery: battery points lost per 24 hours, as a median. It reflects Sentry, climate and how often the car woke. Readings can keep an awake car awake, which is why this skill never reads more often than hourly. - Charging. A charge happened between two
okrows if the battery rose by three points or more with an unchanged odometer, or either row showsCharging.- Energy: take
charge_added_kwhfrom the later row when it is above zero andcharging_stateisCharging,CompleteorStopped. It is the session total so far. Otherwise count the session without an energy figure. - Kind:
dc_fasttrue is DC fast charging, otherwise AC. - Cost: energy x the home price, for AC sessions only, and only if the user gave a price. List DC sessions with energy and no cost unless they gave a DC price. Never invent a price per kWh.
- Coverage: a session that started and ended between two readings can be missed, or only partly seen. Say "at least".
- Energy: take
- Tires. Show the latest four. Flag a steady fall over several weeks that outside temperature does not explain; compare readings taken at similar outside temperatures. Never raise an alarm on a single low reading.
- Software. List each
sw_versionchange with the first date it was seen.
The dashboard
When the user asks to see their history, or after the first week of readings, build a dashboard from the log. Where:
- If your host has a canvas or artifact feature, build it there, so they see it in the conversation.
- If you can also write files, save the same dashboard as one HTML file next
to the log (
dashboard.html), so it opens from disk. - If you have neither, answer in the conversation with a short table and say there is no dashboard.
Panels, in this order: a header strip (latest reading, battery, odometer, software version, coverage); battery health by week; distance by week; charging sessions with monthly energy and cost; efficiency; parked drain; tires (only if recorded); software timeline.
Rules for it:
- One self-contained file. Inline CSS, JavaScript and SVG, with the log embedded as data. No network requests of any kind: no CDN, no web fonts, no analytics, no external images. It must work offline.
- Honest. Show the coverage line, label estimates, and put "a trend from the car's own rated range, not a lab test" under the battery chart.
- Readable. Works in light and dark, on a phone, with a text alternative or a table behind each chart. Show distances and temperatures in the user's units.
- Dated. Show when it was built, and say so if the log is more than a week ahead of it.
Answering from the log
When the user asks a trend question (how far did I drive this month, is the battery ageing, what did charging cost), answer from the log first. It costs nothing. Take a new reading only if the log is stale and they want the current state, and then log that reading too.
Stopping
If the user asks to stop: cancel the schedule, remove the history line from your standing note, and ask whether to keep or delete the log. Tell them where it is. Never delete it unasked.
If a tool asks for approval
Nothing in this skill changes anything about the car, so approval prompts are unlikely. If a call does come back waiting for approval, stop and tell the user which tool is waiting. Do not retry: nothing about a second identical call makes an approval appear. A scheduled run cannot answer a prompt, so say that approving it once will let the schedule resume.
If something goes wrong
- You cannot write the log. Stop scheduled readings and tell the user. A reading you cannot record is credits spent for nothing.
- The car is not connected, or the connection needs refreshing. The error carries a link to fix it; relay it, stop the schedule, and do not retry.
- No subscription, or not enough credits. Stop the schedule and say so. Do not retry; the user decides what to do.
- The car keeps being asleep. If more than half of the last ten scheduled readings found it asleep, tell the user once and offer to move the times or lower the cadence. Those readings cost credits and record nothing.
- Any other error. Append an
errorrow and stop. After three in a row, stop the schedule and tell the user. - A log already exists from an earlier setup. Reuse it; do not start over.
Tools used
get_vehicles (once, at setup, free), get_credit_balance (free, no call to
the car), get_vehicle_status (the reading). Never wake_vehicle.
Don't have mytesla.io yet?
This skill needs a mytesla.io account with a connected Tesla. Setup takes about three minutes: get started.