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

Uploaded Python 3Windows ARM64

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

Uploaded Python 3Windows x86-64

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

Uploaded Python 3musllinux: musl 1.2+ x86-64

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

Uploaded Python 3musllinux: musl 1.2+ ARM64

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

Uploaded Python 3manylinux: glibc 2.17+ x86-64

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

ninecli-0.1.4-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.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

Hashes for ninecli-0.1.4-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 db6020e320e40dba4a463ab29d94dedcbfce8729b6f688df9462b5dd5bf03637
MD5 432e1a9400fc805f2d6a8eae1e46bcc4
BLAKE2b-256 4f80e4a56263e812adf67fa4d6ce43b248d8dc3870dcb3c9957d54d00bbfec0f

See more details on using hashes here.

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

Hashes for ninecli-0.1.4-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 a7e1b259250411dcae9f3be61d4d4787c3b4ede8d186b079916d5c346e5e45f4
MD5 1e2c386838b36d0313bcec5030ebd0fc
BLAKE2b-256 cd57500913cccf77edcd1c92dc09b7737a4d51f3bdb1e1d9523050fa4f983fed

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.4-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 6122558d88d638c032ae47af44d7ca3db1937e6123a8e1357bf6e25dd8ba3292
MD5 9ede9734854ba3c8a7e0f3d838fba0e0
BLAKE2b-256 edf943a04fc95443d592e4e10000329bacc2ec2d9ec51bd4117be55c07842167

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.4-py3-none-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 a40dd96752cf164513f272ad6d1d41f5e8b8c36be44200132d507b4b17b8f0e9
MD5 b5ed8e1a355097495b9298e87ec42a33
BLAKE2b-256 67d3ff579392b2f54c0533eb239b576e3edce46d0d9b2a681f98c6e6dd0e1ecb

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.4-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 141ba69d6d81802743a768a9cedcae6dae472db26d4f58e5854283f11b7e3a22
MD5 95dc53681c6c66d5d3147f87222b2fc0
BLAKE2b-256 e52e0ca403a51d1f2e8e3a730e3b2fc7105a273dd0788ec7d3949905397060d7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.4-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 199b4533e17d7da3ce501f3de6d0f7d1b86e58f1fb30ab6b80f7755ef6f29215
MD5 3bf2fb134e44f9ce63bfbe01c325fac0
BLAKE2b-256 746c12ffd97c8da7b78949cff55735fe550295f9b27cff11a2cea9d305449fb0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.4-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7cdb77a05114d210738d772f8da544a64e8c6dc7a72974d5688994da4c9db205
MD5 00a0cce486b73671843c5c741fef23b8
BLAKE2b-256 60e17fc71a741dbd82375c31d0ae02bba08ee8b8686cbf8523a64de5a7f40d99

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.4-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d7c34ae957f4484d43a0b52f45ab2b7aee5fe318dd3f9dc27727f3f582911cdd
MD5 a98cba277aabf3ab0636105beb9590ad
BLAKE2b-256 31b8e5bad9e3c6e945d109418396bc0bdec1c2ce018e0ac9471753e1f6b1a306

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