.Zeugwerk/config.json reference
.Zeugwerk/config.json is the single configuration file used by both zkbuild-action and zkmake. It describes the solution structure, declares package dependencies, maps TwinCAT library references, and optionally configures source patches. The file lives at the root of your repository under .Zeugwerk/config.json.
The easiest way to create and maintain this file is through the Twinpack IDE extension, which generates it from your open solution.
Minimal example
A single library project with no external packages:
{
"fileversion": 1,
"solution": "MyProject.sln",
"projects": [
{
"name": "MyProject",
"plcs": [
{
"name": "MyPLC",
"version": "1.0.0.0",
"type": "Library"
}
]
}
]
}
Top-level fields
| Field | Required | Description |
|---|---|---|
fileversion |
Yes | Schema version. Always 1. |
solution |
Yes | Path to the Visual Studio solution file (.sln), relative to the .Zeugwerk/ folder's parent directory. |
projects |
Yes | Array of project objects (see Projects). |
modules |
No | Array of subdirectory paths, each containing its own .Zeugwerk/config.json. Used for monorepos or solutions split across multiple folders. Each module is built independently and its libraries are combined in the final artifact set. |
Modules
When a solution is split across multiple folders, list the subdirectories under modules. Each listed folder must contain its own .Zeugwerk/config.json.
{
"fileversion": 1,
"solution": "MyProject.sln",
"modules": [
"modules/AxisControl",
"modules/SafetyPLC"
]
}
The build system processes each module in order, accumulating compiled libraries into a shared cache. Later modules can depend on libraries produced by earlier modules.
Projects
Each entry in projects maps to a Visual Studio project in the solution.
| Field | Required | Description |
|---|---|---|
name |
Yes | Must match the project name in the .sln file exactly. |
plcs |
Yes | Array of PLC objects (see PLCs). |
PLCs
Each entry in plcs describes one TwinCAT PLC project within the Visual Studio project.
| Field | Required | Description |
|---|---|---|
name |
Yes | PLC name as it appears in the TwinCAT solution tree. |
version |
Yes | Version in Major.Minor.Patch.Build format, e.g. 1.2.0.0. Used for the output artifact filename. |
type |
Yes | Project type. See PLC types. |
title |
No | Human-readable display name. Defaults to name if omitted. |
distributor-name |
No | Name of the distributor shown in the TwinCAT library manager. |
packages |
No | External packages to install before building. See Packages. |
references |
No | TwinCAT system library references. See References. |
patches |
No | Source patches to apply before compiling. See Patches. |
PLC types
| Value | Description |
|---|---|
Library |
Standard TwinCAT library. The build produces a .library file. |
FrameworkLibrary |
Same as Library; indicates the PLC is part of the Zeugwerk Framework family. |
Application |
TwinCAT application (runtime project). No .library is produced; the solution is built and can be activated to a target. |
UnitTestApplication |
TwinCAT test application in the same solution (native TcUnit). Built with the release solution and executed in the test phase. See Unit tests — Option C. |
Packages
The packages array declares external Twinpack packages that the PLC depends on. The build system downloads, resolves, and installs them automatically before compilation.
{
"packages": [
{
"name": "ZCore",
"version": "1.2.19.0",
"repository": "Twinpack",
"branch": "release/1.2",
"target": "TC3.1",
"configuration": "Distribution",
"distributor-name": "Zeugwerk GmbH"
}
]
}
| Field | Required | Description |
|---|---|---|
name |
Yes | Package name as registered in the Twinpack repository. |
version |
Yes | Exact version to install, e.g. 1.2.19.0. |
repository |
Yes | Twinpack repository identifier (e.g. Twinpack, bot). Must match a configured source in Twinpack. |
branch |
No | Source branch for the package (e.g. release/1.2, main). |
target |
No | TwinCAT target platform (e.g. TC3.1). Defaults to the target passed to the build tool. |
configuration |
No | Package build configuration (e.g. Distribution, Release, Snapshot). |
distributor-name |
No | Distributor name shown in the TwinCAT library manager (e.g. Zeugwerk GmbH). |
Full example with packages
{
"fileversion": 1,
"solution": "TwinCAT Project1.sln",
"projects": [
{
"name": "TwinCAT Project1",
"plcs": [
{
"name": "MyPLC",
"version": "1.0.0.0",
"type": "Library",
"distributor-name": "My Company",
"packages": [
{
"name": "ZCore",
"version": "1.2.19.0",
"repository": "Twinpack",
"branch": "release/1.2",
"target": "TC3.1",
"configuration": "Distribution",
"distributor-name": "Zeugwerk GmbH"
},
{
"name": "Tc2_MC2",
"version": "3.3.38.0",
"repository": "Beckhoff",
"target": "TC3.1",
"configuration": "Release",
"distributor-name": "Beckhoff Automation GmbH"
}
],
"references": {
"*": [
"Tc2_Standard=*",
"Tc2_System=*",
"Tc3_Module=*"
]
}
}
]
}
]
}
References
The references field maps TwinCAT target platforms to a list of system library references that must be present in the PLC project. These are Beckhoff system libraries (e.g. Tc2_Standard) that ship with TwinCAT, not Twinpack packages.
{
"references": {
"*": [
"Tc2_Standard=*",
"Tc2_System=*",
"Tc2_MC2=*",
"Tc3_Module=*"
]
}
}
The key "*" applies to all TwinCAT target versions. You can also use a specific version string (e.g. "TC3.1.4024.56") to apply references only when building for that exact version.
Each entry in the array follows the format LibraryName=Version, where * means "any installed version".
Patches
Patches modify the PLC source code before compilation. They are declared under patches at the PLC level and are never committed to the compiled output - they only affect the build.
Two types are supported:
Platform patches
Applied automatically when building for a specific TwinCAT version. Useful for version-specific compatibility fixes.
{
"patches": {
"platform": {
"TC3.1.4024.56": [
"patches/fix-4024.patch",
"patches/workaround.replacement"
]
}
}
}
Argument patches
Applied only when the build tool is explicitly told to apply a named patch (via --patch <identifier> in zkmake, or the patch argument in zkbuild-action). Useful for feature flags, toggling optional behaviour, or build variants.
Note
Argument patches are not available on the free tier of zkbuild-action. Contact us or open an issue if you need them for open source use.
{
"patches": {
"argument": {
"enable-feature-x": [
"patches/enable-feature-x.replacement"
]
}
}
}
Activate an argument patch:
:: zkmake (on-premises)
zkmake.exe build --patch enable-feature-x
# zkbuild-action (GitHub)
- name: Build
uses: Zeugwerk/zkbuild-action@1.0.0
with:
username: ${{ secrets.ACTIONS_ZGWK_USERNAME }}
password: ${{ secrets.ACTIONS_ZGWK_PASSWORD }}
patch: enable-feature-x
Patch file formats
.patch files - Standard Git patches applied via git apply. Create one with:
git diff > patches/my-change.patch
.replacement files - Search-and-replace over source files. A JSON file with three fields:
| Field | Description |
|---|---|
filter |
Glob pattern selecting which files to modify (e.g. *.TcPOU, *.TcGVL). |
search |
Regular expression to find. Special regex characters must be escaped. |
replace |
Replacement string. Use $1…$N for regex capture groups. |
{
"filter": "*.TcPOU",
"search": "FEATURE_FLAG := FALSE",
"replace": "FEATURE_FLAG := TRUE"
}
Complete example
{
"fileversion": 1,
"solution": "MyProject.sln",
"projects": [
{
"name": "MyProject",
"plcs": [
{
"name": "MyPLC",
"version": "2.1.0.0",
"type": "Library",
"title": "My PLC Library",
"distributor-name": "My Company",
"packages": [
{
"name": "ZCore",
"version": "1.2.19.0",
"repository": "Twinpack",
"branch": "release/1.2",
"target": "TC3.1",
"configuration": "Distribution",
"distributor-name": "Zeugwerk GmbH"
}
],
"references": {
"*": [
"Tc2_Standard=*",
"Tc2_System=*",
"Tc3_Module=*"
]
},
"patches": {
"platform": {
"TC3.1.4024.56": [
"patches/compat-4024.patch"
]
},
"argument": {
"debug-mode": [
"patches/enable-debug.replacement"
]
}
}
}
]
}
]
}