Unofficial CLI for the Ninebot (九号) scooter Passport + business APIs
Project description
ninecli
Unofficial CLI for the Ninebot (九号) scooter app — read vehicle info, view ride history, and run vehicle controls (engine start/stop, seat trunk, find-me bell) from the terminal.
Not affiliated with Ninebot / Segway.
Install
# one-off, no install
uvx ninecli
# or install into current env
pip install ninecli
Multi-platform wheels are published for Linux (amd64, arm64) and
macOS (amd64, arm64); pip / uv picks the right one automatically.
Quick start
ninecli login -u <phone> -p <password> # password login, saves tokens.json
ninecli whoami # verify the saved token
ninecli vehicles # list owned + shared vehicles
ninecli status # show one vehicle's status (asks which one)
ninecli travel # ride history for the current month
Vehicle controls (bell, engine-start, engine-stop, buck) print
a y/N safety prompt — pass -y to skip.
Usage
$ ninecli --help
ninecli — Ninebot scooter Passport + vehicle info + control
Usage:
ninecli [command]
Available Commands:
bell Ring the find-my-vehicle bell
buck ⚠️ Open the seat trunk
completion Generate the autocompletion script for the specified shell
engine-start ⚠️ Power on / unlock the vehicle
engine-stop ⚠️ Power off / lock the vehicle
help Help about any command
login Password login (Passport) — saves tokens.json
login-code SMS-code login (Passport) — sends code, then consumes it
mcp Run a Model Context Protocol server for Ninebot APIs
serve Run an HTTP proxy exposing Ninebot APIs as plaintext REST
status Show vehicle status (location, battery, lock, acc, perms)
travel Ride history (default: list current month); --detail <id> shows one ride
vehicles List owned + shared vehicles
whoami Verify the saved token (calls POST /v5/user)
Flags:
--config string config directory (default: $NINEBOT_CONFIG_DIR or ~/.config/ninebot)
-h, --help help for ninecli
--json emit raw decrypted JSON instead of human-readable output
-y, --yes bypass the y/N safety prompt on control commands (engine-start/engine-stop/buck)
Use "ninecli [command] --help" for more information about a command.
REST proxy (serve)
ninecli serve # start local HTTP API
ninecli serve --token secret --quiet # require Bearer auth + suppress logs
Serve exposes the encrypted Ninebot APIs as a plaintext REST server
driven by your saved tokens.json. It is useful for home-automation
integrations, dashboards, or scripts that would rather hit curl than
re-implement the Netease crypto layer.
Default bind: 127.0.0.1:18009. Environment variables: NINEBOT_SERVE_BIND,
NINEBOT_SERVE_TOKEN.
Endpoints:
GET /healthz # always 200 (unauthenticated)
POST /auth/login # {account,password}
POST /auth/login-code # {account} — send SMS code
POST /auth/login-code/consume # {account,code}
POST /auth/refresh # rotate access_token
GET /whoami
GET /vehicles
GET /vehicles/{sn}/status
GET /vehicles/{sn}/travel?month=YYYYMM
GET /vehicles/{sn}/travel/{detail_id}
POST /vehicles/{sn}/engine/start
POST /vehicles/{sn}/engine/stop
POST /vehicles/{sn}/buck
POST /vehicles/{sn}/bell
All responses use the envelope {"ok": true, "data": ...} or
{"ok": false, "error": {"code": "...", "message": "..."}}. Tokens
and credentials are never echoed in responses.
Docker Compose deployment
Save the following as docker-compose.yml:
services:
ninecli:
build:
dockerfile_inline: |
FROM ghcr.io/astral-sh/uv:python3.13-alpine
RUN uv tool install ninecli
ENV PATH="/root/.local/bin:${PATH}"
ENTRYPOINT ["ninecli"]
command: ["serve", "--bind", "0.0.0.0:18009"]
ports:
- "18009:18009"
environment:
NINEBOT_CONFIG_DIR: /config
NINEBOT_SERVE_TOKEN: ${NINEBOT_SERVE_TOKEN:-}
volumes:
- ${NINEBOT_CONFIG_DIR:-~/.config/ninebot}:/config
restart: unless-stopped
Usage:
# Optional: protect every non-/healthz endpoint with Bearer auth
export NINEBOT_SERVE_TOKEN=change-me
# Optional: override the host-side config directory mounted into /config
export NINEBOT_CONFIG_DIR=$HOME/.config/ninebot
docker compose up --build -d
curl http://127.0.0.1:18009/healthz
curl -H "Authorization: Bearer $NINEBOT_SERVE_TOKEN" \
http://127.0.0.1:18009/vehicles
The compose service maps 18009:18009, sets NINEBOT_CONFIG_DIR=/config
inside the container, and mounts ${NINEBOT_CONFIG_DIR:-~/.config/ninebot}
from the host to /config. Run ninecli login on the host first, or use the
proxy auth endpoints (POST /auth/login, POST /auth/login-code) to create
tokens.json through the server.
Model Context Protocol (mcp)
ninecli mcp # stdio MCP server (default)
ninecli mcp --http --bind 127.0.0.1:18019 # Streamable HTTP server
ninecli mcp --http --token secret # require Bearer auth in HTTP mode
mcp runs a Model Context Protocol server that exposes Ninebot APIs as
typed MCP tools. AI clients (Claude, Cursor, etc.) can call vehicle read,
travel, control, and auth operations without re-implementing the Netease
crypto layer or managing tokens.
Default stdio transport is intended for local MCP clients. Use --http to
run a Streamable HTTP server. HTTP bearer auth is optional; when --token is
set, every request must include Authorization: Bearer <token>. Reuses the
same env variables as serve: NINEBOT_SERVE_BIND, NINEBOT_SERVE_TOKEN.
Tools exposed:
- Auth:
auth_login,auth_send_code,auth_consume_code,auth_refresh - Read:
whoami,vehicles,vehicle_status,travel,travel_detail - Control:
engine_start,engine_stop,buck,bell
Control tools that change vehicle state (engine_start, engine_stop,
buck) include "requires user confirmation" in their descriptions so the
client knows to ask before calling.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ninecli-0.1.4-py3-none-win_arm64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-win_arm64.whl
- Upload date:
- Size: 3.3 MB
- Tags: Python 3, Windows ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db6020e320e40dba4a463ab29d94dedcbfce8729b6f688df9462b5dd5bf03637
|
|
| MD5 |
432e1a9400fc805f2d6a8eae1e46bcc4
|
|
| BLAKE2b-256 |
4f80e4a56263e812adf67fa4d6ce43b248d8dc3870dcb3c9957d54d00bbfec0f
|
File details
Details for the file ninecli-0.1.4-py3-none-win_amd64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-win_amd64.whl
- Upload date:
- Size: 3.7 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7e1b259250411dcae9f3be61d4d4787c3b4ede8d186b079916d5c346e5e45f4
|
|
| MD5 |
1e2c386838b36d0313bcec5030ebd0fc
|
|
| BLAKE2b-256 |
cd57500913cccf77edcd1c92dc09b7737a4d51f3bdb1e1d9523050fa4f983fed
|
File details
Details for the file ninecli-0.1.4-py3-none-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 3.6 MB
- Tags: Python 3, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6122558d88d638c032ae47af44d7ca3db1937e6123a8e1357bf6e25dd8ba3292
|
|
| MD5 |
9ede9734854ba3c8a7e0f3d838fba0e0
|
|
| BLAKE2b-256 |
edf943a04fc95443d592e4e10000329bacc2ec2d9ec51bd4117be55c07842167
|
File details
Details for the file ninecli-0.1.4-py3-none-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: Python 3, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a40dd96752cf164513f272ad6d1d41f5e8b8c36be44200132d507b4b17b8f0e9
|
|
| MD5 |
b5ed8e1a355097495b9298e87ec42a33
|
|
| BLAKE2b-256 |
67d3ff579392b2f54c0533eb239b576e3edce46d0d9b2a681f98c6e6dd0e1ecb
|
File details
Details for the file ninecli-0.1.4-py3-none-manylinux_2_17_x86_64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-manylinux_2_17_x86_64.whl
- Upload date:
- Size: 3.6 MB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
141ba69d6d81802743a768a9cedcae6dae472db26d4f58e5854283f11b7e3a22
|
|
| MD5 |
95dc53681c6c66d5d3147f87222b2fc0
|
|
| BLAKE2b-256 |
e52e0ca403a51d1f2e8e3a730e3b2fc7105a273dd0788ec7d3949905397060d7
|
File details
Details for the file ninecli-0.1.4-py3-none-manylinux_2_17_aarch64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-manylinux_2_17_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
199b4533e17d7da3ce501f3de6d0f7d1b86e58f1fb30ab6b80f7755ef6f29215
|
|
| MD5 |
3bf2fb134e44f9ce63bfbe01c325fac0
|
|
| BLAKE2b-256 |
746c12ffd97c8da7b78949cff55735fe550295f9b27cff11a2cea9d305449fb0
|
File details
Details for the file ninecli-0.1.4-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.4 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cdb77a05114d210738d772f8da544a64e8c6dc7a72974d5688994da4c9db205
|
|
| MD5 |
00a0cce486b73671843c5c741fef23b8
|
|
| BLAKE2b-256 |
60e17fc71a741dbd82375c31d0ae02bba08ee8b8686cbf8523a64de5a7f40d99
|
File details
Details for the file ninecli-0.1.4-py3-none-macosx_10_9_x86_64.whl.
File metadata
- Download URL: ninecli-0.1.4-py3-none-macosx_10_9_x86_64.whl
- Upload date:
- Size: 3.6 MB
- Tags: Python 3, macOS 10.9+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7c34ae957f4484d43a0b52f45ab2b7aee5fe318dd3f9dc27727f3f582911cdd
|
|
| MD5 |
a98cba277aabf3ab0636105beb9590ad
|
|
| BLAKE2b-256 |
31b8e5bad9e3c6e945d109418396bc0bdec1c2ce018e0ac9471753e1f6b1a306
|