esxcli is the primary command set on an ESXi host. Almost every configuration and diagnostic action that has a command-line form lives under it, and unlike the older vim-cmd and esxcfg- tools, it has one consistent grammar and a machine-readable output mode.
Most esxcli material is a list of commands to copy. That is useful right up to the moment you need a command nobody wrote down, or you need the output in a script rather than on a screen. Both problems are solved by understanding how the tool is built rather than by memorising more of it.
This page covers the grammar: how a command is assembled, how to discover the ones your specific host version supports, how to make the output parseable, and how to run the whole thing remotely from a management workstation or from PowerCLI. The VMware ESXi command line cheat sheet stays the place to look up individual commands.
Applies to: ESXi 6.7, 7.0 and 8.0. The standalone ESXCLI 8.0 package is documented as compatible with commands in ESXi 6.7.x, 7.0.x and 8.0.x
Quick answer
Three commands teach you the entire tool. Run them in the ESXi Shell or over SSH and you will not need to search for an esxcli command again.
> esxcli --help
> esxcli esxcli command list
> esxcli --formatter=csv storage filesystem list
The first lists the top-level namespaces on this host. The second lists every command the host actually implements, which is the authoritative answer for that ESXi version. The third is the same data any script should consume: delimited, quoted, and addressable by column name instead of by character position.
How an esxcli command is built
Every esxcli command follows one structure, documented by Broadcom as:
esxcli [connection options] <namespace> [<namespace> ...] <cmd> [cmd options]
Four parts, always in that order. Once you can see the parts, an unfamiliar command stops being a magic string.
| Part | What it is | Example |
|---|---|---|
| Connection options | Where to run it. Omitted entirely in the ESXi Shell. Also where the --formatter dispatcher option goes | --server SRV-VC-01 --vihost esx01.lab.local |
| Namespace | The subject area. Nested namespaces are supported, so there are usually two or three | storage core |
| Command | The verb. Almost always list, get, set, add or remove | list |
| Command options | Arguments to the verb, shown by that command’s own --help | -d naa.60060160b0402000 |
The top-level namespaces are stable across recent versions: device, esxcli, graphics, hardware, iscsi, network, nvme, rdma, sched, software, storage, system, vm and vsan. The one worth noticing is esxcli itself: it is a real namespace holding commands that describe the command set.
Practical examples
1. Find a command without leaving the shell
The problem: you need to check something on esx01.lab.local and you do not know which namespace owns it. Searching the web returns commands for a different ESXi version that may not exist on this host.
The solution: walk the namespace tree with --help, or dump the whole command surface and filter it. The second is faster once you know it exists.
Appending --help at any depth lists what is available one level down. The output names the child namespaces and commands, so three or four of these walks you to anything.
# One level at a time - each step shows what is valid next
esxcli storage --help
esxcli storage core --help
esxcli storage core device --help
# Or dump every command this host implements and grep it
esxcli esxcli command list | grep -i snapshot
esxcli esxcli command list reads the command set from the host you are on, so it is version-accurate by definition. A command that is missing from that list does not exist on this build, no matter what a blog post says.
2. Make the output safe to parse
The problem: a script parses esxcli storage filesystem list by splitting each line on whitespace and taking the second field as the volume name. It works in the lab and returns garbage in production.
The solution: stop parsing the human table. The --formatter dispatcher option gives you the same data in a delimited format, and it must appear before any namespace.
Here is the default output. Note the second datastore name: an admin created it through the vSphere Client and used spaces.
Mount Point Volume Name UUID Mounted Type Size Free
------------------------------------------------- ----------- ----------------------------------- ------- ------ ------------ ------------
/vmfs/volumes/6512f1a2-9a8b7c6d-5e40-0025b5000102 DS-ISO 6512f1a2-9a8b7c6d-5e40-0025b5000102 true VMFS-6 549755813888 120259084288
/vmfs/volumes/6512f1a2-3b4c5d6e-7f80-0025b5000101 DS PROD 01 6512f1a2-3b4c5d6e-7f80-0025b5000101 true VMFS-6 2199023255552 879609302220
Splitting that on whitespace returns DS for the second volume, not DS PROD 01. The column layout is presentation, not a contract: it also shifts as soon as a value grows wider than its header.
The formatter fixes it. Values that contain the delimiter are quoted, and fields are addressed by name, so neither a space in a value nor a change in column order can break the script.
# --formatter goes BEFORE the namespace. It accepts exactly three values: csv, xml, keyvalue
esxcli --formatter=csv storage filesystem list
# keyvalue is the friendliest for shell scripts and for eyeballing a single object
esxcli --formatter=keyvalue system version get
# Write it out for later
esxcli --formatter=csv storage filesystem list > /tmp/filesystems.csv
On the consuming side, hand the CSV to a real CSV parser rather than to cut or awk. In PowerShell that is one cmdlet:
# ConvertFrom-Csv keys on the header row, so column ORDER is irrelevant
# and a quoted value containing a space or comma stays intact
$fs = ssh root@esx01.lab.local "esxcli --formatter=csv storage filesystem list" | ConvertFrom-Csv
$fs | Where-Object { $_.Type -eq 'VMFS-6' } | Select-Object 'Volume Name', Free
esxcli storage filesystem list --formatter=csv fails, because --formatter is a dispatcher option that belongs to esxcli itself, not to the command. Broadcom’s own guidance is blunt about it: always use a formatter for consistent output.
3. Run it against a host you are not logged in to
The problem: SSH is disabled on the hosts, as it should be, but you still need to collect the same value from twelve of them.
The solution: the standalone ESXCLI package runs on a management workstation and talks to the host or to vCenter over the API. The command after the connection options is identical to what you would type in the shell.
# Straight at a host
esxcli --server esx01.lab.local --username root storage nfs list
# Through vCenter: --server is the vCenter, --vihost picks the ESXi host to act on
esxcli --server SRV-VC-01 --username admin --vihost esx01.lab.local storage nfs list
--cacertsfile, or pass the thumbprint it printed with --thumbprint. Do not put a password on the command line: omit --password and let it prompt, so the secret stays out of shell history.
4. Run esxcli from PowerCLI
The problem: your automation is already PowerCLI. Shelling out to ssh for one value means managing a second set of credentials and parsing text again.
The solution: Get-EsxCli -V2 exposes the same command set as objects over the existing vCenter connection. No SSH, no text parsing, and the results are already typed.
The namespaces become properties and the commands become methods. Calling a method without arguments is .Invoke().
# -V2 is the supported interface. Without it you get V1, which is deprecated
$vmhost = Get-VMHost esx01.lab.local
$esxcli = Get-EsxCli -VMHost $vmhost -V2
# esxcli network nic list -> $esxcli.network.nic.list.Invoke()
$esxcli.network.nic.list.Invoke() | Select-Object Name, LinkStatus, MTU, Driver
# Typing the command without .Invoke() prints what it expects instead of running it
$esxcli.storage.nmp.device.set
For commands that take arguments, ask the method to build the argument table for you. CreateArgs() returns a hash table pre-populated with the parameter names, which removes all guesswork about what the command wants.
# Build the argument table, fill it in, then invoke
$arguments = $esxcli.storage.nmp.device.set.CreateArgs()
$arguments.device = "mpx.vmhba1:C0:T2:L0"
$arguments.psp = "VMW_PSP_MRU"
$esxcli.storage.nmp.device.Set.Invoke($arguments)
# Or inline, when you already know the argument names
$esxcli.storage.nmp.device.Set.Invoke(@{default=$true; device="mpx.vmhba1:C0:T2:L0"})
Where-Object and Export-Csv without parsing a single line of text.
5. Collect one value from every host in the cluster
The problem: an advisory asks you to confirm the driver version of the storage adapter on every host before a firmware campaign.
The solution: put the Get-EsxCli call in a loop over the cluster. Building the esxcli object per host is what makes this work, since each object is bound to one host.
# One esxcli object per host - do not reuse one across the loop
Get-Cluster 'PROD-CL01' | Get-VMHost | ForEach-Object {
$h = $_
$cli = Get-EsxCli -VMHost $h -V2
$cli.software.vib.list.Invoke() |
Where-Object { $_.Name -like 'nfnic*' -or $_.Name -like 'lpfc*' } |
Select-Object @{N='VMHost';E={$h.Name}}, Name, Version
} | Export-Csv -Path C:\reports\hba-drivers.csv -NoTypeInformation
Hidden gems
The V1 interface is deprecated and will disappear. The older Get-EsxCli without -V2 takes arguments by position, so $esxcli.storage.nmp.device.set($null, "device", "psp") silently means something different if a future ESXi build reorders or adds a parameter. Broadcom documents V1 as not guaranteed to be compatible across two ESXi versions. Any script you expect to keep should use -V2 and named arguments.
The command list is per-host, not per-product. Two hosts in the same cluster on different patch levels can implement different command sets. When a script has to run across a mixed cluster, check for the command before calling it rather than trapping the failure afterwards.
keyvalue is the format for a single object. CSV is right for lists, but for something like system version get that returns one record, --formatter=keyvalue produces one field per line, which reads well and diffs cleanly between two hosts.
Namespaces answer questions the vSphere Client cannot. The client shows you a datastore’s free space; esxcli storage core device list shows the device behind it, its queue depth and whether it is a boot device. When you are chasing a storage problem the host-level view is often the one that resolves it, which is the same reason rescanning storage from the host succeeds when a client-side rescan does nothing.
Which access method to use
The same command runs four ways. They are not interchangeable in practice, because each one has a different failure mode when the host is unhealthy.
| Method | Needs | Use it when |
|---|---|---|
| ESXi Shell or SSH | Shell access on the host | The host is in trouble and the management agents may be part of the problem |
Standalone ESXCLI, --server host | Network and API access to the host | SSH is disabled by policy but the host is reachable |
Standalone ESXCLI, --server vCenter plus --vihost | vCenter credentials | You want one credential for the whole estate |
Get-EsxCli -V2 | An existing PowerCLI connection | The result feeds a report or a larger automation |
Where this matters
- Firmware and driver campaigns.
software vib listacross every host, exported once, is the evidence a change board asks for. - Storage incidents. When a datastore goes inaccessible, the host view under
storage coretells you whether the problem is the path, the device or the filesystem. - Audit and compliance evidence. A CSV produced by a formatter is reproducible; a screenshot of a terminal is not.
- Hosts that will not respond in the client. The shell keeps working after hostd has stopped answering, which makes esxcli the last diagnostic tool standing.
- Mixed-version clusters after a partial upgrade. Comparing
esxcli esxcli command listbetween two hosts shows exactly what changed in the command surface.
Tips and limitations
--formatteraccepts exactly three values:csv,xmlandkeyvalue. Anything else is rejected, and there is no JSON formatter.- Never parse the default table output in a script. It is formatted for a human reader and the column widths move with the data.
--vihostis not supported by every command. If a command rejects it, run against the host directly instead; the command’s own--helptells you whether it is accepted.- esxcli commands that change state need the appropriate host privilege. A read-only account can run every
listandgetand will fail onset, which makes read-only accounts a safe default for reporting scripts. - The ESXi Shell is not a general-purpose Linux shell. Standard tools are BusyBox builds, so options you rely on elsewhere may be missing. Move data to a workstation and process it there.
- An esxcli object from
Get-EsxCliis bound to one host. Build a new one inside the loop rather than reusing it.
Official documentation
- ESXCLI Syntax | Broadcom TechDocs
- Using ESXCLI Output | Broadcom TechDocs
- ESXCLI Command Reference | Broadcom Developer Portal
- Get-EsxCli | VMware PowerCLI Reference
Related tools
- PowerCLI Command Builder: assemble the PowerCLI side of these examples without looking up parameter names.
Related guides
- Get-VM inventory reporting in PowerCLI: the vCenter-level inventory report that pairs with these host commands.
- VMware ESXi command line cheat sheet: the lookup list of individual esxcli commands this page teaches the grammar for.
- Rescan storage on an ESXi host: a worked example of running storage commands at the host level.
- Remove a stale datastore in vCenter: what to do when the filesystem list still shows a datastore that is gone.
- Install PowerCLI for vSphere: the prerequisite for the Get-EsxCli examples above.
- Useful ESXi and vCenter folders, tools and logs: where to look next when a command tells you something is wrong.