Skip to content

CLI options

Options are specified via command arguments, or within a doctor.json file (automatically gets created on initialization doctor init). Check the commands section for the commands these options can be passed to.

doctor authenticates with the certificate of your own Entra app registration. The --appId, --tenant, and --certificate options are required for every command which talks to SharePoint, and can be defined in the doctor.json file so you do not need to repeat them.

-a, --auth <auth> : The authentication type to use. certificate is the only supported value, and it is the default.

--appId <appId> : The ID of the Entra app registration to authenticate with. Required.

--tenant <tenant> : The ID of the tenant to authenticate to. Required.

--certificate <certificate> : The certificate to authenticate with. Required. This can be the path to your certificate file (.pfx, .p12, or .pem), relative to the folder from where you run doctor, or the base64 encoded contents of that file.

Terminal window
# Path to the certificate file
doctor publish --certificate ./cert.pfx --appId <appId> --tenant <tenant> --url <url>
# Base64 encoded certificate
doctor publish --certificate <base64String> --appId <appId> --tenant <tenant> --url <url>

--password <password> : The password of your certificate file, when you protected it with one.

It can also come from the DOCTOR_CERTIFICATE_PASSWORD environment variable, which is the better place for it when you run doctor yourself: a value passed as --password is printed by the terminal that runs it and sits in the process list for the whole run, where any user on the machine can read it. The order is --password, then password in doctor.json, then the environment variable.

Terminal window
DOCTOR_CERTIFICATE_PASSWORD='…' doctor publish

When none of them has a password and the certificate needs one, doctor asks for it in the terminal, with the input shown as dots. It checks the password against the certificate before signing in, and asks again from an empty field when it does not fit — three tries. Nothing is asked when the certificate has no password, and without a terminal to ask in — a CI/CD pipeline, or --output json — doctor stops with a message saying the password is missing instead.

Before v2.0.0, doctor could also authenticate with the deviceCode and password authentication types. Both are removed:

  • The password type is no longer supported by the CLI for Microsoft 365.
  • The deviceCode type signs you in as a user, which does not work for all the APIs doctor calls during a publishing run.

Certificate authentication uses application permissions, which work for every API doctor needs, and it is the only type which works unattended in a CI/CD pipeline. If you used one of the removed types, follow the certificate authentication guide to set up an app registration.

-u, --url <url> : The URL of the site collection to use.

--library <library> : The library in SharePoint where doctor keeps your referenced images, the site logo, the rendered Mermaid diagrams and the publish state. Check library for where each of them goes.

-f, --folder <folder> : The folder location in where you will create your markdown files.

--webPartTitle <webPartTitle> : The title doctor gives the Markdown web part it puts on each page, which is how it recognises that web part on a page it has no recorded ids for. Default value is: doctor-placeholder. Pick it once — check webPartTitle for why.

--overwriteImages : Uploads every image referenced in the markdown files again, replacing the file in the SharePoint library. Without it, only images which are new or changed since the last publish are uploaded.

--debug : Provides more information of what is happening during command execution. You can also enable this by setting the DEBUG=true environment variable, which is useful in CI/CD pipelines.

--verbose : Provides extended logging output. When enabled, the task list is rendered with the verbose renderer, so every task and its output stays visible instead of being collapsed. For the doctor status command, this flag also lists the unchanged files.

--output <default|json> : The way the command reports its result. With json, the human readable output is silenced and a single JSON document is written to stdout, which a CI/CD pipeline can gate on or turn into a pull request comment. Check the JSON output section for the documents the status and publish commands return.

--commandName <commandName> : Override the command used to execute CLI for Microsoft 365. By default, doctor executes commands through the bundled @pnp/cli-microsoft365 API directly. The m365 (default) and localm365 values both use this in-process API. Any other value is executed as a binary on your PATH. Use this option only when you explicitly want to run a different command binary.

--commandTimeout <commandTimeout> : The timeout in milliseconds for each CLI for Microsoft 365 command which doctor executes. Default value is: 120000 (2 minutes). Increase this value when you run into Command timed out after 120000ms errors, which can happen on large sites or slow connections.

{
"commandTimeout": 300000
}

The --output json argument turns the result of a run into something a script can act on. All human readable output is left out, and doctor writes a single JSON document to stdout.

Terminal window
doctor status --output json

Which lets your pipeline decide whether it has anything to publish:

Terminal window
if doctor status --output json | jq -e '.summary.upToDate' > /dev/null; then
echo "Nothing changed, skipping the publish"
fi
{
"command": "status",
"success": true,
"version": "2.1.0",
"url": "https://<tenant>.sharepoint.com/sites/<documentation>",
"state": {
"enabled": true,
"tracked": 12,
"filesChecked": 14
},
"summary": {
"new": 1,
"modified": 2,
"unchanged": 11,
"deleted": 0,
"orphaned": 0,
"changed": 3,
"upToDate": false
},
"pages": {
"new": [{ "file": "docs/new-page.md", "slug": "new-page.aspx" }],
"modified": [],
"unchanged": [],
"deleted": [],
"orphaned": []
},
"warnings": []
}
Property Description
state.enabled Whether the publish state is used. All pages are reported as new when it is disabled with --disableStatePersistence.
summary.changed The new and modified pages together: what the next publish run processes.
summary.upToDate true when there is nothing left to publish, and nothing to remove.
pages.* The pages of each category, with the file path relative to the folder you ran doctor from. A deleted page has no file, an orphaned language file has no slug.

The pages lists are always complete, also for the unchanged pages. The --verbose flag only influences the human readable output.

{
"command": "publish",
"success": true,
"version": "2.1.0",
"url": "https://<tenant>.sharepoint.com/sites/<documentation>",
"summary": {
"pages": { "total": 14, "created": 1, "updated": 2, "skipped": 11, "removed": 0 },
"images": { "total": 3, "uploaded": 3, "skipped": 0 },
"retries": 0,
"errors": 0,
"durationMs": 42123
},
"failedFiles": [],
"warnings": []
}

The timings property is added when you pass the --timingDetails flag.

A failing run writes the same kind of document, and exits with code 1:

{
"command": "publish",
"success": false,
"version": "2.1.0",
"error": {
"message": "The provided folder location doesn't exist."
}
}

Every other command returns a { "command", "success", "version" } document, so --output json never leaves you with output which cannot be parsed.

--continueOnError : Continue when an error occurs during the publishing process.

--outputFolder <outputFolder> : When providing this option, the processed markdown files will be generated in this folder.

--cleanEnd : Removes the pages which the run did not want, at the end of the whole process. A page which was skipped — as unchanged, or because its metadata could not be worked out — is still a page doctor wants, and is left alone. What gets removed is what has no markdown file behind it any more.

--cleanStart : Removes all pages before creation. This ensures that you that all changes made to your documentation get removed.

--confirm : Don’t prompt for confirming removing the files when you specified to clean up pages and assets before publishing.

--skipExistingPages : Will not overwrite pages if they already existed on the site. The shorter --skipExisting alias can be used as well.

--forceAll : Reprocess all pages, ignoring the saved publish state. By default doctor only publishes pages which are new or whose content changed since the last run. Check the change detection section for more information.

--removeDeleted : Recycles the pages which doctor published before, but whose markdown file no longer exists. Requires the --confirm flag, or doctor asks you to confirm the removal. Check the removing deleted pages section for more information.

--skipPrecheck : Skips the checks which run before any page is written: the local front matter and slug validation, and the capability check described below. Check the pre-process checks section for more information.

--timingDetails : Shows additional per-page timing statistics (average, fastest and slowest page) after the publishing run. The total publishing time is always shown, also without this flag.

--applyTheme : Applies the theme defined in the siteDesign.theme property of your doctor.json file.

--retryWhenFailed : Specifying this flag will retry the command if it failed. In some cases it can be that SharePoint fails to process your request, and this allows you to try again without running the whole flow from scratch.

--skipPages: : This flag allows you to skip the pages provisioning in the publish flow.

--skipNavigation: : This flag allows you to skip setting the navigation in the publish flow.

--skipSiteDesign: : This flag allows you to skip setting the site’s look and feel in the publish flow.

--cleanQuickLaunch : Allows you to specify if you want to remove all the navigation elements defined in the QuickLaunch navigation before adding the new navigation structure.

--cleanTopNavigation : Allows you to specify if you want to remove all the navigation elements defined in the TopNavigation navigation before adding the new navigation structure.

--pageTemplate : Name of the default page template to use for all the pages which will be created. It accepts the template’s page title, its file name or its page id. A page can override it with the template front matter — see page templates.

--reapplyTemplates : Applies the page template to pages which already exist, not only to the ones Doctor creates. Off by default. Check page templates.

--disableComments : Disable comments for all pages. By default the comments are enabled on the pages.

--disableStatePersistence : Disables loading and saving of the publish state file. When you use this flag, doctor cannot detect changes, so all pages are processed on every run.

--stateFile <stateFile> : The path of the state file within the library defined by --library. Default value is: .doctor/state.json, which results in Shared Documents/.doctor/state.json when the default library is used.

doctor keeps track of what it published in a state file which is stored on your SharePoint site. For every page it stores a hash of everything the page is built from, the timestamp of when it got published, and the instance ids of the web parts doctor put on it — which is how it recognises its own controls on the next run and leaves the ones you added in SharePoint alone. The file also carries a hash of the publish settings and your custom shortcodes, so changing one of those marks every page as changed, and a hash of every image and diagram doctor uploaded to the library, so a changed one is uploaded again and an unchanged one is not.

On the next run, doctor compares the hash of each local file with the one in the state file:

  • Pages which are new or modified get published.
  • Pages which are unchanged get skipped.

A skipped page is still a page on the site, so it keeps everything a published page would have kept: its entry in the site navigation, which is rebuilt on every run, and its place in the site when --cleanEnd removes the pages the run did not want. The same goes for a page skipped because its metadata could not be worked out.

The hash covers everything the published page is built from, not just the file you edited:

What changed Effect
The markdown file that page is modified
A partial it uses every page using that partial is modified
An image it references, in its text or as its header.image banner every page referencing that image is modified, and the image is uploaded again. The state records a hash of every file doctor uploads, so an unchanged image is not — unless --overwriteImages is set
The slug of a page it links to every page linking to it is modified, so its links keep pointing at the right page
A custom shortcode’s code every page is modified — a shortcode decides what its pages render
A publish setting in doctor.json (markdown.*, webPartTitle, partials.*, library, the template options) every page is modified
The page template, with --reapplyTemplates every page using that template is modified

Images and linked pages are read once per run, however many pages refer to them.

Localized pages are tracked the same way, under the URL SharePoint issued for them. They are published in their own phase which runs after the normal pages, so a changed .lang.md file gets published even when its source page did not change.

The state is saved after each page, so when a publishing run fails halfway, the already published pages do not need to be processed again on the next run.

The following options influence this behavior:

  • --forceAll: reprocess everything, ignoring the state.
  • --disableStatePersistence: do not load or save the state at all.
  • --stateFile: store the state on another location.
  • --library: the library in which the state file is stored.

Use the doctor status command to see which pages will be published on the next run.

Deleting a markdown file does not remove the page it created on your site. doctor knows which pages it published, as it tracks them in the state file, and doctor status lists the ones without a local file as Deleted.

Pass the --removeDeleted flag to act on them:

Terminal window
doctor publish --removeDeleted --confirm

Every page which is tracked in the state, but has no markdown file anymore, gets recycled and dropped from the state. The pages end up in the site’s recycle bin, so you can still restore them from SharePoint itself.

Good to know:

  • The state file is the source of truth. Pages which were created outside of doctor, or before the state file existed, are not touched. Use the --cleanEnd flag when you want to remove everything doctor does not have a markdown file for, whether or not it is in the state.
  • Multilingual pages are removed together with their source page. Translations of a page which still exists are kept.
  • Pages which are already gone from the site are removed from the state as well, so the state keeps matching your site.
  • When a markdown file cannot be resolved to a page (an unreadable file, or one without a title), no pages get removed at all. The pre-process checks catch these before the publishing run, unless you use --skipPrecheck.
  • The flag has no effect in combination with --disableStatePersistence or --skipPages, as doctor needs the state to know which pages it created.

Before any call to SharePoint is made, doctor validates your markdown files and stops the publishing run when it finds issues. This prevents a run from failing halfway through. The following checks are performed:

  • Files which cannot be read.
  • Front matter which cannot be parsed.
  • Pages without a title in their front matter.
  • Duplicate slugs, as these pages would overwrite each other on the site.
  • Localization references in the front matter pointing to a file which does not exist on disk.

When one or more issues are found, the run stops and all issues are listed at once (up to a maximum of 20, followed by the number of remaining issues). Pages of the translation type are skipped during this validation.

doctor then asks the site which of its operations the account is actually allowed to perform, and prints the answer before anything is written:

Available permissions on https://contoso.sharepoint.com/sites/docs:
yes Publish pages
yes Set page metadata
yes Upload assets to "Shared Documents"
no Update a page without changing its history — page descriptions will change 'Modified' and 'Modified By'
no Manage the site navigation — the 'menu' setting is skipped
no Change the look of the site — the 'siteDesign' setting is skipped
yes Read the term store
yes Read the site users

Publishing pages and setting metadata need rights on the Site Pages library. The navigation, the theme, the header and footer and the site logo need Manage Web rights on the site — an account that is perfectly able to publish pages often does not have those, which used to surface as a failure at the very end of a run, with every page already written.

  • A step the account cannot perform is skipped, not attempted and failed. Each one is repeated in the warnings at the end of the run.
    • Without Manage Web, the menu and siteDesign settings are left alone and the pages still publish.
    • Without rights to set columns, the metadata and author front matter is skipped — and not even worked out, so the term store and the user lookups are not paid for either.
    • Without access to the term store, a page which sets a managed metadata column by its label is skipped whole. The app registration needs the TermStore.Read.All permission from SharePoint — see the term store.
    • Without rights to write to the asset library, a page which has to upload something is skipped whole rather than published with its pictures pointing at nothing — that means a page with an image, with a header.image, or with a Mermaid diagram, since doctor draws those during the publish and uploads them like any other image. The publish state is not saved either, so the next run publishes everything again.
  • A missing system update right is the one that is not a skip: descriptions are written with an ordinary update instead, at the cost of the page’s Modified date and Modified By.
  • Not being able to create or update pages stops the run straight away, since that is the whole job.
  • Only the steps this run was going to take are listed — no menu in your configuration means no line about navigation.
  • If the site’s permissions cannot be read at all, doctor says so and attempts everything, exactly as it did before this check existed.

This is a check of what the account may do, not of what the site will accept. A term which is not in the term set, or an author who is not a member of this site, is still found per page while publishing.

Use the --skipPrecheck flag when you want to skip this validation and the capability check.

--provider <provider> : The CI/CD platform to generate the definition for. Supported values are github (default) and azdo. Check the workflow command section for more information.

Visitors