This release is a pre-release and may not be stable for production use.
licli
licli is a CLI for Li Auto (LiXiang) vehicle APIs. It covers auth, real-time status, tire pressure/temperature/warnings, travel history, control commands, an HTTP API server, and an MCP server.
Run it without installing anything (PyPI via uvx, or npm via npx):
alias licli='uvx liauto'
licli help
# or
alias licli='npx -y @liauto/cli'
licli version
Commands
licli activate # activate the current device (first activation or re-activation)
licli login # device login, prints an OAuth URL, then persists the pasted token JSON
licli vehicles # list cached vehicles
licli status <VIN> # query vehicle state (--json/--raw)
licli tire <VIN> # query tire pressure/temperature/warning (--json/--raw)
licli travel <VIN> [YYYY-MM] # monthly travel history; with YYYY-MM, that month's detail
licli control <VIN> <action> # lock/unlock/find/wake + ac <on|off|auto|temp|fast-cool|fast-heat> + seat-vent/seat-heat [pos] <1-3|off> + wheel-heat <on|off> + window [pos] <0-99> + trunk <open|close> (action: result <id>)
licli version # print version
licli serve # HTTP API server (default 127.0.0.1:18001; --addr/--token/--allow-control)
licli mcp # MCP server, stdio (default) or --transport http (default 127.0.0.1:18002)
Run licli with no arguments (or licli <unknown>) to print the command list.
Global flags: --json (JSON output), -v / --verbose (verbose logging to stderr).
Exit codes: 0 success, 1 user input error, 2 network failure, 3 HTTP non-200, 4 activation failure, 5 config permission/corrupt, 6 missing/invalid/expired activation code, or code bound to a VIN not in this account.
Activation code
Running licli requires a valid activation code, set as an environment variable:
export LICLI_CODE=<activation code>
licli activate # activate the device (onboarding; also done automatically by login)
licli login # establish the account (auto-activates a device if needed)
licli vehicles # list vehicles (also tells you your VIN)
activate, login, vehicles, version, and help work without a code.
serve and mcp also start without one: they bind and answer liveness
(/healthz / tools/list) before login, and check the code per request.
Every other command requires a code.
A code is bound to a VIN: it is admitted only when that VIN appears in the vehicle list of the account you are logged in to.
To get a code, message the Telegram bot @licli_bot.
HTTP API server (serve)
licli serve runs a foreground HTTP server (default 127.0.0.1:18001, override with --addr). Bind to a loopback address, set --token, or pass --allow-control to enable the control endpoints.
Endpoints:
| Method | Path | Description |
|---|---|---|
| GET | /healthz |
Liveness probe (unauthenticated) |
| GET | /vehicles |
List vehicles; query limit (default 20), offset, refresh=true |
| GET | /vehicles/{vin}/status |
Vehicle state (state, platform, fetched_at, location when available) |
| GET | /vehicles/{vin}/tire |
Tire pressure/temperature/warnings (tires, platform) |
| GET | /vehicles/{vin}/travel |
Travel month history (months) |
| GET | /vehicles/{vin}/travel/{ym} |
One month's detail; {ym} is YYYY-MM |
| POST | /vehicles/{vin}/control |
Send a control command |
| GET | /vehicles/{vin}/control/{requestId} |
Query a prior command's result |
| POST | /login |
Returns {auth_url, notice} to start an OAuth login |
| POST | /login/submit |
Persists {"token_json": "..."} (strict JSON) |
All endpoints except /healthz require Authorization: Bearer <token> when a token is configured. serve starts and answers /healthz before login: an activation code is checked per request, and every route except /healthz, the two /login routes, and GET /vehicles needs one (bound to a VIN in the account). GET /vehicles is ungated, like the CLI vehicles command. The two control endpoints return 403 control_disabled unless the control gate is open (loopback bind, a configured token, or --allow-control); the two /login endpoints require the same control gate.
POST /control body (strict JSON, unknown fields rejected):
{ "action": "lock", "temp": 22.5, "pos": "fl", "level": 2, "open": true }
action is one of lock, unlock, find, wake, ac_on, ac_off, ac_auto, ac_temp, ac_fast_cool, ac_fast_heat, seat_vent, seat_heat, wheel_heat, window, trunk. The other fields are per-action; unset fields take the action's default:
| Field | Applies to | Values |
|---|---|---|
temp |
ac_temp |
number, 16–32 |
pos |
seat_vent |
fl | fr |
pos |
seat_heat |
fl | fr | rl | rr |
pos |
window |
fl | fr | rl | rr | all |
level |
seat_vent, seat_heat |
int, 0–3 (0 = off) |
level |
window |
int, 0–99 |
open |
trunk |
bool |
pos is only valid for seat_vent/seat_heat/window; any other action rejects it. Errors use a unified envelope {"ok": false, "error": {"code", "message", "retryable"}}.
MCP server (mcp)
licli mcp serves the Model Context Protocol over stdio (default) or Streamable HTTP (--transport http, default 127.0.0.1:18002). It exposes nine tools: vehicles, status, tire, travel_months, travel_month, control, control_result, login, login_submit. An activation code is checked per tool call: vehicles is ungated (read your VIN), login/login_submit are the bootstrap, and the rest require a code bound to a VIN in the account. The two control* tools are enabled by default under stdio; under --transport http they require --allow-control or --token. The two login* tools require the same control gate, and their token transits the MCP client (the model and the host transcript) — see the warning in the tool description.
Register it with Claude Code (no install needed):
claude mcp add licli -- uvx liauto mcp
Configuration
Credentials are stored under the XDG config directory (~/.config/licli by default, or $XDG_CONFIG_HOME/licli) with 0700 directory and 0600 file permissions:
device.json— activated device + key suiteauth.json— API token, ID token, refresh token, expiry
Docker Compose deployment
Run the HTTP API server (serve) and MCP server (mcp) in containers sharing the host config:
services:
licli-api: &licli
build:
dockerfile_inline: |
FROM ghcr.io/astral-sh/uv:python3.13-alpine
RUN uv tool install liauto
RUN ln -sf /usr/local/bin/liauto /bin/licli
ENV PATH="/root/.local/bin:$${PATH}"
ENV XDG_CONFIG_HOME=/config
ENV LICLI_SERVE_ADDR=0.0.0.0:18001
ENV LICLI_MCP_ADDR=0.0.0.0:18002
ENV LICLI_MCP_TRANSPORT=http
ENTRYPOINT ["liauto"]
command: ["serve", "--allow-control"]
ports:
- "18001:18001"
environment:
LICLI_CODE: ${LICLI_CODE:-}
LICLI_SERVE_TOKEN: ${LICLI_SERVE_TOKEN:-}
volumes:
- ${LICLI_CONFIG_DIR:-~/.config/licli}:/config/licli
restart: unless-stopped
licli-mcp:
<<: *licli
command: ["mcp", "--allow-control"]
ports:
- "18002:18002"
licli-api shares its build, env, volume and restart policy with licli-mcp via the &licli anchor. Both read the same host credentials (auth.json / device.json under ~/.config/licli, or $LICLI_CONFIG_DIR). The containers bind non-loopback addresses, so --allow-control enables the control endpoints and LICLI_SERVE_TOKEN gates them behind a bearer token.
Log in once before starting the stack — the interactive login writes auth.json / device.json into the mounted config volume, and both services pick them up:
docker compose run --rm -it licli-api login
Metadata
Release files for liauto 0.1.1b3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 48.9 MB
Release files / liauto-0.1.1b3-py3-none-win_amd64.whl
| Download URL | liauto-0.1.1b3-py3-none-win_amd64.whl |
|---|---|
| Size | 7.8 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
1d847e60f1c55692267ecea9fe28e214094165308025748c3e10cc8b4f24cad9
|
|
BLAKE2b-256 checksum How to use checksums |
bb25a459e94cca3865482876cf72e16e9a15707bf3edac3cfbed3c40c3ea157b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / liauto-0.1.1b3-py3-none-musllinux_1_2_x86_64.whl
| Download URL | liauto-0.1.1b3-py3-none-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 7.1 MB |
| Tags | Linux musl 1.2+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
384e09572607c374f9fd7c043268834ca969fa921ccf66b25248cf2cd58e25e9
|
|
BLAKE2b-256 checksum How to use checksums |
38f381d499022dbb9ee7abaafebd207e37a97f024254aa109e8cf2b35240a251
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / liauto-0.1.1b3-py3-none-musllinux_1_2_aarch64.whl
| Download URL | liauto-0.1.1b3-py3-none-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 6.5 MB |
| Tags | Linux musl 1.2+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
5459854282855b0dbaf4e5eaf111ab142161a22b47a554fd900ae67e15a986f9
|
|
BLAKE2b-256 checksum How to use checksums |
1e19a1e2c0457dbbcdfbc9cf6fddd9a3839c08f7a29424ac5929a3b0fc0a5303
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / liauto-0.1.1b3-py3-none-manylinux_2_17_x86_64.whl
| Download URL | liauto-0.1.1b3-py3-none-manylinux_2_17_x86_64.whl |
|---|---|
| Size | 7.1 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
04cb4a58d97a7f8ac4bf9c289fd0fde289eaa952e5e3703ec8d94b182781fd47
|
|
BLAKE2b-256 checksum How to use checksums |
d22ccabc9de0f0da9ca5518cb9608eaaa757a308c86af66d1a36a7ea0c3484ca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / liauto-0.1.1b3-py3-none-manylinux_2_17_aarch64.whl
| Download URL | liauto-0.1.1b3-py3-none-manylinux_2_17_aarch64.whl |
|---|---|
| Size | 6.5 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
058afa13ff5bfaea511b8d2b0facf25d61d7825e588836b5303decb4c0a479e9
|
|
BLAKE2b-256 checksum How to use checksums |
7885b6b3af340d05cef3c7270537c66f18c7a92874cc34169106f0393311737a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / liauto-0.1.1b3-py3-none-macosx_11_0_arm64.whl
| Download URL | liauto-0.1.1b3-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 6.7 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
e431b51362841fba3b6d007cf611ecdf54c60d2cfc71439d41d9f45d3d9041e2
|
|
BLAKE2b-256 checksum How to use checksums |
9d5a5f4a8303223570cda3d52254a06ff7c5603484fe12e5d02ac0178759bb00
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / liauto-0.1.1b3-py3-none-macosx_10_9_x86_64.whl
| Download URL | liauto-0.1.1b3-py3-none-macosx_10_9_x86_64.whl |
|---|---|
| Size | 7.2 MB |
| Tags | Python 3 macOS 10.9+ x86-64 |
|
SHA-256 checksum How to use checksums |
6ba083e81d0d718f3f37922feaf380897c45cfbc66a864ff86a3781085f9773e
|
|
BLAKE2b-256 checksum How to use checksums |
d6828d4190b24e3ce77ae537095e3ed7300dd1c6129d48ac6844cc2f08657c28
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Security for liauto 0.1.1b3
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.