The commands

Published

All seven carry that label: the Engine's reference lists them and records no validation state for them, so this page claims none beyond their being published. They stay at the top level, outside the groups, because signing in comes before choosing a service. connect was already in earlier releases; the other six arrived in 1.0.0b10, and without login every command still signs in for itself.

CommandWhat the Engine's reference says it does
m365g loginsign in and keep the session for later commands. The only command that keeps one
m365g statuswhich connection later commands will use. Reaches no tenant
m365g connection listevery stored connection. Reaches no tenant
m365g connection usemake a stored connection the active one. Reaches no tenant
m365g connection removeremove a stored session and its record, as logout --name
m365g logoutremove a stored session and its record
m365g connectreach a tenant and say what was established. Collects nothing

login, connect and a logout that has a kept sign-in to clear reach a tenant. status, connection list and connection use read the local record and reach nothing.

Installing it

Published

One package installs both names. Version 1.0.0b10 of m365-governance-as-code installs m365g and m365-governance, and the manual's installation page says how, platform by platform.

PowerShell
pipx install m365-governance-as-code==1.0.0b10
m365g --version

The two names are one command line. Whatever is typed after m365-governance in the manual can be typed after m365g, and the earlier command names behave as they did. The Engine's release notes record what was measured before the release: an installation of the previous version was upgraded, both names were run from outside any checkout, the packaged fixtures, rules and schemas were found, and uninstalling left no command and no package file behind.

The version is pinned because it is a pre-release. Without == an installer does not select a pre-release.

Once it is installed, the order is the one this page follows.

StepCommandReaches a tenant
Register the application the command line signs in throughm365g engine setupOnly with --register, as an administrator
Sign in and keep the sessionm365g loginYes
See which connection later commands will usem365g statusNo
List or choose a kept connectionm365g connection list, m365g connection use NAMENo
End a session, or remove one by namem365g logout, m365g connection remove NAMEOnly to clear a kept sign-in

m365g engine setup is m365g setup under its grouped name, and m365-governance setup under the earlier one. Minimum permissions says what each read then asks for.

Signing in

PowerShell
m365g login --client-id <application id> --tenant-url https://contoso-admin.sharepoint.com

login first prints the report connect prints, with authentication and authorization as two separate answers: a session that opened is not a statement about what the identity may read. It then records the connection and prints it. The identifiers are replaced by placeholders here.

Text
Logged in. Later commands for contoso.sharepoint.com use this connection.
contoso (active)
  tenant      contoso.sharepoint.com  (https://contoso-admin.sharepoint.com)
  directory   <directory id>
  application <application id>
  signs in as delegated, by interactive; who: not reported by the session
  session     kept in the operating system's protected storage
  recorded    2026-11-10T09:10:44Z
  stored in   the macOS Keychain

The line who: not reported by the session is the engine's own. The record holds the kind of identity and the method; no collection path for the person's name is established, so none is written.

Where the sign-in is kept

The token is written by the sign-in library into the operating system's protected storage, and never by the engine: the macOS Keychain, Windows data protection, or the Linux keyring. The engine holds no token, prints none and writes none into evidence.

Where protected storage cannot be established, the login is refused. On Linux the library falls back to an unprotected file when no keyring answers. login refuses to keep a session there, before anybody signs in, and checks what is on disk after the sign-in as well: a token cache it can read is cleared and the login fails.

What the engine records is a description, in connections.json under the user's configuration directory: the connection's name, the tenant address, the directory, the application registration, the sign-in method, the kind of identity the session reported, and when. It refuses to hold a secret. M365G_HOME moves the file.

What is on record

PowerShell
m365g status
Text
contoso (active)
  tenant      contoso.sharepoint.com  (https://contoso-admin.sharepoint.com)
  directory   <directory id>
  application <application id>
  signs in as delegated, by interactive; who: not reported by the session
  session     kept in the operating system's protected storage
  recorded    2026-11-10T09:10:44Z
This is the local record, not a check: `m365g connect` asks the tenant whether the session still signs in and what it may read.

status reads the local record and reaches no tenant, so it says what was recorded at login and not whether the session still works. connect is the command that asks the tenant. With nothing recorded, status prints Logged out: no active connection. and exits 1.

connection list prints the same block for every stored connection. connection use NAME answers in one line:

Text
contoso is the active connection, for contoso.sharepoint.com.

There is one identity per tenant and application registration. A second login for the same pair replaces the first, and says which connection it replaced.

One sign-in, for SharePoint and for Microsoft Graph

The SharePoint collections sign in through PnP.PowerShell and reuse a kept session: every command in the spo group reports Signs in as the active connection (login), or with --client-id in its own help. After one login, m365g spo site list, m365g spo hub list and m365g spo sharing list run without asking again.

The Microsoft Graph reads sign in as the same person, through the same application registration, so the same kept session answers them too. Their help says Signs in as the active connection (login) for the scope above, or with a certificate, or with a token the operator supplies.

That covers m365g entra ca list, m365g entra tenant governance get, m365g entra guest list, m365g entra app list, m365g entra serviceprincipal list and m365g entra group list.

A certificate, or a token placed in the environment, still takes precedence over the kept session when either is given.

A session is used only for its own tenant. A command aimed at another tenant, by an option or a project file, ignores the active connection and says so. For the application registration and the tenant address the order is: an option on the command line, then a project file, then the active connection.

Each Graph read asks for its own scope, and no other

A Microsoft Graph read asks only for the scopes its collector declares. They are the ones recorded beside the collector, and the command reference prints them under Permissions. No wider set is asked for once and kept for convenience, so reading guests does not ask for what reading applications needs.

A scope nobody has consented to is asked for at the sign-in, and it is the person's to grant. The directory shows its own consent prompt there. The engine grants nothing and consents to nothing: no read has a step that accepts a prompt. Whether a given person may accept a given scope is the directory's rule, not the engine's.

Consent can be given for oneself alone. The directory's prompt lets an administrator consent for their own account without consenting on behalf of the organisation, and the engine asks for nothing more than that: no read on these pages needs a grant made for everybody.

The token a sign-in returns is spent at once. It is not written, kept by the engine or placed in an argument.

The reads that sign in for themselves

CommandHow it signs in
m365g entra license listfor itself on every delegated run: a kept session is not reused
m365g exo forwarding getfor itself on every delegated run: a kept session is not reused

The licensing read signs in through the Microsoft Graph PowerShell SDK, whose kept context is shared with everything else an operator does with that SDK. The collector confines its sign-in to its own process, so it neither leaves that context behind nor uses one that was already there. The forwarding read signs in through Exchange Online PowerShell, which keeps no session between processes.

Logging out

PowerShell
m365g logout
Text
contoso: logged out, stored sign-in removed.

A logout that cannot clear the stored sign-in keeps the record and exits 1, so that it is not mistaken for a logout. With nothing to remove it prints Already logged out: no active connection.

The one write the engine makes

m365g engine setup --register registers the application the command line signs in through. It is the only write the engine makes to a tenant. It needs an administrator, who signs in and consents in a browser, and it is made only by setup and only on explicit agreement. No other command on these pages changes anything in a tenant: login opens a session, and every read reads.

A person who is not an administrator runs setup without --register and receives the request an administrator acts on. The manual describes that journey under setup.