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:
  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

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.6-py3-none-win_arm64.whl (3.3 MB view details)

Uploaded Python 3Windows ARM64

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

Uploaded Python 3Windows x86-64

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

Uploaded Python 3musllinux: musl 1.2+ x86-64

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

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3manylinux: glibc 2.17+ x86-64

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

ninecli-0.1.6-py3-none-macosx_10_9_x86_64.whl (3.6 MB view details)

Uploaded Python 3macOS 10.9+ x86-64

File details

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

File metadata

  • Download URL: ninecli-0.1.6-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.6-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 8db446153e9aaa99535a9b69e44f6f7755232284e2a78c631ad4f95ddd90622f
MD5 5c3d8c8e210e854674f969f4e7e07f46
BLAKE2b-256 6f1b33f8b7cdf3accdd872ccaa0e08dccab16e1b1969570f2a7d9d5b22c92681

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ninecli-0.1.6-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.6-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 f64b031236a9ecb84e55a2fa593dfd82748574f1e49d4a697f1365bc2dcc6f4a
MD5 039b8a17dc7296aef35d258223198bb0
BLAKE2b-256 88696d73ae37a5b62377129bf5898544af6860ffbb57eb7cc90547fcb8698fdc

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.6-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 68e2b2e32de815d0262f94b6348790a00b688f60910f0d3dc6a3b29f0a6200f1
MD5 15250fa7622759b0ffcfb35ea9fcb386
BLAKE2b-256 e58c9c6ea31cd9d1b38dc34dddc175f4e742ba15fd336ece07834143122313af

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.6-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 cd473cf235eae77c3b48edf95a1f7c39b5000c5fe4b167b06d75a442f6b21fed
MD5 599ec0afbf2dc8648ea3a419aae9091b
BLAKE2b-256 29cefc27ed23e287c9403a80bfb35a8faca83cb606d47d4bb9216e70d851991e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.6-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 03a3c0675e23d0530ab7a1ac467c7758c95e1f9038ccc1c7c2391d9944bc1b4a
MD5 2957c2270fcdffde7403e7397fea34c3
BLAKE2b-256 bb243232cf0cbe751e5779420add4d0e69b6670e05dc78fb15428664b83e3b8b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.6-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 bc88ae134942446c4baf0437f9a0ed0e113beefe0d64369a44384639e181baa0
MD5 58e75e0c8df8adf499db3adae7f49298
BLAKE2b-256 e23779a6559cc68cab8bfbcb96af8f557da9949f5453374357d1409ca69fb881

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.6-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 bc62a876dc6c61e38a052da0b493ffb46deb45f4bb696ab01954c47c3621d01b
MD5 79124ae566af25c05215d4c3a37aff21
BLAKE2b-256 21c0f64f22caf2fbe02ce8f5ccf38be300cad9a291387c7398907aab4e620210

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.6-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 03e79bd208845d22201cb01676d913b718d68cc274d3e5decd098f93e04ef870
MD5 64da10fd7d574d15e74c50169e32f9d5
BLAKE2b-256 eda2f573eff267a7e32b4eb9f12ac0f1564a9effd235db543860472c40e5d0a6

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