Documentation
plccheck CLI
Use npx plccheck for Siemens PLC diagnostics, tests, coverage, transpilation, and automation.
plccheck CLI
plccheck is the command-line tool for checking, testing, and exporting Siemens PLC projects from a terminal or automation workflow.
Use it with npx:
npx plccheck check ./my-plc-project
The CLI is useful when you want the same PLC feedback outside the VS Code UI: local terminal checks, CI jobs, scripted validation, or LLM/agent workflows that need a reliable command to inspect a Siemens project.
Project Layout
plccheck works best when each PLC project has a .plc.json file at its root. The PLC root defines the symbol and type scope for files below it.
{
"name": "PackingLine PLC",
"libraries": [
"../shared_types"
]
}
Supported project files include SCL / Structured Text source, S7DCL exports, S7RES resources, data blocks, UDTs, AWL files, PLC tag-table XML, and .scltest test files.
TIA exports preserve project-library instances in the same shape as TIA VCI exports: library-owned PLC objects become .liblink placeholders in the PLC folder, while the shared library definition is written once under a sibling Types folder with .libinfo and .libint sidecars. plccheck resolves those placeholders through project-library discovery, separate from custom library paths listed in .plc.json, without duplicating library code in every PLC.
Quick Commands
| Task | Command |
|---|---|
| Check a PLC project | npx plccheck check ./my-plc-project |
| Run PLC tests | npx plccheck test ./my-plc-project |
| Run one test subset | npx plccheck test ./my-plc-project --filter motor |
| Write coverage artifacts | npx plccheck test ./my-plc-project --coverage-json coverage.json --coverage-lcov lcov.info |
| Stream machine-readable test events | npx plccheck test ./my-plc-project --events-json |
| Transpile S7DCL FBD/LAD to SCL | npx plccheck transpile --to scl ./Program.s7dcl |
| Build a PLC runtime executable | npx plccheck compile --out plc-run.exe ./my-plc-project |
| Build and run a PLC runtime | npx plccheck run ./my-plc-project -- --opcua-port 4849 |
| Export PLC software | npx plccheck tia export software Demo.ap21 --out exported --plc PLC_1 |
| Export project hardware | npx plccheck tia export hardware Demo.ap21 --out exported |
| Start an LSP server | npx plccheck serve |
Check PLC Source
Use check to parse and type-check a file, folder, or PLC root.
npx plccheck check ./my-plc-project
The command exits non-zero when it finds errors. This makes it suitable for CI and for agent workflows where a tool needs a clear success/failure signal.
Useful flags:
| Flag | Description |
|---|---|
--jobs N | Controls parallel checking. Defaults to the available Go runtime parallelism. |
--show-warnings | Prints warning diagnostics as well as errors. |
Example:
npx plccheck check --show-warnings --jobs 4 ./my-plc-project
Run PLC Tests
Use test to run .scltest suites for a PLC root.
npx plccheck test ./my-plc-project
The test runtime is designed for fast iteration. It generates a runtime for the PLC project, runs selected test cases, and resets generated runtime state quickly between tests.
Useful flags:
| Flag | Description |
|---|---|
--filter <text> | Runs only test cases whose names contain the filter text. |
--list-cases | Prints selected test cases before running. |
--parallel N | Controls parallel execution of generated test cases. |
--module <path> | Sets the generated Go module path. |
--events-json | Streams machine-readable test events to stdout. |
--entry-ob <name> | Sets the whole-program entry OB when the default OB1 is not correct. |
Examples:
npx plccheck test ./my-plc-project --filter startup
npx plccheck test ./my-plc-project --events-json
npx plccheck test ./my-plc-project --entry-ob Main
Generate Coverage
Use coverage flags with test to write reports.
npx plccheck test ./my-plc-project --coverage-json coverage.json --coverage-lcov lcov.info
Coverage artifacts include statement, function, and branch data where runtime data is available.
| Artifact | Use |
|---|---|
--coverage-json <file> | Structured coverage data for custom tools, CI summaries, and LLM/agent analysis. |
--coverage-lcov <file> | LCOV tracefile for coverage viewers such as Coverage Gutters. |
If you use Coverage Gutters, lcov.info is a convenient default filename:
npx plccheck test ./my-plc-project --coverage-json coverage.json --coverage-lcov lcov.info
Compile and Run PLC Runtime
Use compile to generate a temporary Go runtime and build a standalone executable:
npx plccheck compile --out plc-run.exe ./my-plc-project
Use run to build and launch the runtime in one step. Runtime arguments go after --:
npx plccheck run ./my-plc-project -- --opcua-port 4849 --scan-period 24h
Transpile S7DCL to SCL
Use transpile to inspect generated SCL for TIA Portal exports.
npx plccheck transpile --to scl ./Program.s7dcl
For ambiguous inputs, provide the source form explicitly:
npx plccheck transpile --to scl ./Program.s7dcl
The source format is determined from the file extension. A single .s7dcl file may contain SCL, FBD, and LAD networks; all supported networks are emitted in source order. This is useful when reviewing graphical exports in text-based workflows or when an agent needs to reason about the equivalent SCL.
Emit Source Summaries
Use emit when you need a derived representation of a source file.
npx plccheck emit --target scl-summary ./Program.scl
Use this for inspection and automation tasks where a compact summary is easier to consume than the original export.
LSP Server Mode
serve starts the language server over stdio:
npx plccheck serve
Most users do not need to call this directly. It is intended for editor integrations or tools that can speak the Language Server Protocol.
TIA Portal Openness
On Windows x64 machines with TIA Portal Openness V21 or newer, tia commands attach to a running TIA project or open an explicit .ap21/.zap21 path. For an already open project, --project can be the exact project name shown by tia list --json instead of the full project path.
tia export software <project> uses the direct archive reader by default and falls back to TIA Openness when direct export fails or cannot produce every artifact. Pass an existing .zap21/.ap21 path for a TIA-free direct export, or pass the exact name of an open project. For an open project, Openness saves the project and copies its persistence files to a stable temporary snapshot before the direct reader runs. --engine direct and --engine openness force one software engine without fallback; --engine auto is the default.
tia export hardware <project> always uses TIA Openness and exports the whole project. Software and hardware are separate operations so ordinary source export does not pay the hardware-export startup cost.
npx plccheck tia host status --json
npx plccheck tia host install
npx plccheck tia rpc --filesystem-root exported
npx plccheck tia list --json
npx plccheck tia compile --project "Demo Project" --plc PLC_1 --json
npx plccheck tia export software Demo.ap21 --out exported --plc PLC_1 --delete-stale
npx plccheck tia export software "Demo Project" --out exported --engine auto
npx plccheck tia export software Demo.ap21 --out exported --engine openness
npx plccheck tia export hardware Demo.ap21 --out exported
npx plccheck tia import --project Demo.ap21 --root exported "exported/PLC_1/Program blocks/Main.scl" --create
npx plccheck tia import --project Demo.ap21 --root exported "exported/PLC_1/Program blocks/Main.scl" --overwrite-remote-changes
npx plccheck tia import --project Demo.ap21 --root exported --skip-library-instances "exported/PLC_1"
npx plccheck tia import --project Demo.ap21 --root exported "exported/PLC_1/Program blocks"
npx plccheck tia repair-library-dependencies --project Demo.ap21 --plc PLC_1 --owner CA
npx plccheck tia compile --project Demo.ap21 --plc PLC_1 --json
npx plccheck tia online --project Demo.ap21 --plc PLC_1
npx plccheck tia online --project Demo.ap21 --plc PLC_1 --online-auth-type ProjectUser --online-user engineer --online-password-env TIA_PROJECT_PASSWORD
npx plccheck tia offline --project Demo.ap21 --plc PLC_1
npx plccheck tia snapshot --project Demo.ap21 --plc PLC_1 --json
npx plccheck tia download --project Demo.ap21 --plc PLC_1 --json
Without --json, project-scoped tia list prints a PLC summary table with block/type counts and example commands using the listed PLC names. Human tia export software output prints each exported block and data type path relative to the export directory with its real file extension, then finishes with exported/failed block counts instead of dumping the structured file list. Use --json when scripts need the full structured result.
If tia list --json shows a running TIA process with projectPath but a project command reports that TIA Openness did not expose the project, the running Portal can see the file path but cannot provide a usable Openness Project. A common cause is that the machine is missing a TIA product or add-on required by that project. Close that TIA Portal instance and rerun a verification export with plccheck tia export software <path> --out <dir> --engine openness to surface TIA's native open error.
export writes each PLC under its own PLC-name root with a .plc.json file and preserves Program blocks / PLC data types folders. It also writes every TIA system constant for that PLC to system-constants.yml; this includes hardware IDs as well as the other constants exposed by the PLC's tag tables.
Software export through Openness accepts three optional item filters as environment variables: PLCCHECK_TIA_EXPORT_BLOCK_NAME, PLCCHECK_TIA_EXPORT_BLOCK_LANGUAGE, and PLCCHECK_TIA_EXPORT_BLOCK_PATH. Each holds one or more ;-separated values that must match the block name, programming language, or TIA folder path exactly (case-insensitive). PLCCHECK_TIA_SKIP_TYPE_EXPORT=1 skips PLC data types and project-library definitions. These filters apply to --engine openness.
The VS Code extension uses --engine direct for linked PLC exports and full temporary comparison snapshots. Source, resource, and format baselines in .meta.json support comparison and Openness import validation without TIA fingerprints. Diff previews reuse the accepted comparison snapshot; replacement and post-import refresh obtain a fresh export. Editor exports enable --allow-partial, keeping successfully rendered objects usable while reporting unavailable objects and suppressing stale-file cleanup. Linked projects compare automatically when opened and after saved storage changes; background snapshots use --saved-only to preserve unsaved TIA edits. See Direct export and comparison for details. The CLI's tia diff continues to default to --engine openness; pass --engine direct to use content comparison.
plccheck tia export hardware refreshes the canonical full-project CAx document at <out>/hardware.aml and parses that document into an in-memory hardware model. Readable, deterministic views of that model are written to <out>/hardware/project.yml, <out>/hardware/networks.yml, and one file per device under <out>/hardware/devices/. The device views preserve nested AML attributes, including interface channel metadata and module input/output start addresses. The canonical AML and its derived YAML always describe the complete project. Generated YAML files have no export timestamp and begin with an autogenerated warning. Hardware export and YAML generation use staged replacement, so an export or rendering failure preserves the previous complete artifact and exits non-zero. A CAx call is stopped after five minutes by default; set PLCCHECK_TIA_CAX_EXPORT_TIMEOUT_SECONDS to a positive number to change that watchdog.
SCL blocks are emitted through TIA external-source generation as .scl; PLC types, DBs, FBD, and LAD blocks are emitted through TIA document export first so the main editable output is .s7dcl. The export job runs inside one TIA exclusive-access scope across all selected PLCs, and the scope text is updated for each block or type with item progress, percentage, and ETA so long document exports show continuous TIA progress. Each item is staged in a clean temporary folder before replacing that item's previous files, so re-exporting into the same output directory does not require deleting it first. import accepts one or more source files or folders, expands folders recursively, infers the target PLC from paths under Program blocks / PLC data types, and requires --create before creating missing TIA folders or blocks. Supported direct import sources are .scl, .s7dcl, .db, .udt, .xml, .awl, .lad, and .fbd; pass the owning source file instead of .s7res resource sidecars or .meta.json metadata sidecars. By default, import skips unchanged local files, skips local files whose TIA object changed while the local source stayed unchanged, and rejects files changed both locally and in TIA since the last metadata refresh. Pass --overwrite to import when both sides changed, or --overwrite-remote-changes to import when only the TIA object changed. When an import would overwrite an existing project-library type instance or one of its project-library dependencies, it fails by default because plain document/source import detaches that object from its library type; pass --skip-library-instances to leave those library-owned targets unchanged and continue importing the rest, or pass --allow-library-instance-overwrite only for an intentional mutation run. repair-library-dependencies is the safe repair path for that failure class: it recreates the named library instance's project-local dependency objects from the project library. compile, online, offline, snapshot, and download operate on all PLCs unless --plc narrows the scope; snapshot skips safety DBs and DBs without retained members while reporting skip/error data. download compiles first, uses the target configured in the TIA project, reports the selected target in JSON, and falls back to software-only changes when Siemens Openness rejects a full load because of fail-safe data.
Device actions automatically accept non-secret TLS/online authentication modes when TIA exposes them, such as trusted TLS, anonymous user, single sign-on, or no user. If the PLC requires explicit credentials, pass --online-auth-type ProjectUser|GlobalUser|PasswordOnly, --online-user <name> where applicable, and --online-password-env <env> so the password comes from an environment variable instead of the process command line. The bridge also reads PLCCHECK_TIA_ONLINE_USER_TYPE or PLCCHECK_TIA_ONLINE_AUTH_TYPE, PLCCHECK_TIA_ONLINE_USER, and PLCCHECK_TIA_ONLINE_PASSWORD when flags are omitted.
Packaged Windows x64 builds install one stable host at %ProgramFiles%\\plccheck\\tia-openness-bridge\\v1. tia host status|install|upgrade|uninstall manages that bundle. Normal TIA commands automatically upgrade an installed host when the packaged candidate manifest changes, refresh its Siemens AllowList entry, and recover interrupted staging/backup transactions before launch. File and trust changes can request Windows administrator approval through UAC and ensure the invoking Windows user belongs to the local Siemens TIA Openness group. tia trust --json remains the advanced inspection path for an explicitly selected bridge, and PLCCHECK_TIA_BRIDGE remains an unmanaged development/test override.
tia rpc keeps the bridge process, TIA Portal connection, selected project session, and object handles alive for the lifetime of stdin. It speaks newline-delimited JSON-RPC 2.0, performs initialization internally, and exposes bounded object traversal, reflection discovery/invocation, event subscriptions, and audit reads. Startup flags opt into project writes, device actions, private APIs, and tagged filesystem roots. Through RPC, operation.run with action export writes the PLC software and system-constant artifacts, while action export-hardware writes the canonical AML through the active session. Use plccheck tia export hardware when the derived hardware YAML views are also required. See TIA Openness RPC host for the protocol, policy, methods, handle lifecycle, and examples.
Agent-Friendly Usage
For LLM coding agents and search tools, these are the most useful commands:
npx plccheck check ./my-plc-project
npx plccheck test ./my-plc-project
npx plccheck test ./my-plc-project --coverage-json coverage.json --coverage-lcov lcov.info
npx plccheck transpile --to scl ./Program.s7dcl
npx plccheck tia host status --json
npx plccheck tia rpc --filesystem-root exported
npx plccheck tia export software Demo.ap21 --out exported --json
Recommended agent workflow:
- Locate the PLC root containing
.plc.json. - Run
npx plccheck check <plc-root>before changing behavior. - Add or update
.scltestfiles for the target block. - Run
npx plccheck test <plc-root>. - Use
--coverage-jsonwhen coverage or branch visibility matters. - Use
transpile --to sclwhen reviewing S7DCL FBD/LAD exports.
The CLI returns process exit codes that automation can trust: successful checks/tests exit with 0; diagnostics, failing tests, invalid paths, or invalid options exit non-zero.