Get started
Install
Section titled “Install”Requires Python 3.11+. pipx gives xdr its own isolated environment and
puts the command on your PATH, which matters when an agent spawns it as a
subprocess.
Linux / macOS
Section titled “Linux / macOS”pipx install "git+https://github.com/NerfBlasters/m365-xdr-cli.git"xdr --versionWindows (PowerShell)
Section titled “Windows (PowerShell)”python -m pip install --user pipxpython -m pipx ensurepath# refresh PATH in this session so pipx and xdr are visible without reopening$env:Path = [Environment]::GetEnvironmentVariable("Path","User") + ";" + [Environment]::GetEnvironmentVariable("Path","Machine")
pipx install "git+https://github.com/NerfBlasters/m365-xdr-cli.git"xdr --versionUpdating
Section titled “Updating”pipx upgrade xdr-cli # or: pipx reinstall xdr-cliDevelopers: see Development for an editable install.
Shell completion
Section titled “Shell completion”xdr uses Click’s shell completion. To enable it for the current Bash session:
eval "$(_XDR_COMPLETE=bash_source xdr)"For Zsh use eval "$(_XDR_COMPLETE=zsh_source xdr)"; for Fish use
_XDR_COMPLETE=fish_source xdr | source. To avoid generating the script on
every shell startup, save that shell’s generated output and source the saved
file from your shell configuration. PowerShell users can generate its script
with $env:_XDR_COMPLETE = 'powershell_source'; xdr, then clear the variable
with Remove-Item Env:_XDR_COMPLETE and load the saved script.
The former --install-completion and --show-completion options were removed
in 0.15.0. Help now uses plain Click formatting; command examples and parameter
help remain available through --help.
Two ways to sign in
Section titled “Two ways to sign in”| Portal cookie (quick start) | Entra app registration | |
|---|---|---|
| Setup | Minutes: copy one request from your browser’s DevTools | Register an app, add permissions, get admin consent |
| Talks to | The Defender portal’s own apiproxy interface — undocumented and unsupported by Microsoft; can break without notice | Microsoft Graph security and Defender for Endpoint APIs — documented and supported |
| Credential | Your browser session cookie: a bearer credential for you, subject to the same expiry, Conditional Access and sign-in-frequency rules as the portal. Renewal is manual (re-import). | MSAL tokens with refresh; or a service principal for automation |
| Covers | Hunting, incidents, alerts, investigate, domains, device show/timeline/action-status, every response action, package download | Everything except package download and the AD domain inventory |
| Permissions | Whatever your user already has in the portal (Defender RBAC applies) | Delegated permissions you grant, plus the user’s Defender roles |
Start with the portal cookie if you want to try the tool today. Set up the app
registration when you need a supported path, CI/automation, or a team-wide
credential. Both can coexist; xdr picks the official backend when its
credentials are present and the cookie otherwise (--backend overrides).
Details, limits and error codes: docs/portal_cookie.md.
Quick start (portal cookie)
Section titled “Quick start (portal cookie)”-
Tell
xdrwhich tenant you are in. Create~/.xdr-cli/config.toml(or add the line to an existing one). The Directory (tenant) ID is on the Entra admin center’s Overview page, and in Defender portal URLs astid=.tenant_id = "<TENANT_ID>" -
Capture your session, import it, and start investigating:
# 2. Capture your portal session (tested with Microsoft Edge):# - sign in to https://security.microsoft.com and open any device's# Timeline tab# - open DevTools (F12) > Network, filter for "apiproxy"# - right-click the timeline request > Copy > "Copy as cURL (bash)"# - save the clipboard to a file, e.g. ~/mde-curl.txtxdr auth portal-cookie ~/mde-curl.txt # stores the cookie (0600) and # shreds the source filexdr auth status # backend: portal-cookie
# 3. Look around.xdr incidents list --since 7d --severity highxdr incidents show <ID> --expand alerts # <ID> is .id from the list
# 4. Investigate one incident end to end.xdr investigate --auto-enrich <ID>
# 5. Hunt.xdr hunt run "DeviceProcessEvents | where Timestamp > ago(1d) | where FileName == 'powershell.exe' | take 10"xdr library list --search kerberosxdr library run qry_process_tree --param device_name=WS-01Optional: xdr lists init copies the reference-list templates the hunting
library reads (internal subnets, known-good signers, tenant domains, …) into
~/.xdr-cli/lists/. Generic lists ship with defaults; tenant-specific ones
such as TenantDomains start empty. Not needed for incidents or
investigate.
When a command answers with exit 2 in cookie mode, the session has expired:
capture and import a fresh cookie. xdr auth logout deletes the local cookie
only; it does not sign you out of the portal.
Global flags go before the subcommand: xdr --quiet incidents list,
xdr --no-interactive investigate 42, xdr --backend official hunt run ….