multicloud-cli
mctl connects your AWS account to Multicloud.
Multicloud then starts machines in your account, and AWS bills you directly.
You give Multicloud no password and no access key: you create one IAM role with the public
Terraform module multicloud/multicloud/aws.
Install it from PyPI (Python 3.10 or later):
pipx install multicloud-cli # or: uv tool install multicloud-cli
If mctl is not found after the install, run uv tool update-shell (or pipx ensurepath) and open a new shell.
Upgrade with uv tool upgrade multicloud-cli (or pipx upgrade multicloud-cli). Check the version with mctl --version.
Connect an AWS account
You need to be an owner of your team on multicloud.io, an AWS login that can create IAM roles, and OpenTofu or Terraform 1.5 or later.
mctl auth login # opens your browser; sign in as you do on multicloud.io
mkdir multicloud-aws && cd multicloud-aws
mctl cloud-account create --cloud AWS --account 123456789012 --region us-east-1
mctl cloud-account apply 7 # init, plan, asks you, apply, then waits for "Ready"
Keep the folder: it holds the Terraform state of the role.
To run OpenTofu or Terraform yourself, get a one-time connect code instead of apply:
mctl cloud-account token 7 # prints one "export TF_VAR_multicloud_connect_token=..." line
tofu init && tofu apply
mctl cloud-account verify 7 --wait
Commands
| Command | What it does |
|---|---|
mctl auth login |
Sign in with your browser (SSO). --no-browser prints a code to enter on another device (SSH, containers). --api-key stores an API key instead (hidden prompt or --key-stdin). |
mctl auth status / logout |
Show how you are signed in and check it works; end the session and remove the stored sign-in and key. |
mctl cloud-account create |
Declare an AWS account and write multicloud.tf. |
mctl cloud-account apply <id> |
init, plan, a question (--yes skips it, --plan-only stops after the plan), then apply with a fresh connect code and a wait for the check. |
mctl cloud-account token <id> |
A new one-time connect code, for a manual terraform apply. |
mctl cloud-account verify <id> [--wait] |
Check the role again: Ready (exit 0), the missing permissions (exit 1) or pending (exit 5). |
mctl cloud-account list / show <id> [--json] |
The connections of your team. |
mctl overview / billing |
Setup checklist, alerts and pool counts; payment gate status. Read access or a member sign-in. |
mctl extend create NAME |
Make an Extend pool. Owner sign-in only. |
mctl peering create|list|show|revoke POOL ... |
Manage the peerings of an Extend pool. Owner sign-in only. |
The connect code reaches Terraform only through the environment of the apply process.
mctl never prints a key or a token, and only mctl cloud-account token prints a connect code.
Overview, Extend pools and peerings
mctl overview # checklist, alerts, pools by status
mctl billing # payment gate
mctl extend create edge --max-servers 5
mctl peering create edge --pods 20 # prints the install command for your cluster
mctl peering show edge 4 # a READY peering also gives its bundle, once: save it
mctl peering revoke edge 4
extend and peering need an SSO sign-in as an owner (mctl auth login); an API key gets 403.
Sign in
mctl auth login opens your browser on auth.multicloud.io (authorization code with PKCE, on a temporary
port of 127.0.0.1). mctl auth login --no-browser uses the device flow instead: it prints a web address and a
code, and you sign in on any device. Both give a short-lived access token (15 minutes) and a refresh token.
mctl keeps them in the OS key store, else in ~/.config/multicloud/credentials (mode 0600), and refreshes the
access token by itself. A session ends after at most 10 hours; then run mctl auth login again.
- Organization. The sign-in holds the organizations you belong to. With one, no
--orgis needed. With several, name one:--org <team-id>orMULTICLOUD_ORG. - Order of credentials.
MULTICLOUD_API_KEY(for CI), then the SSO sign-in, then a stored API key. - Roles. Pool reads need membership. Everything that changes a pool, and every
cloud-accountcommand, needs the owner role of the team (an API key with the matching scope works too). - Logout.
mctl auth logoutends the session at Keycloak and deletes the local copy. Becausemctlshares your Keycloak browser session, it signs you out of Keycloak in your browser too. - Settings.
MULTICLOUD_ISSUER_URL(orissuerin~/.config/multicloud/cli.json) overrides the Keycloak realm URLhttps://auth.multicloud.io/realms/multicloud. Like the API URL it must behttps://. - Other environments. The defaults point to production (
auth.multicloud.io,api.multicloud.io). For another environment, setMULTICLOUD_ISSUER_URL(for examplehttps://auth.example.com/realms/multicloud) andMULTICLOUD_API_URL(for examplehttps://api.example.com) to that environment's hosts beforemctl auth login. Set both: the sign-in server (issuer) and the API must belong to the same environment, or the API rejects the token. - API key (CI, scripts).
mctl auth login --api-key --org <team-id>, orMULTICLOUD_API_KEYin the environment.
Manage CI pools
A pool is a group of build machines that Multicloud starts for you and stops when they are idle.
With an API key, reading needs Read access, create and update need Write, and delete, hibernate and wake need Admin.
With an SSO sign-in, reading needs team membership and the rest needs the owner role.
Every command takes --org <team-id> (also before the command: mctl --org acme pool list) and, where it makes
sense, --json for the raw answer. pool list and cloud-account list take -q (only the IDs) and
--no-headers. Data goes to stdout; progress and questions go to stderr.
<pool> is the number from mctl pool list or the exact pool name.
mctl pool classes # the machine sizes you can ask for
mctl pool create ci --github-org my-gh-org --max-cost-per-hour 2 --classes cpu-4 \
--clouds '[{"type":"AWS","regions":["us-east-1"]}]'
mctl pool list
mctl pool hibernate ci # pause: no machines, no cost, the name stays
mctl pool wake ci --wait --timeout 15m # exit 0 ready, 5 timeout, 6 pool deleted, 1 other error
| Command | What it does |
|---|---|
mctl pool create <name> |
Make a pool. Use --from-file pool.json for the full request, or the flags --github-org, --clouds, --classes, --max-cost-per-hour, --spot-policy, --cpu-units-requests, --image-by-class, --egress-by-class, --class-headroom. A repeated run with the same --idempotency-key makes one pool. Put cloud keys in the file, not on the command line. |
mctl pool update <pool> |
Change --max-cost-per-hour, --classes, --spot-policy, --cpu-units-requests or --clouds. Only the options you give change. |
mctl pool show <pool> / cluster <pool> |
The pool, or its machines and their cost. |
mctl pool hibernate <pool> / wake <pool> |
Pause or resume a pool. |
mctl pool delete <pool> [-y] |
Delete a pool for good. It asks first; without a terminal, -y is required. To pause a pool, use hibernate. |
mctl pool rotate-credentials <pool> / rotation-status <pool> |
Renew the pool's access credentials; show the progress of the last renewal. |
Find servers and prices
The catalog lists the servers of AWS, Azure and Google Cloud with prices. An API key needs the Catalog access
(catalog scope); MULTICLOUD_API_KEY needs no --org. Filter names are the API names: --min-vcpus and
--min_vcpus both work. Data goes to stdout; the page line (Page 1 of 3, 42 results.) goes to stderr.
mctl catalog search --provider aws --min-vcpus 8 --max-price-per-hour 0.5 --sort-by vcpus
mctl catalog search --has-accelerator --accelerator-name 'A100.*' --price-type SPOT -q # only the IDs
mctl catalog show 11
mctl catalog compare 11 12 13
mctl catalog locations --provider aws
mctl catalog providers
mctl catalog field-values # the values the filters accept
Every command takes --json. mctl catalog search -h lists all filters.
Use it from an AI agent
The skill multicloud-connect-aws in multicloud/skills teaches an agent
such as Claude Code to run these commands. The agent asks you before each apply and never sees the key or the code.
More
Every command shows its options with --help or -h, for example mctl pool create -h.
Exit codes: 0 ok, 1 error, 2 usage, 3 sign-in or access, 4 not found, 5 still pending or wait timeout, 6 pool gone.
Shell completion: eval "$(_MCTL_COMPLETE=zsh_source mctl)" in ~/.zshrc (bash_source for bash).
License: Apache-2.0.
Metadata
Release files for multicloud-cli 0.2.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 |
|---|---|---|---|---|
| multicloud_cli-0.2.0.tar.gz | 69.6 kB | Without provenance | Details for multicloud_cli-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| multicloud_cli-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for multicloud_cli-0.2.0-py3-none-any.whl |
Total release size: 120.9 kB
Release files / multicloud_cli-0.2.0.tar.gz
| Download URL | multicloud_cli-0.2.0.tar.gz |
|---|---|
| Size | 69.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f4dd81e9e0224bfc29376a6171a7ea70dce0f8bafad3eeae7baf9207168749a
|
|
BLAKE2b-256 checksum How to use checksums |
f844a5c5c60a019d00856faa8dcd164fd891bc0bf56f174ebbcf4e8103d5cb34
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / multicloud_cli-0.2.0-py3-none-any.whl
| Download URL | multicloud_cli-0.2.0-py3-none-any.whl |
|---|---|
| Size | 51.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0d32cafd1df32a7190677194d93335b096ef8653cca83afc03b47f63d8347fac
|
|
BLAKE2b-256 checksum How to use checksums |
d0de056e849a3331f0c363173af27dac09731d5d59380c5a64c9d6a0a36ba5c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.2 {"installer":{"name":"uv","version":"0.12.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for multicloud-cli 0.2.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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A 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.