CLI Tool
CLI Tool
Overview
opcua-cli is a standalone command-line tool for exploring OPC UA servers without writing code. Useful for debugging on-site, verifying connectivity, and inspecting the address space.
Zero additional dependencies — uses the same pure PHP OPC UA client under the hood.
Installation
composer require php-opcua/opcua-cliAfter installation, the CLI tool is available at:
opcua-cliCommands
browse — Browse the address space
# Browse the Objects folder (default)
opcua-cli browse opc.tcp://localhost:4840
# Browse a specific path
opcua-cli browse opc.tcp://localhost:4840 /Objects/MyPLC
# Browse a specific NodeId
opcua-cli browse opc.tcp://localhost:4840 "ns=2;i=1000"
# Recursive browse with depth limit
opcua-cli browse opc.tcp://localhost:4840 /Objects --recursive --depth=3
# JSON output
opcua-cli browse opc.tcp://localhost:4840 /Objects --jsonOutput:
├── Server (i=2253) [Object]
├── MyPLC (ns=2;i=1000) [Object]
│ ├── Temperature (ns=2;i=1001) [Variable]
│ └── Pressure (ns=2;i=1002) [Variable]
└── DeviceSet (ns=3;i=5001) [Object]Options:
| Option | Description |
|---|---|
--recursive |
Browse recursively (tree view) |
--depth=N |
Maximum depth for recursive browse (default: 3) |
read — Read a node value
# Read the Value attribute (default)
opcua-cli read opc.tcp://localhost:4840 "i=2259"
# Read a specific attribute
opcua-cli read opc.tcp://localhost:4840 "ns=2;i=1001" --attribute=DisplayName
# JSON output
opcua-cli read opc.tcp://localhost:4840 "ns=2;i=1001" --jsonOutput:
NodeId: ns=2;i=1001
Attribute: Value
Value: 23.5
Type: Double
Status: Good (0x00000000)
Source: 2026-03-24T15:30:00+00:00
Server: 2026-03-24T15:30:00+00:00Options:
| Option | Description |
|---|---|
--attribute=NAME |
Attribute to read: Value (default), DisplayName, BrowseName, DataType, NodeClass, Description, AccessLevel, NodeId |
write — Write a value to a node
# Auto-detect type (reads the node first)
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=1001" 42
# Explicit type
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=1001" 42 --type=Int32
# Write a boolean
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=2000" true --type=Boolean
# JSON output
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=1001" 42 --jsonOutput:
NodeId: ns=2;i=1001
Value: 42
Type: Int32
Status: Good (0x00000000)Options:
| Option | Description |
|---|---|
--type=TYPE |
Explicit OPC UA type. If omitted, auto-detected from the node. Valid types: Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float, Double, String |
Value casting: When --type is specified, the value is cast accordingly ("true" → bool, "42" → int, "3.14" → float). Without --type, the CLI infers from the string format.
endpoints — Discover server endpoints
opcua-cli endpoints opc.tcp://localhost:4840
opcua-cli endpoints opc.tcp://localhost:4840 --jsonOutput:
Endpoint: opc.tcp://localhost:4840
Security: None (mode: None)
Auth: Anonymous, UserName
Endpoint: opc.tcp://localhost:4840
Security: Basic256Sha256 (mode: SignAndEncrypt)
Auth: Anonymous, UserName, Certificatewatch — Watch a value in real time
Two modes:
- Without
--interval(default): uses OPC UA subscriptions. The server notifies only when the value changes — efficient, no unnecessary polling. - With
--interval=N: manual polling withread()every N milliseconds. Useful for servers that don't support subscriptions or for debugging.
# Subscription mode (default)
opcua-cli watch opc.tcp://localhost:4840 "ns=2;i=1001"
# Polling mode — read every 250ms
opcua-cli watch opc.tcp://localhost:4840 "ns=2;i=1001" --interval=250
# JSON output
opcua-cli watch opc.tcp://localhost:4840 "ns=2;i=1001" --jsonOutput:
[15:30:00.123] 23.5
[15:30:00.625] 23.6
[15:30:01.127] 23.4
^CStop with Ctrl+C.
generate:nodeset — Generate PHP classes from NodeSet2.xml
# Generate with default output
opcua-cli generate:nodeset path/to/Opc.Ua.Di.NodeSet2.xml
# Specify output directory and namespace
opcua-cli generate:nodeset path/to/Opc.Ua.Di.NodeSet2.xml \
--output=src/Generated/Di/ --namespace=App\\OpcUa\\DiOutput:
Generated: src/Generated/Di/DiNodeIds.php
Generated: src/Generated/Di/Codecs/DeviceTypeCodec.php
Generated: src/Generated/Di/DiRegistrar.php
Done. 3 file(s) generated in src/Generated/Di/Generates three types of files:
- NodeId constants — one class with all node IDs as string constants
- Codec classes — one per structured DataType, implementing
ExtensionObjectCodec - Registrar — a class with
register(ExtensionObjectRepository)to batch-register all codecs
Options:
| Option | Description |
|---|---|
--output=PATH |
Output directory (default: ./generated/) |
--namespace=NS |
PHP namespace for generated classes (default: Generated\\OpcUa) |
No server connection required — reads the XML file locally.
dump:nodeset — Export server address space to NodeSet2.xml
# Dump all non-zero namespaces
opcua-cli dump:nodeset opc.tcp://192.168.1.100:4840 --output=MyPLC.NodeSet2.xml
# Dump only namespace 2
opcua-cli dump:nodeset opc.tcp://192.168.1.100:4840 --output=MyPLC.NodeSet2.xml --namespace=2
# With security
opcua-cli dump:nodeset opc.tcp://192.168.1.100:4840 --output=MyPLC.NodeSet2.xml \
-s Basic256Sha256 -m SignAndEncrypt --cert=client.pem --key=client.keyOutput:
Namespace URIs:
[0] http://opcfoundation.org/UA/
[1] urn:myplc:opcua:server
Browsing address space...
Found 12 top-level nodes
Collecting nodes and reading attributes...
Collected 87 nodes
Building XML...
Written: MyPLC.NodeSet2.xml
Done. 87 nodes exported.The exported file can be fed directly to generate:nodeset:
opcua-cli generate:nodeset MyPLC.NodeSet2.xml --output=src/Generated/MyPLC/Options:
| Option | Description |
|---|---|
--output=FILE |
Output XML file path (required) |
--namespace=N |
Export only this namespace index (default: all non-zero) |
WARNING: Always prefer the manufacturer's NodeSet2.xml file over a runtime dump.
The
dump:nodesetcommand reconstructs the address space by browsing and reading attributes at runtime. This works well for NodeId constants and enumerations, but structured DataType definitions may be incomplete or missing depending on the server's OPC UA version and capabilities. Servers that do not support theDataTypeDefinitionattribute (OPC UA < 1.04) will produce DataType nodes without<Definition>fields — meaning no DTOs or codecs can be generated for those types.Use this command only when the device manufacturer does not provide a NodeSet2.xml file. If one is available (from the vendor documentation, the OPC Foundation repository, or the
opcua-client-nodesetpackage), always usegenerate:nodesetdirectly on that file instead.This command is not required and not mandatory for using the library. It is a convenience tool for situations where no other source of type information is available.
Security Options
All commands support full security configuration:
# Username/password authentication
opcua-cli read opc.tcp://server:4840 "i=2259" -u admin -p secret
# Full security with RSA certificates
opcua-cli read opc.tcp://server:4840 "i=2259" \
--security-policy=Basic256Sha256 \
--security-mode=SignAndEncrypt \
--cert=/path/to/client.pem \
--key=/path/to/client.key \
--ca=/path/to/ca.pem \
-u operator -p secret
# ECC security (auto-generated ECC certificate)
opcua-cli read opc.tcp://server:4840 "i=2259" \
--security-policy=ECC_nistP256 \
--security-mode=SignAndEncrypt \
-u operator -p secretECC disclaimer: ECC security policies (
ECC_nistP256,ECC_nistP384,ECC_brainpoolP256r1,ECC_brainpoolP384r1) are fully implemented and tested against the OPC Foundation's UA-.NETStandard reference stack. However, no commercial OPC UA vendor supports ECC endpoints yet. When using ECC, client certificates are auto-generated if--cert/--keyare omitted, and username/password authentication uses theEccEncryptedSecretprotocol automatically.
| Option | Short | Description |
|---|---|---|
--security-policy=<policy> |
-s |
None, Basic128Rsa15, Basic256, Basic256Sha256, Aes128Sha256RsaOaep, Aes256Sha256RsaPss, ECC_nistP256, ECC_nistP384, ECC_brainpoolP256r1, ECC_brainpoolP384r1 |
--security-mode=<mode> |
-m |
None, Sign, SignAndEncrypt |
--cert=<path> |
Client certificate path | |
--key=<path> |
Client private key path | |
--ca=<path> |
CA certificate path | |
--username=<user> |
-u |
Username for authentication |
--password=<pass> |
-p |
Password for authentication |
--timeout=<seconds> |
-t |
Connection timeout (default: 5) |
Output Options
JSON
Add --json (or -j) to any command for machine-readable output. Works with jq and shell scripts:
# Browse and extract node names
opcua-cli browse opc.tcp://localhost:4840 --json | jq '.[].name'
# Read a value
opcua-cli read opc.tcp://localhost:4840 "i=2259" --json | jq '.Value'Debug Logging
Three debug modes:
# Log to stdout (incompatible with --json)
opcua-cli read opc.tcp://localhost:4840 "i=2259" --debug
# Log to stderr (compatible with --json)
opcua-cli read opc.tcp://localhost:4840 "i=2259" --debug-stderr --json
# Log to file (compatible with --json)
opcua-cli read opc.tcp://localhost:4840 "i=2259" --debug-file=/tmp/opcua.log --jsonDebug output shows PSR-3 log messages: handshake, secure channel, session, retries, errors.
Global Options
| Option | Short | Description |
|---|---|---|
--json |
-j |
Output in JSON format |
--debug |
-d |
Debug logging on stdout |
--debug-stderr |
Debug logging on stderr | |
--debug-file=<path> |
Debug logging to file | |
--help |
-h |
Show help |
--version |
-v |
Show version |