TIATool

tiax command reference

Generated from the live --help output of every verb. The C# Usage strings are the single source of truth; this file is a projection of them. tiax-v21.exe shares the same sources, so this reference covers both flavours.

Verb Summary
scan Turn an exports folder into AI-readable JSON (no TIA Portal needed)
scl Print a block's logic as SCL (no TIA Portal needed)
query Ask questions about a scanned project (no TIA Portal needed)
report Generate a visual explorer and Markdown docs (no TIA Portal needed)
mcp Serve a project to Claude over MCP (stdio): cache queries + live TIA tools
devices List a project's devices, modules and I/O addresses (needs TIA Portal)
export Export a TIA project's PLC data to SIMATIC ML XML (needs TIA Portal)
build Generate hardware, tags and SCL blocks into a project (WRITES; needs TIA Portal)
compile Compile every PLC and HMI target and save (WRITES; needs TIA Portal)
import-block Import one edited block XML back into a project (WRITES; needs TIA Portal)
hmi Add project languages and import HMI screens (WRITES; needs TIA Portal)
clean-sources Delete leftover external sources + stale XRef cache (WRITES; needs TIA Portal)
engine Persistent TIA session server for tiax-agent (named pipe; internal)
doctor Check TIA Portal, Openness, user group, versions and license
setup Write the MCP server config for Claude Desktop, Cursor and VS Code
pro CAx import, library types, alarm texts, online/download, WinCC Unified (needs TIA Portal)
plcsim PLCSIM Advanced: list/start/stop instances, read/write tags, run test specs
selftest Live selftest on a copy of a scratch project; promotes capabilities on this PC
restore Restore a project from a backup (new folder, or in place with --in-place --confirmed)
openness Browse, read, write and invoke anything in the Openness object model by path (needs TIA Portal)
script Run a compiled TIATool script against a project in an Openness transaction (needs TIA Portal)
project Create, archive (.zapNN) or retrieve a TIA project (needs TIA Portal)
scl-apply Lint, generate and compile one SCL source into a PLC (WRITES; needs TIA Portal)
journal Verify a workspace journal's hash chain, or export it (JSON lines or CSV)

scan

Turn an exports folder into AI-readable JSON (no TIA Portal needed)

tiax scan <exports-folder> [options]

Reads exported SIMATIC ML XML and writes a .tiax/ cache:

  .tiax/project.json   inventory, fidelity roll-up, failure ledger
  .tiax/index.jsonl    one compact line per artifact — read this first
  .tiax/blocks/*.json  full record per artifact, with real SCL for LAD/FBD

Needs no TIA Portal, no Openness licence and no running TIA. It reads a folder
'tiax export' (or TiaTool) already produced, so it is safe to run anywhere.

ARGUMENTS
  <exports-folder>  Folder containing one subfolder per PLC.

OPTIONS
  --out <folder>    Where to write. Default: a '.tiax' folder beside <exports-folder>.
  --quiet           Only print the summary.
  --full            Re-parse every file (default: delta scan, unchanged files reused by content hash).
  --threads <n>     Parser threads (default: all cores).
  --trace           Print full stack traces on failure.

EXIT CODES
  0  every artifact parsed and serialized
  2  output written, but some artifacts failed — see project.json 'failures'
  1  nothing usable produced

EXAMPLE
  tiax scan "C:\Workspaces\MyProject\exports"

scl

Print a block's logic as SCL (no TIA Portal needed)

tiax scl <file.xml | folder> [options]

Converts exported SIMATIC ML to readable SCL and prints it. LAD and FBD are
reconstructed from the wire graph; SCL and STL come through as source text.

ARGUMENTS
  <file.xml|folder>  A single exported block, or a folder to convert recursively.

OPTIONS
  --out <folder>     Write .scl files instead of printing to stdout.
  --author <name>    Stamp AUTHOR on every block instead of carrying the original
                     through. A converted block is new work under new ownership.
  --block-version <v>
                     Stamp VERSION on every block, e.g. 3.0. Without it the block's
                     own version is carried through, and a source that omits VERSION
                     comes back from TIA reset to 0.1.
  --allow-lossy      Exit 0 even when a LAD/FBD rendering is flagged TIAX-LOSSY.
  --trace            Print full stack traces on failure.

EXIT CODES
  0  every file converted and no rendering was flagged lossy
  2  partial: a file failed, or a LAD/FBD network was flagged TIAX-LOSSY
     (the wire graph contains logic the SCL does not show)
  1  nothing converted

NOTE
  For LAD/FBD this output is a RECONSTRUCTION, not source. It is reliable for bit
  logic, timers, counters and comparisons. Verify before trusting it for arithmetic.

EXAMPLES
  tiax scl "exports\PLC_1\Blocks\Pump_01_Ctrl.xml"
  tiax scl "exports" --out "src" --author DEV --block-version 3.0

query

Ask questions about a scanned project (no TIA Portal needed)

tiax query <what> [argument] [options]

Runs against the .tiax cache produced by 'tiax scan'.

WHAT
  writes <symbol>    Every place a tag is WRITTEN — the question PLC work turns on
  reads <symbol>     Every place a tag is read
  tag <symbol>       Both directions
  block <name|id>    The full record for one block
  callers <block>    Which blocks call this one (from CallInfo, not name matching)
  calls <block>      Which blocks this one calls
  unreachable        Code blocks never reached from any OB — dead code
  search <text>      Free-text across names, titles, comments, logic and HMI content
  stats              Inventory and fidelity roll-up

WHAT (HMI — needs a cache scanned with tiax >= 0.2.0)
  screens [filter]   HMI screens/templates/popups, optionally filtered by name
  screen <name>      The full record for one HMI screen
  hmi-map [filter]   Every HMI tag with its table, connection and the screens using it
  hmi-uses <symbol>  Where a PLC symbol appears on the HMI — matched by NAME (the
                     export does not carry the HMI→PLC tag link)

OPTIONS
  --tiax <folder>    Cache location. Default: ./.tiax, or a .tiax beside the given path.
  --exact            Match the symbol exactly instead of by substring.
  --device <name>    (screens) Only this HMI device.
  --json             Emit raw JSON (the default is a readable table).
  --limit <n>        Cap results (default 50).

EXAMPLES
  tiax query writes TankLevel --tiax "C:\Workspaces\MyProject\.tiax"
  tiax query callers FB_AlarmCollectable
  tiax query unreachable
  tiax query screens
  tiax query hmi-uses SystemOn

report

Generate a visual explorer and Markdown docs (no TIA Portal needed)

tiax report [options]

Produces human-readable output from a .tiax cache.

  explorer.html   One self-contained file — double-click to open. Search, block browser,
                  interface trees, SCL with highlighting, call graph, tag tracking, I/O map.
                  No server, no internet, no dependencies.

  docs/           Markdown + Mermaid. Renders in VS Code, GitHub, or any Markdown viewer.
                  One page per block, plus call graph, I/O map, tag cross-reference and
                  dead-code pages. Good for handover and for committing alongside the project.

OPTIONS
  --tiax <folder>   Cache to read. Default: ./.tiax or a .tiax beside the given path.
  --out <folder>    Where to write. Default: alongside the cache.
  --html-only       Skip the Markdown set.
  --md-only         Skip the HTML explorer.
  --open            Open the explorer when done.

EXAMPLES
  tiax report --tiax "C:\tiax-test\.tiax" --out "C:\tiax-test\report" --open
  tiax report --md-only --out docs

mcp

Serve a project to Claude over MCP (stdio): cache queries + live TIA tools

tiax mcp [options]

Runs a Model Context Protocol server over stdio: cache tools answer questions about
your PLC code instantly from the scanned .tiax cache, and live tools drive the real
project (export, compile, build, import) by spawning tiax CLI verbs as child
processes — the server itself never holds TIA Portal open between calls.

OPTIONS
  --tiax <folder>   Cache to serve. Default: ./.tiax or a .tiax beside the given path.

SETUP (Claude Code)
  claude mcp add tia -- "C:\path\to\tiax.exe" mcp --tiax "C:\Workspaces\MyProject\.tiax"

  Or add to your MCP config:
    {
      "mcpServers": {
        "tia": {
          "command": "C:\\path\\to\\tiax.exe",
          "args": ["mcp", "--tiax", "C:\\Workspaces\\MyProject\\.tiax"]
        }
      }
    }

Run 'tiax scan' once before starting the server. After that it can refresh itself:
the refresh_scan tool re-scans the exports folder and reloads the index in place.
Long-running live tools (export, compile, build) may need the client's tool-call
timeout raised (Claude Code: MCP_TOOL_TIMEOUT=600000; MCP_TIMEOUT is only the
server start-up timeout).

TOOLS EXPOSED
  Cache (instant, no TIA Portal):
    project_stats · list_blocks · get_block · who_writes_tag · who_reads_tag
    who_calls · what_block_calls · unreachable_blocks · search_project
    list_screens · get_screen · hmi_tag_map · where_is_tag_used_on_hmi
  Live (drive the real project; write tools always back up first and refuse to
  run while TIA Portal is open — neither rail can be disabled over MCP):
    tia_status · refresh_scan · backup_project · export_project · list_devices
    compile_project · clean_sources · build_from_source · import_block · hmi_import_screens
    hmi_import_tags · add_project_languages

ARGUMENT RAILS
  Every call is checked against the tool's inputSchema before the licence gate and
  before anything runs: undeclared arguments, wrong types and values outside an enum
  are refused, and so is any path, name or target that starts with '-'. dry_run and
  what_if exist only on the tools that honour them. Child processes get --key=value
  arguments on a command line escaped the way Windows splits it.

TRUST CONTROLS
  Policy    %ProgramData%\TIATool\policy.json (admin-owned; /etc/tiatool/policy.json on
            Linux) over <workspace>\policy.json: allow_tools / deny_tools, read_only,
            allow_online (default false: plc_download, plc_online and plc_compare_online
            are refused),
            allow_scripts, allowed_project_roots / allowed_output_roots,
            require_confirmation, max_writes_per_hour, confirm_mode. Checked before the
            licence; tools it denies outright are not listed. tia_status shows it.
            'tiax-agent policy show' prints it with the file behind every value;
            'tiax-agent policy init [--machine | --workspace <dir>] [--allow-online]'
            writes a commented example.
  Approval  plc_download, an in-place restore and whatever require_confirmation lists
            need a person's yes. This server cannot ask the user itself: the result names
            a request the user approves with 'tiax-agent approve <id>', then the same call
            is repeated (tiax-agent asks through the client when the client can).
  Journal   Writes are journaled with the OS user, host, MCP client and approval, in
            a hash chain ('tiax journal verify'). Without a workspace the first write to a
            project creates one under %LOCALAPPDATA%\TIATool\workspaces.
  Project text (comments, titles, HMI texts) comes back fenced as UNTRUSTED PROJECT DATA.

devices

List a project's devices, modules and I/O addresses (needs TIA Portal)

tiax devices <project.apXX> [options]

Opens the project read-only and prints its hardware tree: every device, every plugged
module with its article number, and the I/O address ranges each module occupies.

ARGUMENTS
  <project.apXX>   Target project. Its version must match an installed Openness version.

OPTIONS
  --json           Emit JSON instead of a tree, for scripting.
  --catalog <text> Instead of the tree, list hardware-catalog entries matching <text>,
                   with the firmware versions this TIA release offers for them.
  --hmi-tag <name> Instead of the tree, dump every Openness attribute of one HMI tag.
                   Use this to find out how a link (e.g. to a PLC tag) is represented,
                   since the Simatic ML export only writes a subset of the attributes.
  --attach         Read through the TIA Portal UI that has this project open instead of
                   refusing because a Portal is running (read-only; detaches afterwards,
                   the UI and the project stay open). Headless as usual when no Portal runs.
  --allow-tia-running
                   Proceed even though a TIA Portal process is running. Read-only,
                   but opening a project the UI holds locked still fails or hangs.
  --timeout <min>  Abort if the operation exceeds this many minutes (default 10).
  --trace          Print full stack traces on failure.

WHAT IT DOES
  Opens the project headless, walks Devices -> DeviceItems recursively, and closes.
  Nothing is written to the project.

  TIA Portal must be CLOSED (the project cannot be open in the UI).

EXIT CODES
  0  the tree was printed      1  the project could not be opened or read

EXAMPLE
  tiax devices "...\MyProject.ap21"

export

Export a TIA project's PLC data to SIMATIC ML XML (needs TIA Portal)

tiax export <project.apXX> <output-folder> [options]

Exports all PLC blocks, tag tables, types, watch/force tables and external sources
to SIMATIC ML XML, one file per artifact, grouped per PLC.

ARGUMENTS
  <project.apXX>    TIA Portal project file. Its version must match an installed
                    Openness version — tiax will not upgrade it for you.
  <output-folder>   Destination. Created if missing. Existing files are overwritten.

OPTIONS
  --mirror          Make the destination hold exactly what this run exported: files of
                    blocks, tables and types the project no longer has (deleted or
                    renamed in TIA) are REMOVED and listed as removed. Only files tiax
                    owns are touched — those in the previous .tiax-export.json, and
                    export files inside the PLC/HMI folders this run wrote; never .git,
                    .tiax or anything else. Skipped when the run exported nothing.
                    Default ON when the destination is in a git work tree or holds a
                    .tiax-export.json from an earlier export.
  --no-mirror       Keep stale files (the pre-0.8 behaviour).
  --incremental     Export only what changed since the destination's .tiax-export.json:
                    blocks, tag tables and PLC data types whose Openness ModifiedDate
                    (and interface/code dates) match the manifest and whose file still
                    has the recorded SHA-256 are kept, not exported again; everything
                    new or changed is exported, and the files of objects the project no
                    longer has are removed (mirror semantics, manifest-owned files only).
                    Watch tables, external sources and HMI artifacts carry no dates and
                    are exported every run. Falls back to a full export (and says why)
                    when the manifest is missing or unreadable, describes another project
                    file (another project, or another TIA version) or was written by
                    another TIATool version. Implies --mirror.
  --attach          READ through the TIA Portal UI that has this project open instead of
                    refusing because a Portal is running (read-only: --compile is refused).
                    Without a running Portal the project is opened headless as usual.
  --compile         Compile the project before exporting. This MODIFIES the project
                    (opt-in). Without it the project is left untouched, but blocks
                    TIA considers inconsistent are skipped and listed in the summary.
  --no-compile      Accepted for backward compatibility; this is now the default.
  --keep-volatile   Do not strip volatile timestamps (CreationDate, CompileDate, ...).
                    By default they are blanked so git records semantic changes only.
  --allow-tia-running
                    Proceed even though a TIA Portal process is running. Only for
                    deliberate attach scenarios; you own the coordination then.
  --timeout <min>   Abort if the whole operation exceeds this many minutes (default 30).
  --trace           Print full stack traces on failure.

MANIFEST
  Every run writes <output-folder>\.tiax-export.json: for each exported file its
  type, device, name, sha256 and (blocks, tag tables, PLC data types) the Openness
  ModifiedDate. It is the ownership record --mirror relies on and the baseline
  --incremental compares against, and carries no run timestamp, so re-exporting
  an unchanged project does not change it.

EXIT CODES
  0  every artifact exported (incremental: or kept unchanged)
  2  exported, but at least one artifact failed — see the summary
  1  nothing usable produced

EXAMPLE
  tiax export "C:\Projects\Line_01\Line_01.ap19" "C:\Projects\Line_01\exports"
  tiax export "C:\Projects\Line_01\Line_01.ap19" "C:\Projects\Line_01\exports" --incremental

build

Generate hardware, tags and SCL blocks into a project (WRITES; needs TIA Portal)

tiax build <project.apXX> <source-folder> [options]

Applies a source folder to a project, in this order:
  1. hardware.json  — plug/remove signal modules and set their start addresses
  2. TagTables\*.xml — PLC tag tables (overwritten by name)
  3. HmiTags\*.xml   — HMI tag tables (needs the blocks, so it runs after them)
  4. compile         — every PLC and HMI target

The PLC work is saved before the HMI stage runs, so a failure there cannot roll back
the tag table and the generated blocks.

ARGUMENTS
  <project.apXX>    Target project. Version must match an installed Openness version.
  <source-folder>   Folder holding hardware.json, TagTables\ and .scl files.

OPTIONS
  --plc <name>      The PLC that receives the tag tables, SCL sources and deletes
                    (its name, device item or station). Required when the project
                    has more than one PLC: tiax never picks one, so an unnamed or
                    unknown target fails with AMBIGUOUS_TARGET / NOT_FOUND and the
                    list of candidates, before anything is changed. Also selects the
                    station when hardware.json names none.
  --hmi <name>      The HMI that receives HmiTags\ (same rules as --plc).
  --dry-run         Print what WOULD happen — the SCL files and the block names
                    inside them, the tag tables, the hardware.json plan and the
                    delete list — then exit 0 without starting TIA Portal at all.
                    Costs seconds, opens nothing, modifies nothing. Run it first.
  --no-hardware     Skip step 1.
  --no-hmi-tags     Skip step 3 (HMI tag tables).
  --no-compile      Skip step 4.
  --keep-sources    Keep the external source files 'build' adds (one per .scl).
                    By default they are DELETED right after generation, because
                    leftover sources break TIA's Search and Cross-references.
                    Use 'tiax clean-sources' to clean projects built earlier.
  --delete-blocks <a,b,c>
                    Delete these blocks by name after the SCL sources have been
                    generated. Use it when a restructure leaves the previous
                    program's blocks behind: they are orphans, but they still
                    compile and they still contain assignments to the same
                    outputs, so leaving them is how a project ends up with two
                    programs in it. Names only, never a pattern.
  --delete-types <a,b,c>
                    Delete these PLC data types (UDTs) by name, after the blocks above.
                    A restructure that renames or drops types leaves the old ones behind;
                    they are invisible until one references a constant the new tag table
                    no longer defines, and then the project stops compiling against a type
                    nobody calls. Multi-pass, so orphans that reference each other resolve.
  --messages <n>    How many compiler messages to print (default 60; 0 = all).
                    A restructure produces thousands and the default hides them.
  --no-backup       Skip the automatic zip backup. NOT recommended.
  --backup-dir <d>  Where to write the backup zip (default: beside the project folder).
  --allow-tia-running
                    Proceed even though a TIA Portal process is running. Only for
                    deliberate attach scenarios; you own the coordination then.
  --timeout <min>   Abort if the operation exceeds this many minutes (default 30).
  --trace           Print full stack traces on failure.

hardware.json FORMAT
  {
    "station": "S7-1200 station_1",
    "remove": [ "U21", "U22" ],
    "modules": [
      { "articleNumber": "6ES7222-1BF32-0XB0", "name": "U21",
        "position": 2, "outputStartByte": 2 }
    ]
  }

  "station" may be omitted: the station holding the target PLC is used. A named
  station must exist (no fallback) and must hold the --plc PLC when both are given.

  TIA Portal must be CLOSED (the project cannot be open in the UI).

EXIT CODES
  0  built and compiled clean      2  built, but the compile reported errors
  1  failed (restore the backup)

EXAMPLE
  tiax build "...\MyProject.ap21" "...\PLC Source"
  tiax build "...\Line2.ap19" "...\Line2 Source" --plc PLC_Line2 --hmi HMI_Line2

compile

Compile every PLC and HMI target and save (WRITES; needs TIA Portal)

tiax compile <project.apXX> [options]

Compiles every PLC and HMI target in the project (or only the ones named with
--plc / --hmi), including WinCC Unified panels, prints the compiler's messages,
and saves. The project is saved EITHER WAY — a compile that reports errors still
changes system blocks and timestamps, and pretending otherwise by not saving would
leave the on-disk state half-updated. Exit code 2 is how you learn it was not clean.

ARGUMENTS
  <project.apXX>    Target project. Version must match an installed Openness version.

OPTIONS
  --plc <name>      Compile only this PLC (its name, device item or station).
  --hmi <name>      Compile only this HMI — classic WinCC, or WinCC Unified (compiled
                    through its station, where Openness exposes the compiler).
                    Give both to compile both. With neither, everything is compiled.
                    A name that matches nothing fails with NOT_FOUND and the candidates.
  --block <names>   Compile only these blocks (comma-separated) of one PLC — the --plc
                    one, or the only one. A block the PLC does not have fails with
                    NOT_FOUND before anything is compiled. Not with --hmi.
  --result-json <file>
                    Also write the compile as JSON: counts, targets and every error and
                    warning as {target, block, network, line, severity, text, path,
                    kb_hits[]} (knowledge-base entries matching the text).
  --messages <n>    How many compiler messages to print (default 60; 0 = all).
                    A restructure produces thousands and the default hides them.
  --no-backup       Skip the automatic zip backup. NOT recommended.
  --backup-dir <d>  Where to write the backup zip (default: beside the project folder).
  --allow-tia-running
                    Proceed even though a TIA Portal process is running. Only for
                    deliberate attach scenarios; you own the coordination then.
  --timeout <min>   Abort if the operation exceeds this many minutes (default 30).
  --trace           Print full stack traces on failure.

  TIA Portal must be CLOSED (the project cannot be open in the UI).

EXIT CODES
  0  compiled clean            2  compile reported errors (project saved either way)
  1  failed (restore the backup if in doubt)

EXAMPLE
  tiax compile "...\MyProject.ap21"
  tiax compile "...\TwoLines.ap19" --plc PLC_Line2
  tiax compile "...\TwoLines.ap19" --plc=PLC_Line2 --block=FB_Pump,Main --result-json=compile.json

import-block

Import one edited block XML back into a project (WRITES; needs TIA Portal)

tiax import-block <project.apXX> <block.xml> [options]

Overrides the existing block OR PLC data type (UDT) of the same name, in place, with
the given XML. The surgical writing verb: exactly one named block/type changes, nothing
else. Which tree (Program blocks vs PLC data types) is auto-detected from the XML's
root element, so FB/FC/DB/OB and PlcStruct exports both go through this same verb.
(For bulk generation from SCL sources use 'build'; for HMI content use 'hmi'.)

ARGUMENTS
  <project.apXX>   Target project. Its version must match an installed Openness version.
  <block.xml>      Edited SIMATIC ML block or PLC-data-type export.

OPTIONS
  --plc <name>     The PLC to import into (its name, device item or station). Without
                   it the block/type (or the --sibling-of object) must exist in exactly
                   one PLC: a name found in several PLCs (every PLC has a Main) fails
                   with AMBIGUOUS_TARGET and the list of PLCs, before anything changes.
                   An unknown name fails with NOT_FOUND.
  --sibling-of <name>
                   Import into the group that holds this EXISTING block or type, instead
                   of locating the target by the imported object's own name. Required for
                   anything that does not exist in the project yet -- both a new PLC data
                   type and a new block, e.g. a DB authored as SIMATIC ML because SCL
                   cannot express its exact layout or remanence. Naming a sibling keeps a
                   typo from dropping the object at the tree root.
  --no-backup      Skip the automatic zip backup. NOT recommended.
  --backup-dir <d> Where to write the backup zip (default: beside the project folder).
  --allow-tia-running
                   Proceed even though a TIA Portal process is running. Only for
                   deliberate attach scenarios; you own the coordination then.
  --timeout <min>  Abort if the operation exceeds this many minutes (default 20).
  --trace          Print full stack traces on failure.

WHAT IT DOES
  1. Zips the whole project folder to a timestamped backup (unless --no-backup).
  2. Opens the project headless, finds the group holding the block/type, imports with
     Override inside a transaction, saves, and closes.

  TIA Portal must be CLOSED (the project cannot be open in the UI).

EXIT CODES
  0  imported and saved      1  failed (project unchanged if it failed before save; else restore the backup)

EXAMPLE
  tiax import-block "...\OtherProject.ap19" "...\IDB_ModbusServer.xml"
  tiax import-block "...\OtherProject.ap19" "...\UDT_DriveDiag.xml" --sibling-of UDT_Modbus_PumpControl
  tiax import-block "...\TwoLines.ap19" "...\Main.xml" --plc PLC_Line2

hmi

Add project languages and import HMI screens (WRITES; needs TIA Portal)

tiax hmi <project.apXX> [options]

With no options it just reports the project's active languages and the HMI targets it
found — a safe way to check the tool can see the panel before writing anything.

ARGUMENTS
  <project.apXX>    Target project. Version must match an installed Openness version.

OPTIONS
  --hmi <name>       The HMI that receives --screens / --tag-files / --tags (its name,
                     device item or station). Required when the project has more than
                     one HMI: tiax never picks one — screens used to be imported into
                     EVERY panel — so an unnamed or unknown target fails with
                     AMBIGUOUS_TARGET / NOT_FOUND and the candidates, before anything
                     is changed. Languages are project-wide and need no target.
  --languages <a,b>  Add these cultures to the project's active languages, e.g.
                     "de-DE,en-US". Only adds; never removes, because removing a
                     language discards every text in it.
  --screens <folder> Import every *.xml in <folder> as a screen, overwriting by name.
  --tag-files <dir>  Import HMI tags ONE PER FILE. Layout is
                     <dir>\<TagTableName>\<TagName>.xml — the subfolder names the
                     table, which must already exist. Each tag is overwritten by
                     name; every other tag in the table is untouched. This is the
                     safe way to add tags, and the only one that has worked.
  --tags <folder>    Import every *.xml in <folder> as a whole HMI tag table.
                     AVOID. A table is replaced wholesale, the exported form of a
                     table does not carry each tag's PLC link, and a table document
                     containing <ControllerTag> was observed to hang TIA Portal
                     indefinitely. Use --tag-files instead.
  --no-compile       Skip the compile at the end.
  --no-backup        Skip the automatic zip backup. NOT recommended.
  --backup-dir <d>   Where to write the backup zip (default: beside the project folder).
  --allow-tia-running
                     Proceed even though a TIA Portal process is running. Only for
                     deliberate attach scenarios; you own the coordination then.
  --timeout <min>    Abort if the operation exceeds this many minutes (default 30).
  --trace            Print full stack traces on failure.

ORDER MATTERS
  A screen carries its tag bindings, but not the tags themselves. Importing a screen
  that binds a tag which does not exist yet leaves a dangling reference that only
  surfaces at compile time. Create the tags in TIA first, then import the screens.

  TIA Portal must be CLOSED (the project cannot be open in the UI).

EXIT CODES
  0  done and compiled clean      2  done, but the compile reported errors
  1  failed

EXAMPLE
  tiax hmi "...\MyProject.ap21" --languages "de-DE,en-US"
  tiax hmi "...\TwoLines.ap19" --hmi HMI_Line2 --screens "...\Screens"

clean-sources

Delete leftover external sources + stale XRef cache (WRITES; needs TIA Portal)

tiax clean-sources <project.apXX> [options]

Deletes the external source files in every PLC's 'External source files' folder,
saves and closes the project, then deletes <project>\XRef\XRef.db so TIA Portal
rebuilds its cross-reference index on the next open. Leftover sources (one per
.scl from every 'tiax build') break project-wide Search and Cross-references.

OPTIONS
  --only <a,b,c>    Delete only these sources (names, case-insensitive).
  --dry-run         List what would be deleted; modify nothing.
  --keep-xref       Do not delete XRef\XRef.db.
  --no-backup       Skip the automatic zip backup. NOT recommended.
  --backup-dir <d>  Where to write the backup zip.
  --allow-tia-running
                    Proceed although a TIA Portal process is running.
  --timeout <min>   Abort after this many minutes (default 30).

EXIT CODES
  0  cleaned (or nothing to clean)   2  sources deleted but XRef cache could not be removed
  1  failed (restore the backup)

EXAMPLE
  tiax clean-sources "...\MyProject.ap21" --dry-run

engine

Persistent TIA session server for tiax-agent (named pipe; internal)

tiax engine [options]

Runs a persistent TIA Portal session and serves tiax verbs over a named pipe to
tiax-agent. Normally started by the agent, not by hand.

OPTIONS
  --pipe <name>        Pipe name (default tiax-engine-<flavour>-<user>).
  --idle-minutes <n>   Close project + Portal after n idle minutes (default 15).
  --parent-pid <pid>   Exit when this process exits (the agent).
  --oneshot            Do not keep TIA open: every call opens and closes (debug/fallback).

ENVIRONMENT
  TIAX_ENGINE_SECRET   Shared secret the client must present in its hello message.

doctor

Check TIA Portal, Openness, user group, versions and license

tiax doctor

Checks everything tiax needs on this PC: Windows x64, .NET Framework 4.8, installed
TIA Portal Openness versions (V19/V21), membership of the 'Siemens TIA Openness'
group, running Portal processes, the tiax flavours and the license.

EXIT CODES
  0  all good   2  warnings   1  at least one blocking problem

setup

Write the MCP server config for Claude Desktop, Cursor and VS Code

tiax setup --tiax <cache-folder> [options]

Adds (or updates) a 'tiatool' MCP server entry in the configuration of Claude
Desktop, Cursor and VS Code. Other servers are preserved; the old file is kept
as *.bak. Uses tiax-agent.exe when it is installed beside tiax, else 'tiax mcp'.

OPTIONS
  --tiax <folder>     The scanned .tiax cache to serve (required).
  --client <list>     claude,cursor,vscode (default: all three).
  --http <url>        Point Cursor/VS Code at the agent's HTTP endpoint instead of stdio,
                      e.g. http://127.0.0.1:8765/mcp (needs --token).
  --token <token>     Bearer token for --http (see 'tiax-agent token').
  --name <name>       Server name (default tiatool).
  --dry-run           Show what would change; write nothing.

pro

CAx import, library types, alarm texts, online/download, WinCC Unified (needs TIA Portal)

tiax pro <action> <project.apXX> [options]

ACTIONS
  cax-import          --aml <file> [--mode parking|retain|overwrite]   Hardware from AutomationML (WRITES)
  library-list        [--global <lib.alXX>]                            List library types + versions
  library-use         --type <path> [--plc <name>] [--global <lib>] [--version <x.y>] [--update]
                                                                       Instantiate a type, or update instances (WRITES)
  alarm-texts-export  --xlsx <file> [--plc <name>]                     PLC alarm text lists to XLSX
  alarm-texts-import  --xlsx <file> [--plc <name>]                     XLSX into the PLC (WRITES)
  online-state        [--plc <name>]                                   Online state + PC interfaces
  online-compare      [--plc <name>] [--interface <PC interface>] [--interface-number 1]
                                                                       Offline vs online differences (Labs;
                                                                       read-only, goes online, never downloads)
  download            --plc <name> --interface <PC interface> [--interface-number 1] [--ip <addr>]
                      [--hardware] [--no-software] [--allow-stop] [--allow-reinit] [--no-start] --confirmed
                                                                       Download to a PLC or PLCSIM (ONLINE)
  unified-build       --spec <file.json> [--what-if]                   Screens/items/bindings/alarms (WRITES)

COMMON OPTIONS
  --allow-tia-running  Proceed although a TIA Portal UI is running.
  --no-backup          Skip the automatic backup (CLI only; MCP never passes it).
  --timeout <min>      Default 30.

SAFETY
  Every WRITES action backs the project up first and saves only when the action succeeded.
  download never runs without --confirmed, answers only the TIA prompts you allowed
  (--allow-stop; --allow-reinit for a download that re-initialises data blocks or has to
  download ALL blocks, which resets their actual values to the start values), and cancels
  on anything else (passwords, system data, firmware, reset).

plcsim

PLCSIM Advanced: list/start/stop instances, read/write tags, run test specs

tiax plcsim <action> [options]

ACTIONS
  list                                List registered instances.
  start  --instance <name>            Register (if new), power on and RUN.
  stop   --instance <name> [--power-off]
  read   --instance <name> --tags "a,b,c"
  write  --instance <name> --set '{"tag": value, ...}'
  test   --instance <name> --spec <file.json>   Run cases: set inputs, wait, assert outputs.
                                     Exit 0 all passed, 2 failures.

Tag names are symbolic, as PLCSIM lists them: PLC tags by name, DB members as "DB".member.
Requires S7-PLCSIM Advanced V4+ (the API DLL is located from the registry).

selftest

Live selftest on a copy of a scratch project; promotes capabilities on this PC

tiax selftest --live --template <scratch.apXX> [options]

Copies the template project to a short scratch path and runs, step by step: doctor, devices,
backup + verify, export, scan, generate equipment, build (dry run, real), compile,
re-export + verify_change, import-block round trip, clean-sources, project languages,
read-only/what-if pro actions, CAx import (--include-risky), PLCSIM (if installed),
restore, every built-in template, and the 0.8 steps: incremental export (a second run
changes nothing), project create/archive/retrieve, Openness explorer browse/get, C#
scripts (read mode rolls back, write mode commits), every built-in script extension
compiled against this PC's Openness DLLs with the read-only ones run, and scl_lint +
scl_apply of a tiny FC + compile of that block. Steps 21-22 need tiax-agent beside tiax
and a licence for their write half. The template itself is never modified. Use a
throwaway project with exactly one PLC.

OPTIONS
  --live               Required: the selftest opens TIA Portal and writes the scratch copy.
  --template <apXX>    Scratch project (V19 .ap19 or V21 .ap21; flavour follows the extension).
  --work <dir>         Short working root (default <system drive>\tiaxst).
  --report <file>      Also write the report here (default selftest-report.json).
  --include-risky      Run step 14 (CAx import) — needs --aml <file>.
  --aml <file>         AutomationML file for step 14.

OUTPUT
  The report (schema tiatool.selftest/1) is also stored as
  %LOCALAPPDATA%\TIATool\selftest\latest-<flavour>.json; tiax-agent overlays it on the
  capability registry (selftest_verified / REGRESSION). Then:
  python tools\capabilities.py apply selftest-report.json

EXIT CODES
  0 all steps passed or skipped · 2 at least one step failed · 64 usage

restore

Restore a project from a backup (new folder, or in place with --in-place --confirmed)

tiax restore <project.apXX> [options]

Restores from one of the timestamped restore points every write takes
(<name>_tiax_backup_<yyyyMMdd-HHmmss>.zip beside the project folder).

OPTIONS
  --list               List the restore points and exit.
  --backup <zip>       Restore point to use (default: the newest).
  --in-place           Replace the project folder. Takes a pre-restore backup first and keeps the
                       current folder as <folder>.replaced-<time> (never deleted). Needs --confirmed.
  --confirmed          Required with --in-place.
  --allow-tia-running  Proceed although a TIA Portal UI is running (not recommended).

Without --in-place the backup is extracted to <folder>_restored_<time> beside the project and
nothing else is touched.

EXIT CODES  0 ok · 1 failed (the project is unchanged; in place: rolled back) · 64 usage

openness

Browse, read, write and invoke anything in the Openness object model by path (needs TIA Portal)

tiax openness <project.apXX> <browse|get|set|invoke> --path=<path> [options]

Reaches every object Openness exposes through one path syntax, using the Openness
reflection API (attributes, compositions, actions) plus typed .NET properties.

ACTIONS
  browse   Type, attributes (values of simple types), compositions (count + first 50
           child names and paths), links and actions with parameter types. Read-only.
  get      One attribute value (--name, or end the path with @Attribute). Read-only.
  set      Write one attribute: --name=<attribute> --value-json=<json>. WRITES.
  invoke   Run one Openness action: --name=<action> [--args-json=<json array|object>].
           WRITES, except GetAttributes (reads several attributes; args = array of names).

PATHS (from the Project; segments separated by '/'; positions are 0-based)
  Devices["PLC_1"]/DeviceItems[0]/DeviceItems["PLC_1"]
  plc:PLC_1/BlockGroup/Blocks["Main"]                 plc: = the PlcSoftware of that PLC
  plc:PLC_1/TagTableGroup/TagTables["Default tag table"]/Tags["Start"]@LogicalAddress
  hmi:HMI_1/...                                         hmi: = that HMI's software
  plc: (no name) is the only PLC. Names may use 'single' quotes; \" \' \\ escape.
  A path ending in a composition (e.g. .../Blocks) lists its items.

OPTIONS
  --path=<path>          Object path (empty = the Project).
  --name=<name>          Attribute (get/set) or action (invoke).
  --value-json=<json>    set: the new value as JSON. Enums by NAME ("Sequential"),
                         numbers, true/false, strings, or {"path": "<object path>"}.
  --args-json=<json>     invoke: [positional] or {"parameterName": value}.
  --depth=<0-3>          browse: 0 = counts only, 1 = child names (default), 2-3 = nested.
  --result-file=<file>   Also write the JSON result to this file.
  --allow-tia-running    Proceed although a TIA Portal UI is running.
  --no-backup            set/invoke: skip the automatic backup (CLI only; MCP never passes it).
  --backup-dir=<dir>     Where the backup goes (default: beside the project folder).
  --timeout=<min>        Default 10.

SAFETY
  set and invoke take a timestamped backup first and save only when Openness accepted the
  change. If Openness throws during the change the project is NOT saved (the engine session
  is discarded). A request refused before any change (unknown path, attribute, action or a
  value that does not convert) exits 64 and touches nothing. There is no --dry-run: browse
  and get are already read-only, and the MCP tools plan + confirm before set/invoke.

EXIT CODES
  0  done      1  Openness failed (nothing saved)      64  refused before any change

EXAMPLES
  tiax openness "...\MyProject.ap19" browse --path=plc:PLC_1/BlockGroup --depth=2
  tiax openness "...\MyProject.ap19" get --path=plc:PLC_1/BlockGroup/Blocks['Main']@ProgrammingLanguage
  tiax openness "...\MyProject.ap19" set --path=plc:PLC_1/BlockGroup/Blocks['Main'] --name=AutoNumber --value-json=false

script

Run a compiled TIATool script against a project in an Openness transaction (needs TIA Portal)

tiax script <project.apXX> --assembly=<script.dll> --result-file=<result.json> [options]

Runs a script assembly built by tiax-agent (MCP script_run / extension_run) against the
project. The script is C# with a public static class Script { public static object
Run(ScriptContext ctx) }, compiled for this Openness version. You normally do not call
this verb yourself: the MCP tools compile the script, check it against the guard rail,
and ask for confirmation before a write.

ARGUMENTS
  <project.apXX>        Target project. Its version must match an installed Openness version.

OPTIONS
  --assembly=<dll>      The compiled script (required).
  --result-file=<json>  Where the result is written (tiatool.script-result/1; required).
  --mode=read|write     read (default): runs inside an Openness transaction that is NEVER
                        committed, and the project is never saved. write: needs a licence,
                        takes a backup first, commits only when Run returned without an
                        exception, then saves. There is no --dry-run: read mode is the way
                        to try a script.
  --args-file=<json>    JSON object handed to the script as ctx.Args.
  --no-transaction      Run without ExclusiveAccess/Transaction, for Openness calls that are
                        not allowed inside a transaction (for example compiling; check the
                        Openness manual's transaction restrictions). Read mode then closes the
                        project without saving afterwards, because nothing can be rolled back;
                        write mode still takes the backup, and a failure is never saved.
  --timeout=<min>       Abort after this many minutes (default 10 read, 30 write; max 240).
                        ctx.Cancellation fires at 90% of it.
  --backup-dir=<dir>    Where the write-mode backup zip goes (default: beside the project folder).
  --allow-tia-running   Proceed although a TIA Portal UI is running (CLI only; MCP never passes it).

EXIT CODES
  0  the script ran (write: committed and saved)
  2  the script threw; the result file has the error and log; nothing was committed or saved
  1  fatal: project, transaction or save failed (the result file says why when it could be written)
 64  bad arguments

project

Create, archive (.zapNN) or retrieve a TIA project (needs TIA Portal)

tiax project create   <folder\Name\Name.apNN> [options]
tiax project archive  <project.apNN> --out=<file.zapNN> [options]
tiax project retrieve <archive.zapNN> --out-dir=<new folder> [options]

ACTIONS
  create     A new, empty project (Projects.Create). TIA keeps a project in a folder
             of its own name, so the path is <folder>\<Name>\<Name>.apNN, and the
             extension picks the TIA version (.ap19 = V19). The <Name> folder must not
             exist yet. Needs a licence (it writes a project).
  archive    A compressed archive of the project (Project.Archive, Compressed). The
             project is only read. The archive must be a NEW file of the project's own
             version (.zap19 for a .ap19), outside the project folder. Free.
  retrieve   Unpacks an archive (Projects.Retrieve) into a NEW folder — missing or
             empty — and prints the project file found there. Nothing that exists is
             ever written over. Free.

OPTIONS
  --out=<file.zapNN>   archive: the archive file to write.
  --out-dir=<folder>   retrieve: the folder to unpack into.
  --allow-tia-running  Proceed although a TIA Portal UI is running (CLI only).
  --timeout <min>      Abort after this many minutes (default 30).
  --trace              Print full stack traces on failure.

  TIA Portal must be CLOSED. Openness opens only projects of its own version; an
  archive or project of another version is refused, never upgraded.

EXIT CODES
  0  done      1  failed      64  bad arguments or a target that exists (nothing done)

EXAMPLES
  tiax project create  "C:\Projects\Line2\Line2.ap19"
  tiax project archive "C:\Projects\Line1\Line1.ap19" --out="D:\Archive\Line1_2026-10-13.zap19"
  tiax project retrieve "D:\Archive\Line1_2026-10-13.zap19" --out-dir="C:\Projects\Line1_restored"

scl-apply

Lint, generate and compile one SCL source into a PLC (WRITES; needs TIA Portal)

tiax scl-apply <project.apXX> <source.scl> [options]

Applies an SCL source (any mix of FUNCTION_BLOCK, FUNCTION, DATA_BLOCK, TYPE and
ORGANIZATION_BLOCK) to ONE PLC:
  1. lint (the checks of 'scl_lint': unbalanced blocks, a three-part VERSION that
     generates an EMPTY block, global constants as CASE labels, undeclared #symbols,
     unquoted names with spaces, empty statements). Errors stop the run; warnings
     stop it too unless --accept-warnings. Nothing has been touched at that point.
  2. backup (timestamped zip beside the project folder)
  3. generate the blocks through a temporary external source, which is deleted
     again afterwards — no leftover source breaks TIA's Search / Cross-references
  4. compile that PLC (only that PLC), then save. Blocks that already existed are
     updated where they are; with --group, NEW blocks move into that block group.

OPTIONS
  --plc <name>          The PLC (name, device item or station). Needed when the project
                        has several; an unknown or ambiguous name changes nothing.
  --group <A/B>         Block group for NEW blocks (created when missing). Openness has no
                        move: a block is exported and re-imported into the group inside a
                        transaction, which TIA allows only for a block that compiles; the
                        PLC is then compiled again.
  --no-compile          Generate only (the blocks stay uncompiled). Not with --group.
  --accept-warnings     Apply although the lint reported warnings.
  --result-json <file>  Also write the result as JSON: lint findings, generated / new /
                        updated blocks, and compiler messages {target, block, network, line,
                        severity, text, path, kb_hits[]}.
  --no-backup           Skip the automatic backup (CLI only). NOT recommended.
  --backup-dir <d>      Where to write the backup zip (default: beside the project folder).
  --allow-tia-running   Proceed although a TIA Portal UI is running (CLI only).
  --timeout <min>       Abort after this many minutes (default 30).
  --trace               Print full stack traces on failure.

EXIT CODES
  0  applied and compiled clean
  2  applied, but the compile reported errors (saved; the backup is the way back)
  1  failed — the project was NOT saved
  64 refused by the lint or by bad arguments — nothing was touched

EXAMPLE
  tiax scl-apply "C:\Projects\Line1\Line1.ap19" FB_Pump.scl --plc=PLC_1 --group=Equipment

journal

Verify a workspace journal's hash chain, or export it (JSON lines or CSV)

tiax journal verify [where] [--json]
tiax journal export [where] [--csv] [--out <file>]

The MCP servers journal every project write (journal.jsonl in the workspace; without a
configured workspace, in the project's implicit workspace under %LOCALAPPDATA%\TIATool\
workspaces), plus policy refusals and approval requests. Each line records who acted
(OS user, host, MCP client), the approval a write carried, and prev_hash: the SHA-256
of the line before it. Editing, inserting or deleting a line breaks that chain.

WHERE (default: the workspace containing the current folder)
  --workspace <dir>      A workspace folder (or a folder inside one).
  --project <file.apXX>  The implicit workspace of that project.
  --journal <file>       A journal.jsonl file directly.

verify
  Checks every line: valid JSON, seq one more than the line before, prev_hash equal to
  the hash of the line before. Lines written before 0.8 carry no hash; the chain starts
  at the first hashed line. Prints the head hash: record it elsewhere (a ticket, an
  e-mail) to detect a journal that was cut short later — the chain alone cannot.
  --json                 The result as JSON.

export
  Writes the journal as JSON lines (default) or --csv (one row per entry; columns seq,
  at, kind, tool, ok, task, verdict, os_user, host, mcp_client, approval, approver,
  backup, prev_hash, data). Cells a spreadsheet would read as a formula are prefixed
  with an apostrophe.
  --out <file>           Write to a file instead of standard output.

EXIT CODES  0 ok (verify: chain intact) · 1 no journal · 2 verify found problems · 64 usage

Built from docs/tiax-reference.md in the product repository. Links to files that are not published here are shown as plain text.