MAAS UI: designing the new MAAS CLI

MAAS new CLI iteration 2

Last week, we have been testing out the CLI prototype with 6 MAAS CLI users to collect feedback on what we can do to improve our current CLI experience.

The first thing we tested out was the concept of the initial help or what our testers mostly referred to as “cheat sheet”.

When a user types maas or maas --help , you will see a cheat sheet as a guideline to help you do basic operations. In the first prototype, we introduced the concept of a primary object (machine), so by default, MAAS interprets an action against machines as an object when no object is indicated.

We received a lot of positive feedback for this concept and our testers wanted to see what other objects are available in the CLI. So to provide learnability, we added “Hints” to this page and indicate the current version of MAAS as well as other useful information.

One use case was frequently mentioned during the test regarding how to operate bulk actions for multiple MAASes or data centers.

Breaking down MAAS objects. In the current CLI, we have both singular and plural forms of object as a way to indicate collection services VS individual services. In this version, we stripped down all plural objects and broke them down into different categories for readability. We’ve also added a link to the documentation page for further readings.

Highlight: 5 out of 6 users mentioned that they don’t like reading the documentation and would not bother to read them because when they are working with the CLI they feel like they have to start the search over again in the documentation page. It felt like they have to do a double search to get to the point where they get the answer. So to reduce that hassle, we attached the right documentation link to the relevant commands help page.

In this prototype, we also introduced the concept of primary profile, which is reflected on the current prompt. A user may login to multiple profiles and set one of the profiles as their primary profile. When a user wants to take actions on multiple profiles such as deploying 10 identical machines 3 MAAS profiles, they just need to apply a profile flag to their deployment action.

The user will always see their current profile when they take action. This is to help prevent our users from making mistakes and that they are aware of their current environment.

To enhance the experience for learnability, we also try to break down the help page to be more meaningful. This is an example of the new help page. It will show you a brief description of the action, options, different ways to customise the outputs, examples, and related commands. For instance, maas list will list multiple or individual node description in a compact format as an overview. Whereas a related command is maas show, where a user can drill down detailed information of a particular machine in an elaborate manner.

After going through this user test, our team has agreed to make the default experience in the CLI compatible with our scripting users because we have a separate MAAS UI that can achieve the same purpose. However, if a user prefers to do things in MAAS using the CLI and expecting a beginner’s experience, they can use the” --interactive “ flag or “ -i” to use the interactive prompt.


When a user indicates -i in the CLI, they will be presented with an interactive prompt where, it will ask for required information for the deployment such as OS, release, kernel, setting a machine is a KVM host, and customising cloud-init user-data.

By default, maas deploy will throw an error, because a user needs to supply information about the machine or a characteristic of a collection of machines they wish to deploy.

However, if an error occurs, the prompt will provide guidelines and suggestions including a documentation to help our users perform an action correctly.

Since the default experience is tailored to scripting users, by default a user will get the prompt back when they perform an action. They will also be informed that the machine(s) they deployed are running in the background and they may use any of these suggestions to check up on the status of the deployment.

If a user wishes to have their prompt block when performing an action and want to see if it’s running, they can use the --wait flag to see the waiting state of the CLI. This will show a broken down version of the running task, a loading indication, and the time elapse. Time is quite important for MAAS users because for many users, if something is processing longer than usual, they would rather have that process aborted and reboot.

What’s next?

  1. We are still working to define a better way to help our users debug when an error occurs. So the error state is another important piece that we are focusing on. Our current goal is to enhance the learnability aspects of our CLI and help our users recover from their errors or mistakes.
  2. Another interesting feature is partial matching of the machine name. Currently, MAAS operates on machine IDs, which is not easy to fetch. We will allow our users to operate based on the machine names instead and they can either supply the full FQDN or just hostname. The current prototype provides suggestions for misspelled names and our next task is to allow partial string matching for this.

If you are reading about this and would like to add feedback, we are more than happy to find out how we can improve the CLI experience. Your feedback is a gift.


:fire: hell yeah ! This is fantastic.

One question though, will the new Maas CLI still play nicely with scripting. I’m currently using the Maas CLI to do bulk actions like build bonds on multiple servers using basic shell loops.

Looks like there are quite a few interactive and ‘ncurses prettyfying’ happening. Will the return codes / outputs get hidden at all?


Output will default to pretty but you’ll be able to change output format back to JSON. We’re also hoping to add some flags to make scripting easier, for example make a call blocking.


This is wonderful! I am so excited to try this out. I feel that the lack of interactability with the old MAAS CLI was one of the factors holding me back from learning how to use it. This is a huge benefit and is definitely greatly appreciated. I am totally excited to try out the interactive modes.

@dvnt, we will tailor our default experience to fit in with scripting users’ workflow, especially, when an action involves a waiting state. I’ve created --wait flag, if you want to block the command prompt and see the broken down tasks. If you don’t fill in required info such as the OS, release, or minimum kernel information, the CLI will use default values for those fields when deploying. For non-scriptors, they can use the -i,
–interactive flag to return interactive prompts and help them fill in required info for actions such as deploy.

For list commands and show commands, we will try to have the default output more human readable (table format), but in the --help, it should provide guideline commands to help you customize the output format (yaml, json, csv, values) and customize the columns and filtering your output views. :grinning:



I have a wishlist item for a new CLI concering adressing of objects. Apologies in advance if this is already being considered – I have little context on the scope of the new CLI.

Current MAAS CLI requires use of opaque synthetic ids for objects. E.g. to address nodes you need a system_id, interfaces and disks are also addressed by id, etc.

This leads scripts to often do things like:

a) get a list of objects, e.g. interfaces=$(maas maas-root interfaces read "$system_id")

b) query for the id you want, e.g. bond_slave1_id=$(echo "$interfaces" | jq -r ".[] | select(.name == ...).id")

c) do something with the object, such as:
maas maas-root interfaces create-bond "$system_id" name=bondX parents="$bond_slave1_id" ...

It would be cool if the CLI could be more flexible in addressing objects:

  • The biggest win would be to allow addressing objects by name (e.g. “eno1” for an interface, or “sda” for a disk) so you could e.g. do

maas maas-root interfaces create-bond foohost name=bondX parents=eno1 parents=eno2 ...

  • Building on that, the ability to address objects via a search expression would be useful. Something like (pseudosyntax): “interface_set[].type==‘physical’” to query physical interfaces, or “status==Ready and tag==MyTag” to get operate on nodes that are ready and have a specific tag



I’m glad you mentioned that! In the example in the “list” command, by default it will list everything, but you can also list single or multiple machines.

To list single machine
maas list [MACHINE_NAME] or maas list [ID]

To list all machines in ready status (with default columns)
maas list --status ready

To list all ready machines with customized columns -> FQDN,STATUS,CORE, ARCHITECTURE, POOL columns.
maas list -c FQDN,status="ready",core,arch,pool

Aside from that, we will accept partial string matching such as you may type “focal-foal” (hostname) instead of “focal-foal.maas” (full FQDN).
And if you made a typo, we will have a suggestion on the prompt such as:
“Did you mean xxxx”, where it will search for the nearest neighbors and suggests options.

You won’t need to type the profile name every time you use the CLI. We have a concept of primary profile. This means you can login to multiple profiles, set one of the profiles to your primary profile (where it will interact with by default on the prompt) and when making bulk actions you may perform an action such as deploying multiple machines with the same spec on multiple profiles. It will look something like this.

maas deploy -s acquired --profile=profile1,profile2,profile3

To deploy all acquired machines on profile1, profile2, and profile3.

What he said :sunglasses:

Take my money!

Hey amylily,

thanks for the update. As far as I understand however this only applies to machine names, is that correct?

Or can I address other objects (e.g. interfaces, disks or vlans, …) via name (or partial string match) as well?


Hi @chrome0,
Ideally, other objects as well. The current design only shows the machine associated objects, but ideally, we will apply the same principle for all other objects.

Feel free to put more feedback here, we’re stilling in the designing process of the new CLI :wink:

If you want to play around with it, you can clone this project:

  • clone it into your empty container/VM or any empty instance so it doesn’t override your current maas.
  • You will need to install node(v12) and npm(v6), as this prototype is created in JavaScript. (for demo and testing purposes only)
  • $ npm install -g //install all dependencies in this project globally so you can use $ maas as a command on your terminal

The prototype can only do
maas (global help cheat sheet)
maas object list
maas list
maas list [machine_name]
maas list --format json
maas commission [machine_name]
maas deploy [machine_name]
maas deploy [machine_name] --wait
maas deploy [machine_name] -i
maas deploy -s allocated
maas deploy -s allocated -i
maas deploy -s allocated --wait

The purpose of this prototype is to show different representations such as interactive mode, waiting mode, error state, success state, default list.

If you would like to do a proper testing session where I can get to understand your workflow better and collect more live feedback, please let me know :slight_smile:

This looks amazing. Great job, as always @amylily!

1 Like

Hey @amylily,

thanks for that, this sounds very very nice!

If it helps, some more examples of cli snippets in use, to maybe give some context around workflows:

To add nodes matching a specific hostname (e.g. prefixed with “kube”) to a tag we’re I’m something like this currently:

maas maas-root tag update-nodes kubernetes $( maas maas-root nodes read | jq -r '.[] | select(.hostname | startswith("kube") ) | .system_id ' | while read i ; do echo "add=$i" ; done | paste -s )

It would be awesome if I could instead do something like (passing in a regex for a hostname pattern):

maas maas-root tag add-nodes kubernetes "kube.*"

Filtering by power type (listing non-virsh) and listing hostnames:

maas maas-root nodes read | jq -r '.[] | select(.power_type!="virsh")| .hostname'

Not sure if a filter flag makes sense. As I understand there’s going to be a -c flag to customize output cols – are these going to be arbitrary columns? It would be cool to have an output column power_type, could easily grep then for this. Similarly, having node_type and power_address as an output col would be great.

In a similar vein it would be great to get at nodes ipaddress and macaddr easily. Currently I’m doing sth like this:

maas maas-root nodes read | jq -r '.[]|{host: .hostname, mac_addresses: [.interface_set[].mac_address], ip_addresses: .ip_addresses}'

Similarly, to get at ipaddress/macaddresses for a specific tag

maas maas-root tag machines os-cs | jq -r '.[]|{host: .hostname, mac_addresses: [.interface_set[].mac_address], ip_addresses: .ip_addresses}'

Many thanks, looking forward to the new cli!


Hi @chrome0,

Thanks for sharing, I’ll add these use cases to my notes :slight_smile: .