CLI tool
pnp/cli-microsoft365 avatar
pnp/cli-microsoft365

CLI for Microsoft 365: installation and first tenant command

Manage Microsoft 365 and SharePoint Framework projects on any platform

1,467 stars414 forksTypeScriptMIT

At a glance

What is it?
CLI for Microsoft 365 provides a cross-platform command-line interface for Microsoft 365 workloads and SharePoint Framework projects. It suits terminal users who need scriptable SharePoint, Entra ID, Teams, and Power Platform operations, but it requires an Entra application registration and suitable tenant permissions.
Who is it for?
Adopt CLI for Microsoft 365 when repeated Microsoft 365 administration and SharePoint Framework maintenance need a scriptable, cross-platform command interface. Do not choose it if you require an interactive GUI or want to avoid managing an Entra application registration.
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 3 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

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

Editorial analysis

Why CLI for Microsoft 365 targets terminal administration

CLI for Microsoft 365 solves two related problems: administering a Microsoft 365 tenant from a terminal and maintaining SharePoint Framework projects. Its documented workload coverage includes SharePoint Online, Microsoft Entra ID, Microsoft Teams, Planner, Power Apps, Power Automate, Purview, OneDrive, Outlook, and several other Microsoft 365 services. That makes it relevant to administrators, developers, and automation authors who would otherwise switch among service-specific interfaces.

The project presents one login path for multiple Microsoft 365 workloads. It supports Linux, macOS, and Windows, with documented use from Azure Cloud Shell, bash, cmder, PowerShell, and zsh. Its authentication choices include Device Code, certificate, client secret, federated identity, username and password, and Azure Managed Identity. The selection matters for automation: Device Code is the documented first-login path, while certificate, client secret, and Managed Identity address different deployment conditions.

This is not a general-purpose Microsoft 365 administration console in GUI form. It is a command-oriented tool whose value comes from composable commands, JSON or text output, and JMESPath filtering. The SharePoint Framework side is narrower. The README specifically identifies project upgrades and environment compatibility checks, so SPFx users should not mistake this for a full project generator.

The package exposes the `m365` executable through `package.json`, along with `m365_comp`, `m365_chili`, and `microsoft365`. It is written in TypeScript and distributed as the ES module `@pnp/cli-microsoft365`. Based on the repository layout, the published entry point is built into `dist/index.js`, while the public API and TypeScript declarations are emitted under `dist/`.

How CLI commands turn tenant operations into filtered output

A typical operation follows a command structure consisting of a service prefix, a command group, an action, global options, and command-specific options. The README uses `m365 spo site get` and `m365 spo site list` as concrete SharePoint examples. Commands return responses that can be emitted as JSON or converted to text with the global `--output` option.

The JSON path suits scripts because each response can be filtered with the global `--query` option using JMESPath. In the documented SharePoint list example, a JMESPath expression selects sites whose `Template` equals `GROUP#0`, then returns objects containing only `Title` and `Url`. This avoids requiring a separate JSON processing utility for common extraction and filtering operations.

Text output serves interactive inspection instead. Adding `--output text` changes the presentation of the response from a structure intended for parsing into a human-readable form. Help is available at both levels. `m365 --help` lists commands globally, while `m365 spo site get --help` presents information and examples for one specific command.

The repository is an ES module, and its build script compiles TypeScript before generating command files and copying additional files into `dist`. This indicates that command registration and generated artifacts are part of the built CLI, not only documentation concerns. The README does not expose the internal service client implementation, request retry policy, credential storage format, or command initialization sequence, so those details cannot be inferred from the examples.

Install @pnp/cli-microsoft365 and authenticate with Entra

Install Node.js first. The README says the CLI has been tested with Node.js versions 20 and higher and recommends the Node.js LTS version available at the time. For normal package installation, use npm's global installation command below. After it finishes, the package should be available through the `m365` executable.

bash
npm install -g @pnp/cli-microsoft365

Before logging in, create a custom Microsoft Entra application registration. The README points to `m365 setup` for this purpose, although the displayed example does not include its arguments or describe each setup choice. Complete that setup before continuing because the next command expects the configured identity.

Start the documented Device Code flow with:

bash
m365 login

The command should initiate authentication against the Microsoft 365 tenant. Because Device Code login involves completing an authentication interaction outside the terminal, the user should follow the displayed instructions. The README points to the `login` command documentation for alternative authentication methods, but it does not claim that `m365 login` alone represents every supported mode.

Two installation paths target different needs. `npm install -g @pnp/cli-microsoft365@next` installs the beta package identified in the README, while `npx @pnp/cli-microsoft365` invokes the package through npm without documenting a global installation. Neither command should be substituted for the stable install when reproducible package selection is the priority.

Run a first SharePoint site read and inspect its output

After authentication, the clearest first use is a SharePoint site read. Replace the documented `contoso.sharepoint.com` tenant URL only when your environment uses a different tenant. The command requests JSON, which is the most useful default for confirming that authentication, application permissions, and command routing work together.

bash
m365 spo site get --url https://contoso.sharepoint.com

For immediate terminal output, request text instead:

bash
m365 spo site get --url https://contoso.sharepoint.com --output text

For a first scripted listing, the README supplies this query:

bash
m365 spo site list --query '[?Template==`GROUP#0`].{Title:Title, Url:Url}'

The expected command family is visible, but the README does not state the exact output payload for a particular tenant. That matters during verification. Success should be judged from the returned site object or selected `Title` and `Url` fields, not from an assumed generic message.

Command help is the safest way to inspect an operation before inserting it into automation:

bash
m365 spo site get --help

The README does not document a rollback command for a site read, so this first use should remain read-only. Avoid adding create, remove, or upgrade operations until command help, required permissions, and tenant impact have been checked.

Cross-platform execution and the Docker-specific environment

The npm package supports normal local installation, but the repository also provides a Docker image for environments where dependency isolation is useful. The documented invocation removes the container after exit and allocates an interactive terminal.

bash
docker run --rm -it m365pnp/cli-microsoft365:latest

The `Dockerfile` adds Node.js and npm to an Alpine-based PowerShell image, installs `@pnp/cli-microsoft365` globally, configures shell completion, and defines `CLIMICROSOFT365_ENV="docker"`. It also creates a non-root user named `cli-microsoft365`. Based on that file, a persistent container workflow would require additional volume or authentication considerations, but the repository excerpt does not prescribe one.

This packaging is materially different from the global npm installation. Docker isolates the CLI and its dependencies inside the container, while global npm installation places the command in the host Node.js environment. Neither approach removes the Entra identity requirement. The container sets an environment marker, but the README does not explain every behavior controlled by that marker.

For contributors, the repository documents a separate local build path. It requires Node.js `>= 24.0.0`, which differs from the Node.js 20-and-higher statement for using the published CLI. The build sequence clones the repository, installs dependencies, compiles it, and links the local executable.

bash
git clone https://github.com/pnp/cli-microsoft365
cd cli-microsoft365
npm install
npm run build
npm link

After `npm link`, terminal `m365` commands use the local clone according to the README. This is development setup, not the recommended installation route for ordinary users.

Permissions, maintenance costs, and boundaries of CLI for Microsoft 365

The central operational constraint is Microsoft Entra identity configuration. The README requires a custom application registration before login. It does not enumerate the application permissions needed by each command, so a successful installation does not prove that the application can read sites, modify teams, access Planner, or call Power Platform APIs.

There is a meaningful difference between consumer use and contributor use. A tenant administrator can install the published package and use documented commands. A contributor must clone the TypeScript repository, provide Node.js `>= 24.0.0`, install project dependencies through `npm install`, compile the project, and link it locally. Upgrades can therefore affect both the globally installed package and any separately linked development build.

The repository uses the MIT license. Its `package.json` identifies version `12.0.0`, the npm package `@pnp/cli-microsoft365`, and a set of executables. The repository has no GitHub releases, so version discovery cannot be based on a GitHub release list. The package registry and project documentation remain the relevant sources.

The last push was on 2026-10-13, and the repository is not archived. The README also states that users can follow the project's Bluesky or X accounts for feature, improvement, and bug-fix updates. The beta package under `@next` adds another upgrade decision: stable users should not install it merely to follow repository changes.

A direct Microsoft Graph approach is the main practical alternative, but the README does not provide a detailed feature-by-feature comparison. The visible distinction is architectural. CLI for Microsoft 365 supplies workload-oriented commands, unified login, output modes, and JMESPath filtering; direct Graph use would require constructing HTTP requests and processing responses outside those command abstractions. The repository identifies Microsoft Graph in its package keywords, but it does not provide enough API implementation detail to claim feature parity.

Editorial conclusion

Adopt CLI for Microsoft 365 when repeated Microsoft 365 administration and SharePoint Framework maintenance need a scriptable, cross-platform command interface. Do not choose it if you require an interactive GUI or want to avoid managing an Entra application registration. Before adoption, verify the supported Node.js version, permissions assigned to the custom Entra application, and command-specific access in the target tenant. The first practical acceptance check should be successful authentication followed by the exact read-only SharePoint site command required by your environment.

Frequently asked questions

How do I install CLI for Microsoft 365?

Install Node.js first, then run `npm install -g @pnp/cli-microsoft365`. The README says the CLI has been tested with Node.js versions 20 and higher and recommends the current Node.js LTS version.

What must I configure before running m365 login?

Create a custom Microsoft Entra application registration before logging in. The README points to the `m365 setup` command or its guide to using your own Microsoft Entra identity.

How do I filter CLI for Microsoft 365 output?

Use the global `--query` option with a JMESPath expression. The README demonstrates filtering a site list and returning objects containing `Title` and `Url`.

Does CLI for Microsoft 365 support Windows and Linux?

Yes. The README lists Linux, macOS, and Windows, along with shell support for Azure Cloud Shell, bash, cmder, PowerShell, and zsh.

Official sources

  1. Issues
  2. License: MIT
  3. pnp/cli-microsoft365 on GitHub
  4. Project website
  5. README
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/pnp-cli-microsoft365.svg)](https://hysenlabs.com/projects/pnp-cli-microsoft365)

Was this useful?