Metadata-Version: 2.5
Name: multicloud-cli
Version: 0.3.0
Summary: mctl: the Multicloud command line: sign in, connect your cloud account, run pools
Project-URL: Homepage, https://multicloud.io
Author-email: Multicloud Team <info@multicloud.io>
License: Apache-2.0
License-File: LICENSE
Keywords: aws,cli,cloud,kubernetes,multicloud
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: System :: Systems Administration
Requires-Python: >=3.10
Requires-Dist: click>=8.1
Requires-Dist: keyring>=24
Requires-Dist: requests>=2.31
Provides-Extra: test
Requires-Dist: pytest>=8; extra == 'test'
Description-Content-Type: text/markdown

# multicloud-cli

`mctl` connects your AWS account to [Multicloud](https://multicloud.io).
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](https://registry.terraform.io/modules/multicloud/multicloud/aws).

Install it from PyPI (Python 3.10 or later):

```bash
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.

```bash
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
export AWS_REGION=us-east-1           # Terraform needs a region when your AWS profile has none
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`:

```bash
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. |
| `mctl ssh allow\|list\|revoke`, `mctl node list`, `mctl ssh NODE [-y] [-- ssh args]` | Operators only (role `multicloud-admins`): open tcp/22 on a node for your own IPv4 address, list the nodes and the grants, connect. Details: `mctl ssh --help`. |

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

```bash
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 `--org` is needed. With
  several, name one: `--org <team-id>` or `MULTICLOUD_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-account` command, needs the
  owner role of the team (an API key with the matching scope works too).
- **Logout.** `mctl auth logout` ends the session at Keycloak and deletes the local copy. Because `mctl` shares
  your Keycloak browser session, it signs you out of Keycloak in your browser too.
- **Settings.** `MULTICLOUD_ISSUER_URL` (or `issuer` in `~/.config/multicloud/cli.json`) overrides the Keycloak
  realm URL `https://auth.multicloud.io/realms/multicloud`. Like the API URL it must be `https://`.
- **Other environments.** The defaults point to production (`auth.multicloud.io`, `api.multicloud.io`). For
  another environment, set `MULTICLOUD_ISSUER_URL` (for example `https://auth.example.com/realms/multicloud`) and
  `MULTICLOUD_API_URL` (for example `https://api.example.com`) to that environment's hosts before `mctl 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>`, or `MULTICLOUD_API_KEY` in 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.

```bash
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.

```bash
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](https://github.com/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.
