CLI tool
Azure/azure-cli avatar
Azure/azure-cli

Azure CLI: the az command, its install paths, and where it stops being the right tool

Azure Command-Line Interface. | Common scenarios and use Azure CLI effectively Please check Tips for using Azure CLI effectively.

4,643 stars3,490 forksPythonMIT

At a glance

What is it?
Azure CLI is Microsoft's cross-platform command line for Azure, written in Python and shipped under the MIT licence. It is a thin, scriptable layer over ARM, and the interesting decisions are about install channel, output formatting and telemetry.
Who is it for?
Adopt Azure CLI if you script Azure from bash, zsh or a CI runner and want one command surface across Linux, macOS and Windows. Do not adopt it if your work is mostly interactive portal browsing, or if your team is already standardised on PowerShell where the Az module gives you the same control plane with object pipelines.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Azure CLI is for, and who ends up using it

Azure CLI is a command line front end for Azure's Resource Manager control plane. The README frames it as a "multi-platform command line experience for Azure", and the usage line is the whole mental model:

bash
$ az [ group ] [ subgroup ] [ command ] {parameters}

That shape means every Azure service is reachable as a noun phrase followed by a verb. `az vm create`, `az storage -h`, `az feedback`. There is no plugin marketplace to learn and no per-service binary to install: one `az` entry point covers the surface.

The audience is narrower than "anyone who uses Azure". The people who get value from it are the ones who need the same operation to run identically on a developer laptop, a build agent and a container. If your Azure work is clicking through the portal, the CLI adds a vocabulary you have to learn for no return. If your work is a deployment pipeline, the CLI is the thing that makes the pipeline reproducible.

One detail worth noticing early: the repository is Python, the licence is MIT, and the default branch is `dev`. The last push was on 2026-08-12, the same day as the 2.89.1 release, so the release train and the branch are moving together rather than the branch being a stale mirror.

How az is structured: groups, JMESPath queries and exit codes

The mechanism that matters most is the output layer, because it is what makes the CLI scriptable rather than merely usable. Every command can emit JSON, table or TSV, and `--query` runs a JMESPath expression against the result before it is printed. The README example filters a VM list down to two projected fields:

bash
$ az vm list --query "[?provisioningState=='Succeeded'].{ name: name, os: storageProfile.osDisk.osType }"

That is a server-side list, a client-side filter, and a projection into a named shape, all in one argument. The practical consequence is that you rarely need `jq` for simple field extraction, and you rarely need a second round trip to get a field you already fetched.

The second mechanism is the exit code contract, which the README spells out as a table. 0 is success, 1 is a generic error such as a bad server status code or a CLI validation failure, 2 is a parser error meaning your command line itself is malformed, and 3 means a missing ARM resource, described as being used for existence checks from `show` commands. That last one is the useful part for automation: a `show` against a resource that does not exist is distinguishable from a `show` that failed for an unrelated reason, so a shell script can branch on `$?` without parsing stderr.

Tab completion is the third piece. The README shows completion working on group and resource names, not just on subcommands, which is why `az vm show -g [tab][tab]` lists resource groups. That requires the CLI to have a cached view of your subscription, so the first completion in a fresh shell can be slow.

Installing Azure CLI and running a first query

The README does not carry install instructions itself. It points to the install guide at learn.microsoft.com/cli/azure/install-azure-cli for detailed steps and to a separate install troubleshooting document in the repository for common failures. That is the honest answer to "how do I install Azure CLI": the project deliberately keeps platform installers out of the README, so the version you get depends on the channel you choose rather than on a command in this repository.

If you want to try it without installing anything, the README offers a test run from Azure Cloud Shell. If you want a pinned, disposable environment, the repository maintains a Docker image and documents this invocation:

bash
docker run -u $(id -u):$(id -g) -v ${HOME}:/home/az -e HOME=/home/az --rm -it mcr.microsoft.com/azure-cli:<version>

The `-u` and `-e HOME` flags are there so the container writes its config as your host user and picks up your existing `~/.azure` directory, which is where login state lives. Without them you get a root-owned config directory on the host and have to log in again every run.

Once you have a prompt, the first real thing to do is authenticate and then confirm what you are pointed at. The README does not document the login flow beyond pointing at the get-started guide, but the command group is `az login`, and the CLI writes the resulting subscription context to the same config directory the Docker flags above mount.

For a first non-trivial use, the query example is the best one to copy because it exercises list, filter and projection together:

bash
az vm list --query "[?provisioningState=='Succeeded'].{ name: name, os: storageProfile.osDisk.osType }" --output table

You should see a table with a Name column and an Os column, one row per VM in the current subscription whose provisioning state is Succeeded. If the table is empty, the filter matched nothing rather than the command failing; check the exit code before assuming success.

Where Azure CLI is the wrong tool

The README is candid about one operational constraint, and it is worth reading as a limitation rather than a footnote. Under Data Collection it states that the software may collect information about you and your use of it and send it to Microsoft, and that telemetry collection is on by default. Opting out requires an explicit config write, not an environment variable set at install time:

bash
az config set core.collect_telemetry=no

If you operate in an environment where outbound telemetry from a build agent is a compliance question, that command has to be part of your image build, and it has to be re-applied anywhere the config directory is not persisted. The Docker invocation above mounts `$HOME`, so the setting survives between runs; a container that does not mount it will not.

The second limitation is structural rather than documented. The CLI is a control plane client. It is good at creating, listing, updating and deleting resources, and the README's list of effective-use topics is entirely about that: output formatting, passing values between commands, async operations, generic update arguments, `az resource`, `az rest`, quoting, proxies, concurrent builds. Nothing in that list is about data plane throughput, streaming or high-volume reads. If your job is moving bytes through a storage account, the CLI is the wrong layer and you want an SDK.

The third is quoting. The README lists "Quoting issues" as a known topic in its effective-use guide, which is an admission that passing complex values through a shell to a cross-platform CLI is a recurring source of mistakes. On Windows in particular, the difference between cmd.exe, PowerShell and a bash-compatible shell changes how a JMESPath expression is parsed before `az` ever sees it.

Azure CLI versus the Az PowerShell module

The real alternative for the same job is the Az PowerShell module. Both talk to the same ARM control plane and both cover the same resources, so the difference is not capability but the shape of the data as it moves through your script.

Azure CLI hands you text. You get JSON, table or TSV, and you reshape it with `--query` using JMESPath, or by piping into another process. Composition means string interpolation and careful quoting, which is exactly why the README devotes a section to quoting issues.

Az PowerShell hands you objects. A command returns .NET objects with properties, and composition means passing an object into the next cmdlet's parameter by property name. There is no serialisation boundary to cross and no shell quoting layer between the two commands.

That makes the choice mostly about your existing automation. If your pipelines are bash, your agents are Linux containers, and your configuration management is already text-oriented, Azure CLI fits without adaptation. If your operators live in PowerShell, the Az module removes a class of bugs that the CLI cannot remove, because the bug lives in the shell rather than in the tool. Running both is common and not contradictory: the CLI for container and Linux CI paths, Az for Windows administrative scripts. What does not work well is treating them as interchangeable inside one script.

Maintenance, upgrade cost and what the MIT licence means here

The release cadence is visible in the tags. 2.89.1 landed on 2026-08-12, 2.89.0 on 2026-08-04, and 2.88.0 on 2026-07-07. That is a minor release roughly monthly with patch releases in between, and the last push to `dev` was on 2026-08-12, so the branch and the release are in step. The upgrade cost is not zero, but it is also not a migration project: the CLI's own update path is the install channel you chose, and the README's edge builds section exists for people who want the `dev` branch build ahead of a release, distributed as an MSI, a Homebrew formula and an Ubuntu package among others. Edge builds are a deliberate trade: newer behaviour in exchange for running code that has not been through the release process.

There is one build-level constraint worth knowing if you install from source or vendor the package. The repository's requirements.txt pins setuptools below 81, with a comment explaining that newer setuptools breaks the CLI's setup.py-based builds because 81 removes `setup.py --dry-run` and changes distutils command signatures, and 82 removes pkg_resources. If you are packaging Azure CLI yourself, that pin is not optional advice; it is the difference between a working build and a broken one.

The licence is MIT. That is permissive: it allows use, modification and redistribution with the licence and copyright notice preserved, and it does not impose a copyleft obligation on your own code. It is not legal advice, and the repository also ships a NOTICE.txt alongside the LICENSE, which is the file to read if you are redistributing rather than just consuming.

Editorial conclusion

Adopt Azure CLI if you script Azure from bash, zsh or a CI runner and want one command surface across Linux, macOS and Windows. Do not adopt it if your work is mostly interactive portal browsing, or if your team is already standardised on PowerShell where the Az module gives you the same control plane with object pipelines. Before committing, verify two things: that the install channel you pick matches how your runners get updates, and that you are comfortable with telemetry being on by default until someone runs az config set core.collect_telemetry=no.

Frequently asked questions

What is the Azure CLI?

It is Microsoft's multi-platform command line for Azure, written in Python and structured as `az [ group ] [ subgroup ] [ command ] {parameters}`. The README describes it as a next generation command line experience for Azure and points to Azure Cloud Shell for a test run without installing anything.

How do I install the Azure CLI?

The README does not include install steps; it refers readers to the install guide at learn.microsoft.com/cli/azure/install-azure-cli, with a separate install troubleshooting document in the repository for common failures. For a disposable environment the repository also maintains a Docker image at mcr.microsoft.com/azure-cli.

How do I use the Azure CLI in Visual Studio Code?

The README describes the Azure CLI Tools extension, which lets you create .azcli files with IntelliSense for commands and arguments, snippets that insert required arguments, a command to run the current line in the integrated terminal, and a side-by-side output view. It also notes that enabling IntelliSense for other file types such as .ps1 or .sh requires a workaround referenced in microsoft/vscode-azurecli#48.

Is Azure CLI the same as Cloud Shell?

No. Cloud Shell is a browser-hosted environment that the README offers as a way to take a test run without installing anything, while Azure CLI is the tool itself, which you install locally or run from the project's Docker image. Cloud Shell is a convenience entry point, not a separate product.

What is Azure CLI versus PowerShell?

Both reach the same ARM control plane, but Azure CLI returns text you reshape with JMESPath through `--query`, while the Az PowerShell module returns objects you pass between cmdlets by property name. The README's effective-use guide lists quoting issues as a known topic, which is the practical cost of the text-based approach.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/azure-azure-cli.svg)](https://hysenlabs.com/projects/azure-azure-cli)