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

Uploaded Python 3Windows ARM64

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

Uploaded Python 3Windows x86-64

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

Uploaded Python 3musllinux: musl 1.2+ x86-64

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

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3manylinux: glibc 2.17+ x86-64

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

ninecli-0.1.5-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.5-py3-none-win_arm64.whl.

File metadata

  • Download URL: ninecli-0.1.5-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.5-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 027da5bffd524708e7096c14c7dbecb508c3eef0fcebc8ea7ccbc94fbe475615
MD5 b83dedf87e12a332e8b73516ea509c2f
BLAKE2b-256 65130a5a70e2a09157c030b45ec575b4b445320ec08a8da1fe6ecfd32eee3065

See more details on using hashes here.

File details

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

File metadata

  • Download URL: ninecli-0.1.5-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.5-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 2adad31df50e70b165b83615687089e21d9f1a99000bbe8cfaf90ccf62f7735c
MD5 eb6e45ba89ff95999701b6e9cbdfadab
BLAKE2b-256 8d1381914a2ca3f327d2f7df514f0c9a315a26232636c2893d886b74d3fc3894

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.5-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 8a621fa9e171d0c77b238bf7ecac1a8eed602bf2e9b8228174f625310642840a
MD5 867051f6399f1b6136a6af8025474830
BLAKE2b-256 7c71fb3f5b52551116f67aeb97c2c13650a3ecdf4d56b256d36b8c6aaec4a444

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.5-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 9e12ae63074ad8be8b59e066d69e2b968518c202a1c9b24e1686bc16a2a5c118
MD5 40048703dd6171003d7ee43ad5ac2607
BLAKE2b-256 e09c87a14886e6608a67b4653a18dadc5eb19c449727cd25e37c2fe4e1d4c4d1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.5-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 e5a6ea88fae78e1369ea5e58d2c802cc234301236cf09746d617fb410cc2b620
MD5 fbd7e75d50ea53e4d0502ee5ed52ac90
BLAKE2b-256 5e06440a876811ead4a1235730cf04793f357d329e157b86099fe66a8eb69598

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.5-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 850a70ea8ea761852703fa36653377f94cc40673ca8ef21810c28e337b38fb5d
MD5 3b8dda908d5aa1d4e3fecaa16f67293c
BLAKE2b-256 1bc3c3f52e9e061de77f580ad7c94295c36da99eaa323b93ff764e7db79673d8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.5-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 13fead554aba0b276deb2f4ce6e279b014e1fa7dc15fe45567672f7d2d1ef5d0
MD5 7d0aab2b1eaab760e4f69b8aead17cc4
BLAKE2b-256 85e3e8474fc13f2f227b9893ae4d036e1b1c6921fb9512dcf977cf01139b692e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.5-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 265795abb557f2783eb9d0e0cd50e8a091a6157431ef03f99b64b0e0f020fcff
MD5 e1c184aea3ff70ffd1ba45a748c81766
BLAKE2b-256 ce417b758df93c2c290e7e0dfedd25e4de7cfe26b08940ce322ec6f37173046e

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