Package: meraki-cli
Meraki-CLIA simple CLI tool to automate and control your Cisco Meraki Dashboard!Quick Install:pip3 install meraki-cliUpdate/Upgrade Meraki-CLI:meraki upgrade --upgrade-allQuick Command Cheat Sheet:Meraki-CLI Cheat SheetFull Command Guide:Meraki-CLI Command GuideVERSIONThe version of Meraki-CLI documented here is:1.5.0Version History:Change LogABOUTMeraki-CLI is a wrapper around the officialMeraki Dashboard API Python SDK. It takes all published functions in the library and makes them available to the user as a standard command-line tool with-hhelp options, commands, switches, arguments, and tab autocompletion. It also supports classic Linux-style pipelining, allowing the output of one instance of the program to be piped to the input of another.ExamplesList your associated organizations:meraki organizations getOrganizationsList the Meraki networks within an organization:meraki organizations getOrganizationNetworks --organizationId 123456List the MX VLANs on a network:meraki appliance getNetworkApplianceVlans --networkId N_12345Add a new MX VLAN to a network:meraki appliance createNetworkApplianceVlan --networkId N_12345 --id 100 --name "My New VLAN" --applianceIp "10.0.0.1" --subnet "10.0.0.0/24"CapabilitiesSince the Meraki-CLI tool builds its arguments directly off of Meraki's SDK, it's capabilities exactly match those of the SDK and are updated automatically when Meraki adds new API capabilities. For a list of available commands from the last build of the Meraki-CLI, check out theMeraki-CLI Command Guide.ScreenshotTABLE OF CONTENTSGetting StartedPrepare your OSInstall Meraki-CLIUpgradingGetting and Using your API KeyA Few Starting CommandsMaking Some ChangesTab AutocompletionUsing a Config FileDebugging and LoggingFilteringPipeliningOverriding ValuesTranslationsOutputting CommandsHow the Pipelining WorksAdvanced UsageUsing --kwargsDealing with --kwargs on WindowsContributingGETTING STARTEDPrepare your OSNOTE: If you are installing on Windows 10 and want to use tab autocompletion of commands, you may want to review theWindows 10part of the "Tab Autocompletion" section first to see how to install Meraki-CLI on Windows 10 and be able to use autocompletion.In order to use Meraki-CLI, you need to have Python 3 installed on your OS. If you do not yet have Python 3 installed, visit thisPython 3 Installation Instructions Pageand install for your operating system.Install Meraki-CLIThe easiest (and recommended) way to install Meraki-CLI is to use PIP.You can use PIP to install Meraki-CLI with the commandpip3 install meraki-cliorpython3 -m pip install meraki-cliTo see if Meraki-CLI was successfully installed, run themerakicommand and see if it displays the help menu.UpgradingIf you already have Meraki-CLI installed and want to upgrade to the latest release, run the commandmeraki upgrade --upgrade-allTo see all the upgrade options, view the help page by runningmeraki upgradeIf you are updating from a Meraki-CLI version older than v1.5.0, then usepip3 install --upgrade --no-cache-dir meraki-cliorpython3 -m pip install --upgrade --no-cache-dir meraki-cliGetting and Using your API KeyMeraki-CLI is command-line driven and once installed can be run with the commandmeraki. Once you have installed it, you can see the command guide by running themerakicommand by itself.In order to operate the CLI you need to input your Meraki API key using one of three methods:Saving your API key as an environment variable (recommended):Windows:set MERAKI_DASHBOARD_API_KEY=6bec40cf957de430a6f1f2baa056b99a4fac9ea0MacOS/Linux:export MERAKI_DASHBOARD_API_KEY=6bec40cf957de430a6f1f2baa056b99a4fac9ea0Once saved as an environment variable, you don't need to use the-koption when running commandsSave your API key to a config file. See the "Using a Config File" section for more info on how to do this.Use the-k <api_key>or--apiKey <api_key>argument at the top level of the command likemeraki -k <api_key>You can obtain a Meraki API key by:Logging into the Meraki DashboardClicking your user name in the top right cornerBrowsing toMy profileView the 'API Access' section near the bottom of the pageClick on the 'Generate new API key' button and copy down your new API key before saving. It will be a long hexadecimal string.Note: The API key seen in the examples above is a public one Meraki provides for testing against their sandbox networks. Feel free to use it for testing things out, but sometimes it gets overused and is throttled by Meraki. Meraki also may change it in the future, so use your own if you can. All the output examples shown below use that key.A Few Starting CommandsOnce you have your new key saved, try listing out your organizations with the commandmeraki -k API_KEY_HERE organizations getOrganizations, substituting in your API key. This will print out a formatted table of your organizations. If you saved your API key as an environment variable, you can exclude the-kargument and simply issuemeraki organizations getOrganizations.Take one of your organization ID numbers and look at the networks in it withmeraki organizations getOrganizationNetworks --organizationId 123456You can reformat any of this data into JSON output by adding the-jswitch (before the command) to look something likemeraki -j organizations getOrganizationsIt is important to note that the columns included in a table often do not include all of the data returned from the API. If you need to see all the data returned, then use the-jswitch and allow the tool to print out JSON data.You can also change the table data which is output by filtering and ordering table columns. To do this, use the-cargument and provide a comma-seperated list of columns to display. Example:meraki -c id,name,descriptionTo see any help menu, use the-hoption at any command level:meraki -hor justmerakiwill show you the top level options and argumentsmeraki appliance -hor justmeraki appliancewill show you all the appliance-related commandsmeraki appliance createNetworkApplianceVlan -hor justmeraki appliance createNetworkApplianceVlanwill show you an instruction page with all the arguments and options available for creating a new network appliance VLAN.If you have any Meraki MS switches available, try viewing the port configurations withmeraki switch getDeviceSwitchPorts --serial 1234-ABCD-5678or you can view the operational port stats by usingmeraki switch getDeviceSwitchPortsStatuses --serial 1234-ABCD-5678Making Some ChangesPushing changes into Meraki is done by running the correct command and passing in the necessary arguments.For example, to rename a device, we just run thedevices updateDevicecommand with the proper arguments included:meraki devices updateDevice --serial 1234-ABCD-5678 --name NEW_DEVICE_NAME~$
~$ meraki devices updateDevice --serial Q2HP-F5K5-R88R --name NEW_DEVICE_NAME
┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓
┃ lat              ┃ lng               ┃ address ┃ serial         ┃ mac               ┃ lanIp         ┃ url              ┃ networkId            ┃ name            ┃ model    ┃ switchProfileId ┃ firmware       ┃ floorPlanId ┃
┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩
│ 37.4180951010362 │ -122.098531723022 │         │ Q2HP-F5K5-R88R │ 88:15:44:df:f3:af │ 10.10.10.131  │ https://n149.me… │ L_646829496481105433 │ NEW_DEVICE_NAME │ MS220-8P │ None            │ switch-11-31   │ None        │
└──────────────────┴───────────────────┴─────────┴────────────────┴───────────────────┴───────────────┴──────────────────┴──────────────────────┴─────────────────┴──────────┴─────────────────┴────────────────┴─────────────┘
~$
~$Or if we want to change the VLAN ID and name of a MS switch port, we can use:meraki switch updateDeviceSwitchPort --serial 1234-ABCD-5678 --portId 1 --vlan 100 --name "Data Port"If the change succeeds, you will often see the newly updated item echoed back like this:~$
~$ meraki switch updateDeviceSwitchPort --serial Q2HP-F5K5-R88R --portId 1 --vlan 100 --name "Data Port"
┏━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━┳━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ portId ┃ name      ┃ enabled ┃ poeEnabled ┃ type  ┃ vlan ┃ voiceVlan ┃ allowedVlans ┃ isolationEnabled ┃ rstpEnabled ┃ stpGuard ┃ linkNegotiation ┃ portScheduleId ┃ udld       ┃
┡━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━╇━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ 1      │ Data Port │ True    │ True       │ trunk │ 100  │ None      │ all          │ False            │ True        │ disabled │ Auto negotiate  │ None           │ Alert only │
└────────┴───────────┴─────────┴────────────┴───────┴──────┴───────────┴──────────────┴──────────────────┴─────────────┴──────────┴─────────────────┴────────────────┴────────────┘
~$
~$Many commands which make changes to the dashboard (likeupdateDeviceSwitchPortabove) have optional arguments (like--vlanand--name) which are used to send those changes. See the below help page for theupdateDeviceSwitchPortcommand:~$
~$ meraki switch updateDeviceSwitchPort -h
usage: meraki-cli.py switch updateDeviceSwitchPort [-h] --serial STRING --portId STRING [--kwargs JSON_STRING]

UPDATE A SWITCH PORT

https://developer.cisco.com/meraki/api-v1/#!update-device-switch-port

All Arguments:
  --serial (string): (required)
  --portId (string): (required)
  --name (string): The name of the switch port
  --tags (array): The list of tags of the switch port
  --enabled (boolean): The status of the switch port
  --type (string): The type of the switch port ('trunk' or 'access')
  --vlan (integer): The VLAN of the switch port. A null value will clear the value set for trunk ports.
  --voiceVlan (integer): The voice VLAN of the switch port. Only applicable to access ports.
  --allowedVlans (string): The VLANs allowed on the switch port. Only applicable to trunk ports.
  --poeEnabled (boolean): The PoE status of the switch port
  --isolationEnabled (boolean): The isolation status of the switch port
  --rstpEnabled (boolean): The rapid spanning tree protocol status
  --stpGuard (string): The state of the STP guard ('disabled', 'root guard', 'bpdu guard' or 'loop guard')
  --linkNegotiation (string): The link speed for the switch port
  --portScheduleId (string): The ID of the port schedule. A value of null will clear the port schedule.
  --udld (string): The action to take when Unidirectional Link is detected (Alert only, Enforce). Default configuration is Alert only.
  --accessPolicyType (string): The type of the access policy of the switch port. Only applicable to access ports. Can be one of 'Open', 'Custom access policy', 'MAC allow list' or 'Sticky MAC allow list'
  --accessPolicyNumber (integer): The number of a custom access policy to configure on the switch port. Only applicable when 'accessPolicyType' is 'Custom access policy'
  --macAllowList (array): Only devices with MAC addresses specified in this list will have access to this port. Up to 20 MAC addresses can be defined. Only applicable when 'accessPolicyType' is 'MAC allow list'
  --stickyMacAllowList (array): The initial list of MAC addresses for sticky Mac allow list. Only applicable when 'accessPolicyType' is 'Sticky MAC allow list'
  --stickyMacAllowListLimit (integer): The maximum number of MAC addresses for sticky MAC allow list. Only applicable when 'accessPolicyType' is 'Sticky MAC allow list'
  --stormControlEnabled (boolean): The storm control status of the switch port
  --flexibleStackingEnabled (boolean): For supported switches (e.g. MS420/MS425), whether or not the port has flexible stacking enabled.

Function Signature:
  >>> def updateDeviceSwitchPort(serial: str, portId: str, **kwargs):

Required Arguments:
  --serial STRING       (required)
  --portId STRING       (required)

Misc Arguments:
  -h, --help            Show help for this command
  --kwargs JSON_STRING  (Advanced Users) Optional arguments in JSON format
~$
~$For theupdateDeviceSwitchPortcommand, you can see from the help page above that there are two required arguments:--serialand--portId. There are also many optional arguments like--name,--tags,--enabled,--vlan, etc. Each of the arguments has its value type listed in the help page.Simple value types like string, integer, and boolean are pretty straightforward. The can be provided like:--name "Some Descriptive Name"(string)--vlan 100(integer)--enabled true(boolean)Sometimes it is necessary to provide more complex values in certain arguments. An example from theupdateDeviceSwitchPortcommand is the--tagsargument. The--tagsargument requires a list (array) of items. You can provide this list of items at the CLI using JSON formatting.This will look like--tags '["tag1", "tag2"]'on a Unix shell or--tags "[""tag1"", ""tag2""]"on Windows. This formatting provides a JSON-parsable structure to the CLI tool which is turned into native data and sent over the API to the dashboard. If you want to dive deeper into how to provide JSON data at the CLI, check out theUsing --kwargsandDealing with --kwargs on Windowssections.Note: Advanced users can use the--kwargsoption to input all optional parameters as raw JSON data. Check out theUsing --kwargssection for information on how to do that.Tab AutocompletionMeraki-CLI v1.4.0 introduces tab autocompletion support on MacOS (zsh) and Linux (bash), and Windows 10 WSL using the Pythonargcompleteframework. Once you have installed Meraki-CLI, there are a few additional steps you need to take to enable autocompletion. See below for these steps.Once tab autocompletion is functional, you will be able to hit the TAB key at any point in the command to see your options and/or complete a partial command. You are also able to set the-hswitch at any point in the command and hit ENTER to see the help page for that specific command.MacOSIf you are using the terminal on a modern version of MacOS, you are probably using zsh ("z shell") instead of bash, which is the standard for Linux distros. Use one of the two below options to enable autocompletion for your terminal:Option 1 (Easy)Run the commandcurl -fs https://raw.githubusercontent.com/PackeTsar/meraki-cli/master/.zprofile >> ~/.zprofileto populate your zsh profile with the proper commandsExit your terminal application and re-open itTypemerakiat the prompt and then hit the TAB keyYou now should see all the arguments/switches/commands available to youOption 2 (Manual)Open your zsh profile file withnano ~/.zprofileAdd the below text to the bottom of the file# Tab Autocompletion for Meraki-CLI tool
autoload bashcompinit
bashcompinit
autoload compinit
compinit -u
eval "$(register-python-argcomplete meraki)"
# End of Meraki-CLI commandsOnce the text is added, pressCTRL-X, hit the 'y' key, and hitENTERto save the changes to the fileExit your terminal application and re-open itTypemerakiat the prompt and then hit the TAB keyYou now should see all the arguments/switches/commands available to youLinuxAt your CLI terminal, run the commandactivate-global-python-argcompleteIf you are using a Redhad distro like CentOS, also run the commandecho 'eval "$(register-python-argcomplete meraki)"' >> ~/.bash_profileExit the terminal session and restart it (log out and back in if on SSH)Typemerakiat the prompt and then hit the TAB keyYou now should see all the arguments/switches/commands available to youWindows (10)A native installation of Meraki-CLI on Windows (where you use the Windows Command Prompt for themerakicommands) does not support tab autocompletion. There is, however, a workaround to this. If you're using a modern version ofWindows 10, you can install theWindows Subsystem for Linux(WSL) on your Windows 10 OS and then install Meraki-CLI on the WSL which will support tab autocompletion. This WSL installation is a native Windows feature and the process below should take you about 10 minutes.NOTE: Running WSL version 2 (which is now the default) requires virtualization features to be enabled in your PC's BIOS settings. The settings may be called VT-x, AMD-V, or SVM.Open a Powershell window on your Windows 10 OSas administrator(right-click and then click "Run as administrator")Run the commandwsl --installAfter installation you will be prompted to restart your OS, restart itOnce logged back in, you will see a window pop up saying it is installingOnce installation finishes, it will ask you for a user name and password. Go through these prompts to set up WSLAfter setting it up, you will have a command prompt with something likeuser@MYWIN10PC:~$. Now we will perform a Linux Meraki-CLI installationRunsudo apt updateto pull the latest repository infoRunsudo apt install python3-pipto install the PIP Python package managerRunsudo pip3 install meraki-clito install the Meraki-CLI toolNOTE: We are running this as sudo on purpose. The autocomplete feature must be installed and activated at the global levelOnce installation finishes, run themerakicommand and make sure you see the help outputExit the command window withexitReopen the WSL command window by finding the "Ubuntu" app in your start menuRun the commandsudo activate-global-python-argcompleteto activate the tab autocompletion featureProvide your WSL password when promptedYou should just see the response "Installing bash completion script /etc/bash_completion.d/python-argcomplete"Exit the command window withexitonce againTypemerakiat the prompt and then hit the TAB keyYou now should see all the arguments/switches/commands available to youWSL Meraki-CLI Config FileIf you want to set up a config-file to store your Meraki dashboard API key, you will need to use the Linux file path by:Creating the config file directory withsudo mkdir /etc/meraki-cliCreate the config file by opening the nano text editor withsudo nano /etc/meraki-cli/meraki-cli.confDrop in and modify the example config file text from theUsing a Config FilesectionUsing a Config FileIf you find yourself regularly entering the same arguments into the Meraki-CLI tool like your API key, debug level, logfile, etc, it might make sense to save those settings to a static config file in a permanent location.The Meraki-CLI tool supports the use of a config file to provide any of its arguments. The config file should contain proper JSON syntax and should be a simple JS object (Python dictionary) in format. An example is shown below. If you want to use the arguments of a currently working command, set a maximum debug level of-dddand copy/paste the JSON output under the "Argument Settings" log statement.The config file can be obtained by the program by either explicitly defining its location using the-coption like-c ~/meraki-cli.conf, or by placing the file in a location searched by Meraki-CLI upon program start. The search locations are provided below and are sorted by common OS usage.Windows OS%APPDATA%\meraki-cli\meraki-cli.confThe%APPDATA%is usually equal toC:\Users\<username>\AppData\Roamingby defaultAssuming the default, the config file location would be:C:\Users\<username>\AppData\Roaming\meraki-cli\meraki-cli.conf%LOCALAPPDATA%\meraki-cli\meraki-cli.confThe%LOCALAPPDATA%is usually equal toC:\Users\<username>\AppData\Localby defaultAssuming the default, the config file location would be:C:\Users\<username>\AppData\Local\meraki-cli\meraki-cli.confMacOS~/.meraki-cli/meraki-cli.confThe~directory is your local user directory. It is usually equal to/Users/<username>/by defaultAssuming the default, the config file location would be:/Users/<username>/.meraki-cli/meraki-cli.confNote that the directory name has a leading dot, making it a hidden directory~/Library/Application Support/meraki-cli/meraki-cli.confThe~directory is your local user directory. It is usually equal to/Users/<username>/by defaultAssuming the default, the config file location would be:/Users/<username>/Library/Application Support/meraki-cli/meraki-cli.confLinux/etc/meraki-cli/meraki-cli.confNote: Any of the above locations except/etc/meraki-cli/meraki-cli.confwill work on any platform. TheAPPDATAandLOCALAPPDATAenvironment variables exist on Windows by default, but can be added to any machine. The two~(home) locations will resolve on both Windows or MacOS/Linux to a subdirectory inside the user's home directory.Examplemeraki-cli.confConfig File{
    "apiKey": "6bec40cf957de430a6f1f2baa056b99a4fac9ea0",
    "debug": 1,
    "logfile": "meraki.log"
}Debugging and LoggingIf you are having trouble figuring out why something is not working, you can set the debugging level to one of four levels:Level 0 (default): Only warnings and errors will be displayed or loggedLevel 1 (-d): General status and program progress will be reportedLevel 2 (-dd): General program progress as well as Meraki API library debugging will be reportedLevel 3 (-ddd): Program progress, Meraki API library debugging, and full data dumps will be reportedIf you want to stow those logs away, you can define a log file using something like-l logs.txt. Only logs printed to the screen will be written to the file, so you also need to set a debugging level if you want to see anything other than just warnings and errors.FilteringWhen multiple items are returned from your command, you can filter them by providing a column name (key) and a regular expression to use to match the item's columns value.For example, you can view only enabled switch ports on a switch with:meraki -f "enabled:True" switch getDeviceSwitchPortsStatuses --serial 1234-ABCD-5678The filter (-f) argument is reusable and you can use it multiple times to match based on more than one column. By default the filter uses "OR" logic when dealing with multiple filters. For example, the below command will show any enabled ports and any ports in VLAN 1000.meraki -f "enabled:True" -f "vlan:1000" switch getDeviceSwitchPorts --serial 1234-ABCD-5678If you want to combine those filters so displayed items have to match both of them. Pass in the-aswitch to change the filter logic to "AND" like:meraki -f "enabled:True" -f "vlan:1000" -a switch getDeviceSwitchPorts --serial 1234-ABCD-5678PipeliningBeing able to manipulate the Meraki dashboard from the CLI can be quite useful, but its power grows exponentially when you are able to use pipelining. Pipelining allows you to pass the Meraki objects returned in one command into another and do something with them.Note: When using pipelining, you will likely want to save your API key as an environment variable since it will need to be available to each instance of the program. Otherwise you would have to insert it multiple times likemeraki -k abcd1234 <commands> | meraki -k abcd1234 <commands>.A simple example of this is to display the switch port statuses of the ports on all switches in a network. To do this use:meraki networks getNetworkDevices --networkId N_12345 | meraki switch getDeviceSwitchPortsThe above command can be interpreted the following way:The first command (before the pipe) is retrieving and returning all network device objects in a network. Each device object will have aserialnumber attribute with it.The pipe between the commands is sending the output of the first command into the input of the second.The second command is taking each object in its input and retrieving that object's switch ports. Since the only argument required by thegetDeviceSwitchPortscommand is--serial, and theserialattribute is contained in each object coming from the first command, the second is able to use that information to loop through the input objects and execute the command on them.This functionality should be recognizable to anybody familiar with common pipelining in Linux or PowerShell.If you, for example, wanted to filter the output of the first command to only output MS250 model switches, you can use a filter in it like:meraki -f 'model:MS250' networks getNetworkDevices --networkId N_12345 | meraki switch getDeviceSwitchPortsOverriding ValuesSometimes you want to use the output of one command to feed another, but you want to change something in the data before submitting it in that second command. You can do this by simply providing the changed argument in the command line of the second argument. For example:meraki appliance getNetworkApplianceVlans --networkId N_11111 | meraki appliance createNetworkApplianceVlan --networkId N_22222Here you are taking all of the configured appliance VLANs in network N_11111 and are pushing them into thecreateNetworkApplianceVlanto create new appliance VLANs. But first you are overriding the--networkIdattribute of those VLAN objects so they are applied to a different network. You are effectively copying all appliance VLANs from one network to another.TranslationsAt times the attribute names of objects output from one command do not exactly match the required input names of another, even though the actual data is the same. For example: the output of thegetNetworkApplianceVlanscommand assigns VLAN ID numbers to the attribute nameid, however thedeleteNetworkApplianceVlancommand requires the argument namevlanId. To deal with this we have to provide a translation using the-targument. If you wanted to delete all the appliance VLANs configured on a networkNOT ADVISABLE, you would need to provide a translation on the second instance like:meraki appliance getNetworkApplianceVlans --networkId N_12345 | meraki -t "vlanId=id" appliance deleteNetworkApplianceVlanThe-t "vlanId=id"argument is effectively telling the receiving program to use theidattributes of its input to fill thevlanIdargument required by thedeleteNetworkApplianceVlancommand.Outputting CommandsIf you want to test out the power of pipelining, but don't necessarily want to have the commands executed automatically (in case you did something wrong), you can use the-oswitch to output templatized commands instead. Using the-oswitch in the receiving command will prevent actual execution, and instead will structure and display commands which will perform that execution; complete with arguments and values. The above command can be safely tested using the below:meraki appliance getNetworkApplianceVlans --networkId N_12345 | meraki -o -t "vlanId=id" appliance deleteNetworkApplianceVlanHow the Pipelining WorksThe pipelining feature of the Meraki-CLI utility works by writing standard JSON data out to STDIN; the same data you see if you use the-jswitch. All log messages are written to STDERR to prevent interference.When the program starts, it checks for a leading pipe (ie:| meraki ...): the existence of which would indicate that it needs to process STDIN data, which it then does.When the program processes results to be printed to the screen, it checks for a trailing pipe (ie:meraki ... |): the existence of which would indicate that its output will feed another program instance. When this is detected it automatically switches to JSON output and writes it to STDOUT.ADVANCED USAGEUsing --kwargsSome Meraki-CLI commands require arguments to be provided which are not explicitly defined in the underlying function, but are documented in the command help page. An example of this is theupdateDeviceSwitchPortcommand. You can see an example of this command's help page in theMaking Some Changessection.In the command help page you will see many argument options under the "All Arguments" section, but only two of them are listed in the "Required Arguments" section:serialandportId. Some of the other arguments in the documentation are things likename,tags,enabled, etc.When arguments are not listed in the "Required Arguments" or "Misc Arguments" sections of the command help page, they are considered to be Optional Arguments.Optional Arguments can be provided in one of two ways:Using regular CLI arguments like--name "Test Name"and--vlan 100Nested as JSON data inside the--kwargsargument like--kwargs '{"name": "Test Name", "vlan": "100"}'On Windows CLI, you have to use double-double quotes inside the data like--kwargs "{""name"": ""Test Name"", ""vlan"": ""100""}"When Optional Arguments are provided at the command-line (in either of the two ways), they are parsed into native data types and are included as**kwargsto the underlying target method when it is called.Some arguments cannot be simple data types, for example the--tagsargument from theupdateDeviceSwitchPortcommand. The--tagsargument must be an array, not a simple string or integer. Again there are two ways you can provide this value:Use the--tagsoption and provide a JSON-parsable array like:--tags '["first_tag", "second_tag"]'Use the--kwargsoption to provide the nested JSON data like--kwargs '{"tags": ["first_tag", "second_tag"]}'Both of these options will result in the same data being sent to the underlying target method.Dealing with --kwargs on WindowsThe--kwargsdata passed into Meraki-CLI is a JSON string and the JSON standard requires double-quotes in the data for quoting, it does not allow single-quotes. This becomes challenging on a standard Windows command prompt because Windows usually wants double-quotes used to encapsulate a string on the CLI.. So how do you use double quotes in the data and to encapsulate it?To do this, use regular double-quotes in front of and behind the string to encapsulate it, and you use double-double-quotes in the actual data. That means replacing all uses of a double-quote characters in the data with two double-quotes. Your argument ends up looking like this:--kwargs "{""name"": ""Data Port"", ""vlan"": ""100""}". It is probably easiest to use find/replace in a text editor to do this for you.You can also structure the JSON data and your command a bit if you want to make your command more readable. In Windows, you can do this by ending each line with a carat (^) which will allow the command to continue on the next line. Your command in this example will look like:meraki switch updateDeviceSwitchPort --serial 1234-ABCD-5678 --portId 24 --kwargs ^
"{ ^
    ""name"": ""Data Port"", ^
    ""vlan"": ""100"", ^
}"CONTRIBUTINGThis project is very new and has been created out of need. If you have a feature you would like to see built into it, please open up an issue in Github and describe your desired feature. Any accepted feature requests will be listed in theEnhancement Requests and Known Bugsissue page.If you find a need for a feature and you add it in yourself, or you fix a bug you found, please feel free to open up a merge request!