Xml2Doc.Cli
2.4.0
dotnet tool install --global Xml2Doc.Cli --version 2.4.0
dotnet new tool-manifest
dotnet tool install --local Xml2Doc.Cli --version 2.4.0
#tool dotnet:?package=Xml2Doc.Cli&version=2.4.0
nuke :add-package Xml2Doc.Cli --version 2.4.0
Xml2Doc.Cli
Command-line interface for Xml2Doc, part of the mod-posh organization.
Overview
Xml2Doc.Cli converts C# XML documentation into deterministic Markdown using Xml2Doc.Core.
Version 2.4.0 adds deterministic caller metadata and built-in multi-document layout selection while preserving single-input and aggregate defaults.
The CLI is multi-targeted for:
net8.0net9.0
Rendered Markdown is expected to be identical across supported CLI TFMs for the same options and inputs.
Install as a .NET tool
dotnet tool install --global Xml2Doc.Cli --version 2.4.0
The installed command is xml2doc.
Basic usage
Generate per-type documentation from one XML file:
xml2doc `
--xml .\bin\Release\net9.0\MyLibrary.xml `
--out .\docs
Generate one combined Markdown file:
xml2doc `
--xml .\bin\Release\net9.0\MyLibrary.xml `
--out .\docs\api.md `
--single `
--file-names clean
Aggregate multiple projects into one deterministic output set by repeating --xml:
xml2doc `
--xml .\src\ProjectA\bin\Release\net9.0\ProjectA.xml `
--xml .\src\ProjectB\bin\Release\net9.0\ProjectB.xml `
--out .\docs `
--file-names clean `
--line-endings lf
One XML input uses the compatible single-input loading path. Two or more primary inputs use Core aggregation. Input paths are canonicalized before loading so input order does not control output order.
If two primary inputs define the same XML documentation member, generation fails with XML2DOC006 instead of selecting an owner based on argument order.
Options
| Option | Description |
|---|---|
--xml <path> |
Primary XML documentation input. Repeat to aggregate multiple files. |
--out <path> |
Output directory, or output file when used with --single. |
--single |
Generate one consolidated Markdown file. |
--file-names <verbatim\|clean> |
Filename mode. |
--rootns <namespace> |
Trim a namespace prefix from displayed type names. |
--trim-rootns-filenames |
Also trim the root namespace from filenames. |
--lang <language> |
Fenced-code language. Default: csharp. |
--anchor-algorithm <mode> |
default, github, gfm, or kramdown. |
--template <path> |
Apply a file-based template. |
--front-matter <path> |
Prepend configured front matter. |
--metadata <key=value> |
Add generic caller metadata. Repeat for multiple values. |
--auto-link |
Enable safe free-text symbol linking. |
--alias-map <path> |
Load an additional alias map. |
--external-docs <base-url> |
Route unresolved references to an external documentation base URL. |
--toc |
Emit member tables of contents. Directory output only. |
--namespace-index |
Emit namespace index/pages. Directory output only. |
--no-index |
Suppress the per-type index.md. |
--basename-only |
Use basename-only output names and links. |
--parallel <N> |
Maximum per-type render parallelism. Must be positive. |
--prune-stale |
Remove stale files owned by the selected manifest identity. Directory output only. |
--manifest-id <identity> |
Stable ownership identity required with --prune-stale. |
--line-endings <style> |
lf (default), crlf, or native. |
--layout <mode> |
flat (default) or namespace-folders. |
--report <path> |
Write a JSON execution report. |
--dry-run |
Plan output without writing Markdown. |
--diff |
Compare generated output with current files without modifying them. |
--config <path> |
Load JSON configuration. CLI arguments take precedence. |
--help, -h |
Display help. |
--dry-run and --diff are mutually exclusive. --toc, --namespace-index, and --prune-stale require directory output.
Exit codes:
0— success, or no differences for--diff.1— invalid command-line/configuration input.2— diagnostic or runtime error.3— differences found by--diff.
JSON configuration
Single-input example:
{
"Xml": "src/MyLib/bin/Release/net9.0/MyLib.xml",
"Out": "docs/api.md",
"Single": true,
"FileNames": "clean",
"RootNamespace": "MyCompany.MyProduct",
"CodeLanguage": "csharp",
"Metadata": {
"package": "MyCompany.MyProduct",
"tags": ["api", "stable"],
"version": "2.4.0"
},
"LineEndings": "lf"
}
Multi-input aggregation example:
{
"XmlInputs": [
"src/ProjectA/bin/Release/net9.0/ProjectA.xml",
"src/ProjectB/bin/Release/net9.0/ProjectB.xml"
],
"Out": "docs",
"FileNames": "clean",
"GenerateIndex": true,
"Parallel": 4,
"LineEndings": "lf"
}
When no CLI --xml arguments are supplied, non-empty XmlInputs takes precedence over the legacy single-input Xml property. Repeated CLI --xml arguments take precedence over both configuration properties.
Run a configuration file with:
xml2doc --config .\xml2doc.json
Configuration supports the same applicable values as the CLI surface, including TrimRootNamespaceInFileNames, Report, DryRun, Diff, AnchorAlgorithm, Template, FrontMatter, Metadata, AutoLink, AliasMap, ExternalDocs, Toc, NamespaceIndex, GenerateIndex, Parallel, BasenameOnly, PruneStaleFiles, ManifestIdentity, LineEndings, and Layout.
Repeated --metadata key=value arguments override matching keys from the JSON Metadata object.
Caller metadata produces deterministic YAML front matter containing Core-derived documentId,
documentKind, namespace, symbol, and outputPath values. Those document keys are
authoritative. Metadata cannot be combined with the literal --front-matter file mode.
Unknown JSON properties and invalid values are rejected rather than ignored silently.
Reports, dry run, and diff
When --report is configured, reports include deterministic planned and actual result sets plus runner timing information. Aggregate reports include canonical xmlInputs while retaining the compatible xml field for the first canonical input.
Dry runs do not modify Markdown or ownership state. Reports leave actual-result arrays empty and populate wouldWrite and wouldDelete as applicable.
--diff performs a non-mutating comparison against current generated output. The report/console result classifies added, changed, unchanged, and removed files. Removed files are limited to stale outputs owned by the selected manifest identity when pruning is enabled.
Stale-output ownership
For safe pruning in directory mode, use a stable identity:
xml2doc `
--xml .\bin\Release\net9.0\MyLibrary.xml `
--out .\docs `
--prune-stale `
--manifest-id MyCompany.MyLibrary
Only paths recorded by the manifest for that exact identity can be removed. Untracked files and files owned by other identities are preserved. Pruning is unavailable with --single.
Diagnostics
CLI diagnostics are written to standard error in the stable form:
xml2doc <severity> <code>: <message>
Source locations and member IDs are included when available. Warnings do not fail generation.
Aggregation-specific diagnostics include:
XML2DOC006— multiple primary XML inputs define the same documentation member.
The remaining stable diagnostic IDs are documented in the repository-level Xml2Doc.md.
Running a locally built CLI
Build the project, then run one produced TFM explicitly:
dotnet build .\Xml2Doc\src\Xml2Doc.Cli\Xml2Doc.Cli.csproj -c Release
dotnet .\Xml2Doc\src\Xml2Doc.Cli\bin\Release\net9.0\Xml2Doc.Cli.dll `
--xml .\path\to\MyLibrary.xml `
--out .\docs
Using the built DLL avoids ambiguity when working directly with a multi-targeted executable project.
Determinism notes
- Markdown uses LF on every platform by default.
- Aggregate input paths are canonicalized before loading.
- Per-type rendering may use
--parallel, but output ordering remains deterministic. - CLI reports omit timestamps by default so equivalent invocations remain comparable.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.4.0 | 54 | 9/1/2026 |
| 2.3.1 | 87 | 8/30/2026 |
| 2.3.0 | 118 | 8/17/2026 |
| 2.2.0 | 104 | 8/17/2026 |
| 2.1.0 | 108 | 8/16/2026 |
| 2.0.3 | 96 | 8/15/2026 |
| 2.0.2 | 103 | 8/14/2026 |
| 2.0.1 | 91 | 8/14/2026 |
| 2.0.0 | 101 | 8/13/2026 |
| 2.0.0-preview.113-g69c1a44 | 51 | 8/13/2026 |
| 1.4.0 | 87 | 8/13/2026 |
| 1.4.0-preview.111-g7a5369b | 62 | 8/13/2026 |
| 1.4.0-preview.110-g1edd8f0 | 65 | 8/13/2026 |
| 1.4.0-preview.109-g42abc6e | 64 | 8/13/2026 |
| 1.4.0-preview.108-g611e3f5 | 57 | 8/13/2026 |
| 1.4.0-preview.107-gc4dc99b | 58 | 8/13/2026 |
| 1.4.0-preview.106-gffe4bab | 68 | 8/13/2026 |
| 1.4.0-preview.105-gd9e6cf3 | 60 | 8/13/2026 |
| 1.4.0-preview.104-gfa11148 | 56 | 8/13/2026 |
| 1.4.0-preview.103-gc413f43 | 54 | 8/13/2026 |