Skip to main content

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:
  battery      Show battery info (voltage, temperature, cycles, charge power)
  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}/battery
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, vehicle_battery, 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

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ninecli-0.1.7-py3-none-win_arm64.whl (3.3 MB view details)

Uploaded Python 3Windows ARM64

ninecli-0.1.7-py3-none-win_amd64.whl (3.7 MB view details)

Uploaded Python 3Windows x86-64

ninecli-0.1.7-py3-none-musllinux_1_2_x86_64.whl (3.6 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

ninecli-0.1.7-py3-none-musllinux_1_2_aarch64.whl (3.2 MB view details)

Uploaded Python 3musllinux: musl 1.2+ ARM64

ninecli-0.1.7-py3-none-manylinux_2_17_x86_64.whl (3.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

ninecli-0.1.7-py3-none-manylinux_2_17_aarch64.whl (3.2 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

ninecli-0.1.7-py3-none-macosx_11_0_arm64.whl (3.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

ninecli-0.1.7-py3-none-macosx_10_9_x86_64.whl (3.7 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

Details for the file ninecli-0.1.7-py3-none-win_arm64.whl.

File metadata

  • Download URL: ninecli-0.1.7-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

Hashes for ninecli-0.1.7-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 8ceedd6fa0d3e7a2cffa5ebf83cdb37180280d74948efb64fee338e69104be88
MD5 3db1e50807de37820443c0159ad4307e
BLAKE2b-256 efab2c1e4c1d29228006f8c1db48dbe4fb28c80dc0eb71f0db955cb3548ff46b

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-win_amd64.whl.

File metadata

  • Download URL: ninecli-0.1.7-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

Hashes for ninecli-0.1.7-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 7fc00300bb5b02f431830912b3bdfb1c77b2a423e7686e01ebaeaab6252ae683
MD5 b91bdeb45da28d9bac18c79f4c1256dd
BLAKE2b-256 b88d42fe5fd17f93c3bda63fb41471afc05462b95651d401f5db4903e0b5243e

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.7-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2de20e64f77d79143861f4a50cf0093b3a813836b15bbf57da0f81fd2950af56
MD5 bfe07996e21a475c1e9ed090f1089424
BLAKE2b-256 fc88f317519463e56cbd7caa5963960f858e17e47c08fcd84edcfc4a2fe59a76

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.7-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 e2c82740839948a50ae02142a16f0a260c74667a1ccceda167ef570621b37c90
MD5 c36cd49f5029ebb4e20ab01fee10ba28
BLAKE2b-256 05c8e2f17bc29ce5001fa820a3b214473e2d389181773bbddc16ca0610e1b238

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.7-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 ff3941b81d60e4bba60e9477900e63a9ebd2b02e74cb4b8138f3cfe1d94a81cc
MD5 eb9045fd3615c2f33421c555af7bdc48
BLAKE2b-256 9f5a897692667b5293cc54e02cc0d99e1889c5220eb6b18ce9e209cf4c25dd6b

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.7-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 ff362ad6e1f41dab94d4fb5d477365adc7daa1a5996beebd0c94637ecdd7be15
MD5 2f43c63d374674d17548ebb4d52c653a
BLAKE2b-256 0e349f7c92c8dd0c880a87f59cf948c911d3760caa30736c06af790315c5d513

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.7-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ab3276dc7ae7675806ed21efc68b1f8ce01a233d6236bb67c82291037a564534
MD5 94e96a05d81db68bc1e15624992578bb
BLAKE2b-256 da22d648e0c96d8fe4b1cffe0d7c86c3e35e06e1b948756956e290fe8313c2f1

See more details on using hashes here.

File details

Details for the file ninecli-0.1.7-py3-none-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.7-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 4b248e639e2e359f8ee1f2268ba369c602d21fafc6c0d0eaf146cc5031b7da6d
MD5 a3859e81e029672b523a83d1fb2437f5
BLAKE2b-256 cdf6b63dd7cf8e8a352c98bc2ab23d101a3f09583b08e7349ef2e7b6fba0df06

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page