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.3-py3-none-manylinux_2_17_x86_64.whl (3.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

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

Uploaded Python 3manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3macOS 11.0+ ARM64

ninecli-0.1.3-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.3-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for ninecli-0.1.3-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 fbffdfe784ca8efe11393dcb869bfe429141545f96658153018b534a16462167
MD5 fb038d39c87ff6ea3721b7a8c1a02003
BLAKE2b-256 f7ddd0b7490362d2e66698df514823e8969ae9efaaaa1dd9d3003f5a5bf9690b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.3-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 e42108ec2653804ed2020e2b32d5accab4b1907f43b82686dcc72c216d514b45
MD5 63c6d3c61a63cfae55ad495f929f5722
BLAKE2b-256 100a27e4cc5c43390ad3f81af45b81cf2898c1e20e7823e39670d700d24a3b6e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.3-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8806914eea87049026515a8a822ed9fa3135f2191f386e96d1929c40a521fdae
MD5 7263d71af253748bbe0cca6478b000d4
BLAKE2b-256 09eb4e2322c0a32f84466a6f4d1fe83bd6152a40b2a05f7795d0eea8d95a5bd3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for ninecli-0.1.3-py3-none-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 46463a85d5bbe1369427c21a06f2944f34da48fcb33557d2fe73e6663ad7d73d
MD5 8b54e8e96602968a472b4d12c1fc41db
BLAKE2b-256 c8cb9ab13a1810c77968517bb7cbe6ba80de60211ec44c8ec8708e60e9f6b8bd

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