zkdoc (on-premises)
One of Zeugwerk's CI/CD tools for TwinCAT. zkdoc is the on-premises command-line tool that generates API documentation from TwinCAT PLC source code and produces HTML sites via DocFX. It is the self-hosted counterpart to zkdoc-action.
Use zkdoc when you need to generate documentation in a private or air-gapped environment, integrate with a pipeline that does not use GitHub/GitLab/Bitbucket Actions, or customize the output extensively with your own DocFX templates.
For cloud-based doc generation with no local setup, use zkdoc-action instead.
Comment syntax - How to write documentation comments in your PLC source: Syntax reference.
Availability
| Option | When to use |
|---|---|
| zkdoc-action | Public repositories on GitHub, GitLab, or Bitbucket. Free tier (30 builds/month). |
| zkdoc CLI (this page) | Private repos, on-premises pipelines, or any CI that runs Windows executables. Requires a license. |
Contact us for licensing, trials, and on-premises options.
Requirements
| Requirement | Notes |
|---|---|
| Windows | Required; zkdoc runs as a Windows .NET executable. |
| .NET runtime | Bundled with the zkdoc distribution. |
| License file | license.lic must be placed in the same folder as zkdoc.exe. Trial available on request. |
| DocFX (optional) | Required only for HTML output. Download from dotnet.github.io/docfx. |
Installation & licensing
- Extract the zkdoc ZIP archive to a folder on your machine (e.g.
C:\tools\zkdoc\). - Place
license.lic(provided by Zeugwerk) in the same folder. - Optionally install DocFX and add
docfx.exeto yourPATH.
Verify the installation:
zkdoc.exe --version
Quick start
Point zkdoc at your .plcproj file and it extracts documentation, writes Markdown, and sets up a DocFX project:
zkdoc.exe --docfx --markdown -o "C:\output\docs" "C:\repos\MyProject\MyPLC\MyPLC.plcproj"
Then build the HTML site with DocFX:
docfx.exe build "C:\output\docs\docfx.json"
Serve locally for preview:
docfx.exe serve "C:\output\docs\docfx.json"
Writing documentation comments
zkdoc extracts documentation written directly in your PLC source using /// and //< comment delimiters. The same syntax works with zkdoc-action in the cloud.
For the full reference - delimiter rules, visibility filters, \copydoc, cross-references, diagrams, and code formatting - see the Comment syntax reference.
Usage
zkdoc.exe [filepaths...] [options]
filepaths can be:
- One or more paths to
.plcprojfiles. - A directory that contains a
.Zeugwerk/config.json(the project is resolved automatically). Pass.for the current directory.
CLI reference
| Option | Short | Default | Description |
|---|---|---|---|
filepaths |
(current dir) | Paths to .plcproj files or directories containing .Zeugwerk/config.json. Multiple paths can be listed; zkdoc combines them into one documentation set. |
|
--output |
-o |
documentation |
Root output directory. Created if it does not exist. All generated files are written under this path. |
--docfx |
- | Subfolder name inside --output for DocFX Markdown and the docfx.json project file (e.g. reference). Required to produce HTML with DocFX. |
|
--markdown |
- | Subfolder name inside --output for plain Markdown reference files (no DocFX dependency). Can be used independently of --docfx. |
|
--filter |
-f |
((_)*Test[s]*\\.*?\|.*?\\(_)*Test[s]*\\.*?\|.*?\\(_)*Example[s]*\\.*?) |
Regular expression to exclude source paths. Matched against the full file path. Files whose path contains _Test, _Tests, or _Examples as a subfolder are excluded by default. |
--include-internal |
false |
Include objects marked with the INTERNAL access modifier or the {attribute 'hide'} pragma. Excluded by default. |
|
--exclude-private |
false |
Exclude objects and methods with the PRIVATE access modifier. Included by default. |
|
--exclude-protected |
false |
Exclude objects and methods with the PROTECTED access modifier. Included by default. |
|
--depth |
1 |
Maximum category depth shown in the navigation sidebar of the generated site. Increase for projects with deep namespaces. | |
--twincat-source-target |
src |
Subfolder inside --output where TwinCAT PLC source files are extracted. |
|
--telemetry |
false |
Send anonymous usage data to Zeugwerk (install ID, tool name, version). |
Output structure
After running zkdoc --docfx --markdown -o documentation MyPLC.plcproj, the output directory contains:
documentation/
├── docfx.json ← DocFX project file (generated once; not overwritten if it exists)
├── toc.yml ← Top-level table of contents
├── index.md ← Landing page (generated if not present)
├── reference/ ← DocFX Markdown (--docfx)
│ ├── toc.yml
│ └── <Namespace>/
│ ├── <FunctionBlock>.md
│ ├── <Interface>.md
│ └── ...
├── md-reference/ ← Plain Markdown (--markdown), no DocFX deps
│ └── ...
├── userguide/ ← Placeholder user guide (generated if not present)
│ ├── introduction.md
│ └── toc.yml
└── html/ ← Final HTML output (produced by DocFX build)
└── ...
Note
If docfx.json already exists in the output folder, zkdoc does not overwrite it. This lets you maintain a custom template or adjusted configuration across runs.
Examples
Single PLC, full HTML site
zkdoc.exe --docfx --markdown -o docs MyProject\MyPLC\MyPLC.plcproj
docfx.exe build docs\docfx.json
docfx.exe serve docs\docfx.json
Multiple PLCs in one documentation set
List all .plcproj paths; zkdoc merges them into a single API reference:
zkdoc.exe --docfx --markdown -o docs ^
src\LibraryA\LibraryA.plcproj ^
src\LibraryB\LibraryB.plcproj
Zeugwerk / Twinpack project (auto-discovery)
Pass the repository root (.) and zkdoc will use .Zeugwerk/config.json to discover all PLC projects:
zkdoc.exe --docfx --markdown -o docs .
Exclude additional folders
Use --filter to extend the default exclusions with your own pattern:
:: Exclude _Internal and _Internals folders as well
zkdoc.exe --docfx -o docs --filter "((_)*Internal[s]*\\.*?)" MyPLC.plcproj
Include internal members
zkdoc.exe --docfx -o docs --include-internal MyPLC.plcproj
Exclude private and protected members
zkdoc.exe --docfx -o docs --exclude-private --exclude-protected MyPLC.plcproj
Deeper namespace hierarchy
zkdoc.exe --docfx -o docs --depth 3 MyPLC.plcproj
Customizing documentation output
For adding custom Markdown pages, adjusting the folder layout, and customizing the DocFX HTML template, see the Customizing documentation output reference. The same options apply to zkdoc-action.
Integration with CI/CD pipelines
zkdoc requires a Windows agent with TwinCAT XAE and DocFX installed. The pipeline generates Markdown from the PLC source, then DocFX converts it to HTML. The HTML output can be archived as a build artifact or deployed to a web server / GitHub Pages.
Jenkins (Declarative Pipeline)
pipeline {
agent { label 'windows-twincat' }
stages {
stage('Generate documentation') {
steps {
// Generate DocFX Markdown from PLC source into the documentation/ folder.
bat "zkdoc.exe --docfx reference --output documentation ."
// Build the HTML site from the generated DocFX project.
bat "docfx.exe build documentation\\docfx.json"
}
}
stage('Publish') {
steps {
publishHTML(target: [
reportDir: 'documentation/html',
reportFiles: 'index.html',
reportName: 'API Documentation'
])
}
}
}
post {
always {
archiveArtifacts artifacts: 'documentation/html/**/*', allowEmptyArchive: true
}
}
}
Azure DevOps
jobs:
- job: Docs
pool:
name: 'windows-twincat-agents'
steps:
- script: |
zkdoc.exe --docfx reference --output documentation .
docfx.exe build documentation\docfx.json
displayName: Generate documentation
- task: PublishPipelineArtifact@1
inputs:
targetPath: documentation/html
artifact: api-docs
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
License verification failed |
license.lic missing or expired |
Place license.lic next to zkdoc.exe. Contact us for a trial or renewal. |
Invalid arguments or no output |
No valid .plcproj or config.json found |
Verify the filepath argument and that the file exists. |
| Empty reference section | All POUs matched by the filter | Check --filter. Run with --include-internal to see if items are being hidden by access modifiers. |
| DocFX build errors | Malformed Markdown or missing references | Check zkdoc console output for parse warnings. Missing \copydoc targets print an explicit error message. |
| HTML layout broken | Custom docfx.json references a missing template |
Verify template names in docfx.json. The default templates are default, modern, template, and statictoc. |
docfx.json not updated |
Intentional - zkdoc never overwrites an existing docfx.json |
Edit docfx.json manually, or delete it to let zkdoc regenerate it. |
Summary
- Install zkdoc and place
license.licnext to the executable. - Optionally install DocFX for HTML output.
- Run
zkdoc.exe --docfx --markdown -o <out> <path-to.plcproj>. - Run
docfx.exe build <out>/docfx.jsonand open thehtml/folder. - Add custom Markdown pages to
userguide/and link them intoc.yml.
For comment syntax, cross-references, diagrams, and code formatting: Syntax reference.
For cloud-based generation without a local setup: zkdoc-action.