⚡ autodl-cli
Your AutoDL GPU cloud, one command away.
A typed CLI, a public Python API, and an optional MCP server for AutoDL's web API.
account · gpu · image · instance · nfs · tools — all from the command line.
autodl-cli puts AutoDL's GPU cloud in your shell. Authenticate once, then check your balance, hunt for idle GPUs across regions, drill into machine-level capacity, browse the base-image catalogue and your saved images, and read every instance on your account — without clicking through the web console.
⚠️ This is an unofficial tool, not affiliated with AutoDL. It does not use a public developer API — it reverse-engineers the private endpoints behind the AutoDL web console. Those endpoints can change, rate-limit, or stop working at any time, so use this at your own risk.
🚀 Quick Start
Requirement: Python 3.10 or newer. Check with
python --versionbefore installing.
pip install autodl-cli
Installing from source instead:
git clone https://github.com/KrisTHL181/autodl-cli.git
cd autodl-cli
pip install -e .
1. Authenticate
Credentials land in ~/.autodl-cli/config.toml (mode 0600). Only the API token
and the device fingerprint are stored — never a password.
# Paste a cURL command, an `Authorization:` line, a JSON blob, or a HAR file
# copied from the AutoDL console (DevTools → Network).
autodl auth paste
# Or log in with a phone number and password.
autodl auth login --phone 13800138000
# Non-interactive login.
AUTODL_PASSWORD=... autodl auth login --phone 13800138000
auth login needs a device fingerprint captured from the browser, because
AutoDL ties its captcha counter to that value and the CLI refuses to invent one.
Run autodl auth paste on the portal's login request first; it saves the
fingerprint even when the request carries no token yet.
2. Verify
autodl account me # who am I?
autodl account balance # how much credit is left?
✨ What You Can Do
👤 Account
Inspect the authenticated profile and wallet. Balances are rendered in yuan;
--json returns the API's raw thousandths-of-a-yuan integers instead.
autodl account me
autodl account balance
autodl account balance --charge-type payg
🎮 GPU Capacity
See what is actually free before ordering. gpu list shows per-region GPU
availability and can print the region catalogue when no region is given.
gpu find searches a model name across every region. gpu machines goes one
level deeper: individual machines with idle cards, filtered by region, GPU model,
chip vendor, CPU architecture, billing mode, machine tag, network-disk support,
and availability dates — then sorted by price, idle count, or disk size.
autodl gpu list # every region and its stock
autodl gpu list -r shanghai -a # idle GPUs only in one region
autodl gpu find 4090 -a # search a model across all regions
autodl gpu machines --idle 4 --gpu "RTX 4090" --sort price
autodl gpu machines --charge-type monthly --mount-net-disk --all
🖼️ Base Images
The create page's image picker is a four-level tree: framework, framework
version, Python/OS, and CUDA. image list flattens it into one row per
selectable image and shows the base-image UUID used when ordering. Filters are
case-insensitive substring matches, so --cuda 12 catches every 12.x toolkit.
autodl image list
autodl image list -f pytorch --cuda 12
autodl image list --python 3.12 --chip nvidia
autodl --json image list --chip mthreads | jq -r '.[].image_uuid'
image list-private shows the images saved from your own instances, with the
numeric ID, save status and progress, size, framework, creation time, and UUID.
Every page is fetched, so the listing is complete regardless of AutoDL's page
size.
autodl image list-private
autodl image list-private --page-size 20
autodl --json image list-private | jq -r '.[] | [.id, .name, .status] | @tsv'
Deletion uses that numeric ID and is irreversible, so the command asks for
confirmation; pass --yes in scripts.
autodl image delete-private 842525
autodl image delete-private 842525 --yes
🖥️ Instances
List every instance on the account and drill into any of them. The list marks how
many GPU cards are still free on each instance's machine, flags instances that
fell back to CPU mode, and shows any scheduled shutdown next to the release
deadline. Filters run server-side where the API supports them, and -q matches
UUID, name, region, machine alias, or GPU name locally.
autodl instance list
autodl instance list --status running -q 4090
autodl instance list --unbind-sub-user
autodl instance detail <instance-uuid>
autodl instance power-on <instance-uuid>
autodl instance power-off <instance-uuid>
autodl instance release <instance-uuid>
autodl instance release <instance-uuid> --yes
autodl instance save-image <instance-uuid> my-image
autodl instance save-image <instance-uuid> my-image --try-again
autodl instance create --machine-id 1c0641804d --image base-image-ee43618uo7
autodl instance create --region nm-B2 --gpu "RTX 3090" --image base-image-ee43618uo7
autodl instance create --machine-id 1c0641804d --private-image image-abcd1234 \
--gpu-num 2 --name trainer --data-disk 50
power-on posts to /api/v1/instance/power_on; AutoDL accepts the request
immediately, and the instance may take a moment to show as running. power-off
posts to /api/v1/instance/power_off and keeps the data disk; AutoDL releases
a powered-off instance after the retention window shown by instance list
unless it is powered on again. release posts to
/api/v1/instance/release and deletes the instance and its data disk
immediately; it is irreversible, so the command asks for confirmation unless
--yes is passed. save-image posts to
/api/v1/instance/image/save; AutoDL accepts the request immediately, and the
image appears under the account's private images once the save finishes.
create posts to /api/v1/order/instance/create/payg and orders a
pay-as-you-go instance. Pass either --machine-id or both --region and
--gpu; with the latter the first machine in that region with enough idle
cards of the requested model is ordered on. Use --image for a base image or
--private-image for an image saved from an instance, but not both.
--gpu-num, --name, and --data-disk set the GPU count (default 1), the
instance name, and extra data-disk size in GB (default 0). The command returns
the new instance UUID immediately — the instance may take a moment to appear in
instance list — and does not prompt for confirmation.
🗂️ Network Disk (NFS)
AutoDL's network disk is regional: each region has its own volume and its own
API host. nfs regions shows the available signs, hosts, and quota. nfs ls
reads a directory, nfs rm deletes a file, and nfs upload sends a local file
in the same 5 MiB chunks the web console uses, so large files work too.
autodl nfs regions
autodl nfs ls / --region bj-B1
autodl nfs ls /datasets --region bj-B1
autodl nfs upload ./model.bin --region bj-B1
autodl nfs upload ./model.bin --region bj-B1 --dir-path /models --filename v2.bin
autodl nfs rm /models/old.bin --region bj-B1
autodl nfs rm /models/old.bin --region bj-B1 --yes
--region is required because there is no account-wide default volume. Uploads
hash the first 1 MiB of the file and send that digest with every chunk, matching
the console; a file larger than 5 MiB is split into ordered multipart chunks,
with is_last set on the final one. rm is irreversible and asks for
confirmation unless --yes is passed; it deletes files, not directories.
🛠️ API Debugging
autodl tools request is a thin HTTP client for the AutoDL API. It attaches the
stored token and the required AppVersion header automatically, and works
against arbitrary URLs when --no-auth is passed.
autodl tools request /api/v1/user/detail
autodl tools request /api/v1/instance -X POST -d '{"page_index": 1}'
autodl tools request /api/v1/user/detail --curl # print an equivalent curl
autodl tools request /api/v1/user/detail -i # include status line and headers
autodl tools request /api/v1/user/detail -o out.json
🤖 MCP Server
Install the optional extra and expose every CLI command as a typed MCP tool —
autodl_instance_list, autodl_account_balance, autodl_gpu_machines, and so
on. Each tool inherits the root json switch, and autodl_help / autodl_run
remain available as escape hatches.
pip install "autodl-cli[mcp]"
autodl-mcp # serve over stdio
autodl-mcp --groups instance # only the instance commands
auth paste is excluded from the typed tools because it reads credentials from
stdin, which the MCP child process does not have.
📦 Python SDK
Every handler is reachable through autodl_cli.api, which normalises failures
into one exception hierarchy. Tokens are passed explicitly rather than read from
the config file.
from autodl_cli import api
from autodl_cli.errors import AutoDLError
token = "<your JWT>"
try:
me = api.get_current_user(token)
balance = api.get_balance(token)
instances = api.list_instances(token, query="4090")
for instance in instances:
print(instance["uuid"], instance["name"])
except AutoDLError as exc:
print(f"AutoDL call failed: {exc}")
Use api.AutoDLClient directly when you need the raw authenticated HTTP client.
🧾 JSON Everywhere
--json turns any command's output into plain UTF-8 JSON with no ANSI escapes,
ready for jq and scripts. It is a global option, so it goes before the
subcommand:
autodl --json instance list | jq '.[].uuid'
autodl --json gpu machines --sort price --all | jq '.[0]'
🏗️ Architecture
src/autodl_cli/
├── main.py # Click root group; registers every command group
├── api.py # public Python SDK facade
├── client.py # httpx client — auth, AppVersion header, error mapping
├── config.py # read/write ~/.autodl-cli/config.toml (atomic, 0600)
├── paths.py # the data directory, resolved in one place
├── errors.py # AutoDLError hierarchy
├── output.py # all Rich rendering and --json output
├── commands/ # argument parsing, one module per domain
│ ├── _helpers.py # shared token/ID helpers
│ ├── auth.py
│ ├── account.py
│ ├── gpu.py
│ ├── image.py
│ ├── instance.py
│ ├── nfs.py
│ ├── tools.py
│ └── config.py
├── handlers/ # one module per domain; return plain dicts
│ ├── auth.py
│ ├── account.py
│ ├── gpu.py
│ ├── image.py
│ ├── instance.py
│ ├── nfs.py
│ └── tools.py
├── utils/wait.py # jittered sleep helper
└── mcp/
├── generate.py # AutoDL-specific click2mcp configuration
└── server.py # autodl-mcp stdio entry point
tests/
├── conftest.py # redirects the data tree, registers --live options
├── test_*.py # offline tests
└── live/ # collected but skipped without --live
CLI (main.py — Click group)
→ Command modules (commands/<name>.py — each exports register_<name>())
→ Handlers (handlers/<domain>.py — call the API, return plain Python data)
→ Client (client.py — httpx session, auth, error mapping)
↓
AutoDL web API (reverse-engineered)
| Layer | What It Does |
|---|---|
| 🔐 Auth | Stores a browser JWT and device fingerprint, or logs in with a phone number and password. Writes are atomic and private to the user |
| 🌐 Client | Adds the mandatory AppVersion header, attaches the bearer token, maps HTTP and transport failures onto AutoDLError subclasses |
| 🧩 Handlers | Translate API responses into plain dicts. Never print, never read environment variables, so api.py and the MCP server can reuse them |
| 🎨 Output | Owns every Rich style, table, and JSON dump. Commands never print directly |
| 🔌 MCP | click2mcp walks the Click tree and synthesises typed tools; mcp/ only supplies AutoDL-specific configuration |
🧪 Extras
Optional Dependencies
pip install "autodl-cli[mcp]" # click2mcp — the autodl-mcp server entry point
pip install "autodl-cli[test]" # pytest, for working on the project itself
Shell Completions
Click ships completion for each shell — add the matching line to your rc file:
# bash
eval "$(_AUTODL_COMPLETE=bash_source autodl)"
# zsh
eval "$(_AUTODL_COMPLETE=zsh_source autodl)"
# fish
_AUTODL_COMPLETE=fish_source autodl | source
Local Data
~/.autodl-cli/
└── config.toml # API token, device fingerprint, phone area
AUTODL_CLI_HOME relocates the whole tree, which is how the test suite keeps its
state out of your real config.
Development
pip install -e ".[test]" # editable install with pytest
pre-commit run --all-files
ruff check .
ruff format .
pytest # offline tests, no network
pytest --live # hit the real AutoDL API
pytest --live --live-write # allow tests that modify a real account
Live tests are collected but skipped unless --live is passed; tests/conftest.py
redirects the data tree to tests/.state/ before any project import.
🤝 Contributing
The codebase is laid out for extensibility:
- New command? Add
commands/<name>.pywithregister_<name>(group) -> click.Group, then call it frommain.py. - New handler? Add
handlers/<domain>.py. Return plain dictionaries, never print, and go throughAutoDLClientinstead ofhttpx. - New MCP tool? Nothing to do — typed tools are generated from the Click tree.
Run the formatter before submitting:
pre-commit run --all-files
ruff check .
ruff format .
📜 License
MIT
Built for people who would rather ssh than click.
Report a bug · Fork this repository · Star ⭐ this repo!
Metadata
Release files for autodl-cli 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| autodl_cli-0.1.0.tar.gz | 148.2 kB | With provenance | Details for autodl_cli-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| autodl_cli-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for autodl_cli-0.1.0-py3-none-any.whl |
Total release size: 241.1 kB
Release files / autodl_cli-0.1.0.tar.gz
| Download URL | autodl_cli-0.1.0.tar.gz |
|---|---|
| Size | 148.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2d78959cb1525523c982ab4cc93cc815ae9475134fd19feee71accf433e167ad
|
|
BLAKE2b-256 checksum How to use checksums |
45d1e5afad98f14b4b2968bea0cbfd823937b90f264474a0db010b57cb6c6177
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.
Transparency logRelease files / autodl_cli-0.1.0-py3-none-any.whl
| Download URL | autodl_cli-0.1.0-py3-none-any.whl |
|---|---|
| Size | 93.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
32778974f4263ad5ccb1e69dff654a1d492b4e223d896db3a9d8edba491056a5
|
|
BLAKE2b-256 checksum How to use checksums |
8abcd90c16d3b902a95abd38d9332c316cafdaa468afe977eb9d7833513329a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.
Transparency logSecurity for autodl-cli 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for autodl_cli-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.