free quality report for PLCopenXML exports

Your PLC project compiles. That doesn't mean it works.

PLC Lint reads a PLCopenXML export and finds what the compiler accepts without a word: a timer nobody calls, a setpoint truncated before it is used, a division by a variable that is zero, a branch that can never run. 34 checks, about 10 seconds, no signup.

🔒 You don't have to trust us. The analyzer is open source (MIT) and the local build makes no network calls at all — enforced by a test, not by a promise. Uploaded here, the file is processed in memory and never written to disk. What happens to your code →

Check it here

drag a .xml here or choose a file

No export at hand? It takes half a minute in CODESYS: Project → Export PLCopenXML →

Or run it on your own machine

Your customer's export is their property, and sending it to somebody else's server is rarely your call. So don't: the local build is one .exe — no install, no Python, no network calls at all. Drop an export onto it and the same report appears next to the file.

⬇ Download for Windows

Linux/macOS: python cli.py project.xml · MIT on GitHub

Project in git? uses: caspershes/plc-lint@v1the GitHub Action breaks the build on high-severity findings.

What we check · 34 checks in total

Will stop the controller or send it out of control (13)

Analog input without a plausibility checka broken Pt1000 reaches the controller as a solid 0 °C (profile)
Array index out of boundsreaching the line reads memory that isn't yours
CFC: division by a literal zeroin CFC the block divisor is wired to a literal 0
Channel never written — gap in a channel familydeclared for all four boilers, written for three
Channel parameter fed from another channelpump 1's alarm arrives on pump 2's input
Command depends on its own feedbackstopped → no permission → no command → stopped
Division by a literal zeroliteral /0 and an unguarded divisor variable
Duplicate Modbus address on moduleswhich of the two answers the poll?
Global name typo (gvl.*)references to globals not declared in the GVL
Implicit check does not protecta Check function exists but its guard is gutted
Infinite loop with no exitWHILE TRUE with no exit — the scan stalls
Uncalled timer/triggerTON/TP/R_TRIG read, but the FB is never called
Unreachable IF/ELSIF branchdead ELSIF — the classic heating-curve bug

Quiet defects: it runs, but not as intended (11)

Assignment of a variable to itselfx := x — a typo or lost logic
CASE without an ELSE branch (no default)unhandled selector values
Check present but not activethe check exists but is not registered
Empty IF/loop branchlogic forgotten in an IF or a loop
Integer division (lost fraction?)5/2 yields 2 — the fraction is dropped
Line indexes differently from its groupeleven lines write to their own channel, the twelfth does not
No POUs for implicit checks (runtime guards)the runtime will not intercept a bad index or /0
REAL_TO_TIME(...)*N — setpoint truncationa fractional time setpoint is lost before conversion
REAL_TO_WORD(...)*N — WORD overflow?the product overflows 0..65535
Task watchdog disabledthe task watchdog is switched off
Timer with zero delay (PT := T#0)PT := T#0S — effectively no delay

Style and maintainability (10)

Bloated routine (decomposition candidate)extract the repeated logic into a FUNCTION_BLOCK
Cryptic variable namecryptic single-character names
Dead code — POU is never calledleftovers — or a rename someone forgot to finish
Deep IF nestingdeeply nested IFs
Double `;;` (empty statement)stray ;; and similar litter
Duplicated logic block (copy-paste)structurally duplicated blocks and loops
Magic number — raw constant in coderaw constants in logic, with no name
Name off the PLCopen standardtype prefixes in names (profile)
POU without a single commentnothing explains the logic to the next engineer
Unused local variabledeclared but never used

Every finding comes with suggested fixes and code examples.

Processing happens in memory — the uploaded code is not stored. The tool advises; code changes are up to the engineer (see what the linter can't see). What happens to your code → · Your code & privacy · Industry benchmark · Feedback · GitHub