Skip to main content

CarConnectivity-connector-lucid

OpenSSF Scorecard

A CarConnectivity connector for Lucid Motors vehicles (Air and Gravity), built on python-lucidmotors.

Read-only by default. It polls the same mobile API the Lucid app uses and populates the CarConnectivity model: state, odometer, battery level / range / capacity / cell temperatures, charging state and target, position, doors and locks, climatization, software version. Reads never wake the car, so polling costs nothing in battery drain. Commands (lock, climate, charging, trunk and the rest from 0.2.0; Halo Secure, windows, seats and more from 0.3.0) but stay off unless the config turns them on; see Commands.

Verified against a 2026 Gravity on 2026-09-03.

Install

pip install carconnectivity-connector-lucid

Python 3.12 or newer. The connector logs in with a refresh token only (login_with_refresh_token(), in lucidmotors 1.4.2 and later), so there is no password on disk.

Credentials

The connector needs only a Lucid refresh token, stored in a JSON file:

{"refresh_token": "…"}

Mint one once with the library's login example (username + password, interactively), save the refresh_token it returns, and never store the password. The token does not rotate, so the file can be mounted read-only. Point the config at it — never paste the token into the config file itself.

Config

{
    "carConnectivity": {
        "connectors": [
            {
                "type": "lucid",
                "config": {
                    "refresh_token_file": "~/.config/lucid-token.json",
                    "interval": 60,
                    "driving_interval": 15
                }
            }
        ]
    }
}

All options in doc/Config.md.

Commands

Off by default. Without the option the connector creates no command objects at all and the charge limit is read-only, so nothing CarConnectivity exposes (the REST API, MQTT, the web UI) can send anything to the car. To turn them on, add "commands": true to the connector's config. It must be the JSON boolean true; a string such as "true" is refused at startup.

command where values library call
Charging charging/commands/start-stop start, stop start_charging / stop_charging
Charge limit charging/settings/target_level whole percent, 50 to 100 set_charge_limit
Climatization climatization/commands/start-stop start [--target-temperature 21], stop set_cabin_temperature (precondition / off)
Defrost window_heating/commands/start-stop start, stop defrost_on / defrost_off
Locks doors/commands/lock-unlock lock, unlock doors_lock / doors_unlock
Trunk doors/commands/trunk open, close trunk_open / trunk_close
Frunk doors/commands/frunk open, close frunk_open / frunk_close
Lights and horn commands/honk-flash flash, honk-and-flash lights_flash, honk_horn
Wake commands/wake-sleep wake (a Lucid cannot be sent to sleep) wakeup_vehicle
Sentry (Halo Secure) commands/sentry on, off sentry_mode_on / sentry_mode_off
Enhanced deterrence commands/enhanced-deterrence on, off enhanced_deterrence_on / _off
Sentry at home commands/sentry-at-home on, off sentry_mode_at_home_on / _off
Sentry at work commands/sentry-at-work on, off sentry_mode_at_work_on / _off
Silence a Sentry alarm commands/sentry-alarm off (an alarm cannot be set off remotely) turn_off_sentry_alarm
Security alarm commands/alarm on, off, silent (notifications only) alarm_control
Windows, all four commands/windows vent (drops them a little; again drops them further), close open_all_windows / close_all_windows
Headlights commands/lights on, off lights_on / lights_off
Max A/C climatization/commands/max-ac on, off max_ac_on / max_ac_off
Creature comfort climatization/commands/creature-comfort on, off creature_comfort_control
Seat heat and ventilation climatization/commands/seat-climate <seat> <heat|vent> <off|low|medium|high>, seat driver, front-passenger, rear-left, rear-center, rear-right; rear seats heat only seat_climate_control (every zone of that seat)
Steering wheel heater climatization/commands/steering-wheel-heater off, low, medium, high steering_wheel_heater_control
Battery preconditioning charging/commands/battery-preconditioning on, off battery_precon_on / battery_precon_off
AC current limit charging/settings/maximum_current whole amps, 8 to 80 set_ac_current_limit

Each command also takes {"command": "on"} (seat climate: {"seat": "driver", "mode": "heat", "level": "low"}). The state each one changes is published where the API has it, so a UI can show a toggle:

state attribute from
Sentry on sentry sentry_state.enablement_state (enabled or idle)
Enhanced deterrence on enhanced_deterrence sentry_state.enhanced_deterrence_state (enabled or idle)
Alarm mode alarm alarm.mode
Windows windows/... body.window_position
Charge port door charge_port body.charge_port (not one of doors: it stands open for every charge)
Headlights lights/light_state chassis.headlights
Max A/C, creature comfort max_ac, creature_comfort hvac.max_ac_status, hvac.keep_climate_status (pet mode)
Seat levels seat_heat_driver, seat_vent_driver, seat_heat_front_passenger, seat_vent_front_passenger, seat_heat_rear_left, seat_heat_rear_center, seat_heat_rear_right hvac.seats (a seat's warmest zone)
Steering wheel heater steering_wheel_heater hvac.steering_heater_level
Battery preconditioning battery_preconditioning battery.preconditioning_status
AC current limit charging/settings/maximum_current charging.energy_ac_current_limit

Sentry at home and at work have no state in the API that the connector can read, so they are commands only.

Left out on purpose: software updates (apply_update). The car cannot be driven while an update installs; that is a decision to make in the car or the app with the release notes in front of you, not a button on a dashboard. Also left out: individual seat zones (backrest apart from cushion: the car binds them in pairs and the app sets a seat at once), a full window drop (the library offers vent and close only), the sentry event and video history, which is a read API, not a command, and opening or closing the charge port door, which on an Air opens by hand (its state is read; see below).

How they behave:

  • Only commands wake the car. If the last poll saw the car asleep (any sleep or cloud power state, the same rule the poller reports), the command wakes it first, waits a few seconds, then sends. Polling still never wakes it.
  • Sent once. Nothing is retried. A retried unlock or trunk is a second one if the first landed and only its answer was lost, so a failure comes back as an error and the decision is yours. A command not answered within 60 seconds, counting any login and wake it needed, is reported as such; check the car before sending it again. One that waited out the 60 seconds behind a poll was never sent, and says so.
  • Errors are short. Rate limits, rejected sessions and refusals from the car all come back as a CarConnectivity CommandError naming the command and Lucid's reason.
  • Same session, same rate limit. Commands use the poller's login and count against the same per-account allowance. A successful one triggers an early poll so the model shows the result.
  • A climatization temperature in Fahrenheit is converted; anything outside 10 to 35 °C is refused as a probable unit mistake.

Session lifetime — read this if you run it long

interval is how often the car is polled, minimum 60 s. driving_interval is used instead while a car is driving or about to be, minimum 15 s, defaulting to interval so nothing changes unless you ask. A minute is plenty for a car on a driveway and too coarse for one moving: at 60 s a drive is a handful of points with straight lines between them. Driving is a small share of any day, so the extra requests are few.

Both are the spacing between polls, not the pause after one. A fetch of a sleeping car returns in about a tenth of a second, but Lucid has to reach a car that is awake and driving, and that fetch takes on the order of fifteen seconds — so waiting the full interval after it made a 15 s setting a 31 s cycle. The wait is the interval less however long the fetch took, and the fetch time is logged at debug level if you want to see it.

One account, one client. Lucid rate-limits per account, not per connection, and it says nothing useful when it does: RESOURCE_EXHAUSTED with an empty body, no quota and no retry-after. Running a second logger against the same credentials — another CarConnectivity instance, a Home Assistant integration, a bridge of your own — competes for the same allowance, and the refusals arrive mid-drive when both are polling hardest. When one does arrive the connector waits 5 s, then 10, 20, 40 and so on to a 15-minute ceiling, and drops back to 5 s as soon as a poll succeeds.

A Lucid session's bearer token lasts five minutes and the server enforces that to the second. The connector refreshes only when under 60 s remain, never on every poll: the refresh endpoint is rate-limited, back-to-back refreshes return the same session anyway, and a client that refreshed per poll was throttled thousands of times before this was measured. Keep interval under 240 s or raise the refresh margin.

Metadata

Release files for carconnectivity-connector-lucid 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for carconnectivity-connector-lucid 0.3.1
File Size Uploaded Provenance Actions
carconnectivity_connector_lucid-0.3.1.tar.gz 63.9 kB With provenance Details for carconnectivity_connector_lucid-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for carconnectivity-connector-lucid 0.3.1
File Interpreter ABI Platform Actions
carconnectivity_connector_lucid-0.3.1-py3-none-any.whl Python 3 none any Details for carconnectivity_connector_lucid-0.3.1-py3-none-any.whl

Total release size: 97.9 kB

Release files / carconnectivity_connector_lucid-0.3.1.tar.gz

Download URL carconnectivity_connector_lucid-0.3.1.tar.gz
Size 63.9 kB
Tags Source
SHA-256 checksum
How to use checksums
2ec525bd63bdc019d8fe593fadbeccd89b84bf0d6952fe81555004d3bbf0f070
BLAKE2b-256 checksum
How to use checksums
58f0019005a171a4376f6b26ebcbcd3fadc5b9f8c1f50fcbbd42438c34cfaf58
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Release files / carconnectivity_connector_lucid-0.3.1-py3-none-any.whl

Download URL carconnectivity_connector_lucid-0.3.1-py3-none-any.whl
Size 34.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ff2efa8802227ad47e19855315c2f498810466defce36b5408ca1a2030b1e503
BLAKE2b-256 checksum
How to use checksums
1c8e5f22d7dc24f2e7494a4dbd557b2a2f0b0006ab3452882c1016c347db22ca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

Security for carconnectivity-connector-lucid 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for carconnectivity_connector_lucid-0.3.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page