Skip to content

CLI Tool

The opcsharp CLI tool helps you explore and diagnose OPC UA servers from the command line. It supports endpoint discovery, address space browsing, node value reading, connectivity checks, and code scaffolding.

Quick Reference

CommandDescription
opcsharp discover <endpoint>List server endpoints, security policies, and auth types
opcsharp browse <endpoint>Browse address space as a tree
opcsharp read <endpoint> <nodeIds...>Read node values, display names, and status codes
opcsharp check <endpoint>Step-by-step connectivity diagnostics
opcsharp initGenerate a C# client code snippet

All commands support --json for machine-readable output. The browse, read, and check commands support --username/--password for authenticated servers and --security-policy/--security-mode for explicit security configuration. Credentials can also be set via OPCUA_USERNAME/OPCUA_PASSWORD environment variables or a .env file.

Installation

Install as a .NET global tool:

dotnet tool install --global OpcSharp.Tool

After installation, the tool is available as opcsharp:

opcsharp --help

Requirements

  • .NET 8.0 SDK or later

Update

dotnet tool update --global OpcSharp.Tool

Uninstall

dotnet tool uninstall --global OpcSharp.Tool

Commands

discover — Discover Server Endpoints

Lists all endpoints exposed by an OPC UA server, including their security policies, security modes, and supported authentication types. This command does not require a session — it works even on servers that require credentials.

opcsharp discover <endpoint> [options]

Arguments:

ArgumentDescription
endpointOPC UA server endpoint URL (e.g., opc.tcp://localhost:4840)

Options:

OptionDefaultDescription
--timeout10Connection timeout in seconds
--auto-accepttrueAuto-accept untrusted server certificates
--jsonfalseOutput as JSON instead of a formatted table

Examples:

# Discover endpoints on a local server
opcsharp discover opc.tcp://localhost:4840

# Discover with JSON output
opcsharp discover opc.tcp://192.168.1.100:4840 --json

# Discover with a custom timeout
opcsharp discover opc.tcp://192.168.1.100:4840 --timeout 30

Example output:

Server: My OPC UA Server
URI:    urn:myserver:opcua

┌─────────────────────────────────┬──────────────────┬──────────────────┬────────────────────┐
│ Endpoint URL                    │ Security Policy  │ Security Mode    │ User Tokens        │
├─────────────────────────────────┼──────────────────┼──────────────────┼────────────────────┤
│ opc.tcp://localhost:4840        │ None             │ None             │ Anonymous          │
│ opc.tcp://localhost:4840        │ Basic256Sha256   │ SignAndEncrypt   │ Anonymous, UserName│
└─────────────────────────────────┴──────────────────┴──────────────────┴────────────────────┘

browse — Browse the Address Space

Displays the server’s address space as a tree, starting from a given node. When connecting to a server that requires authentication, provide --username and --password to auto-discover the best secure endpoint.

opcsharp browse <endpoint> [options]

Arguments:

ArgumentDescription
endpointOPC UA server endpoint URL

Options:

OptionDefaultDescription
--nodei=85Starting NodeId (default: Objects folder)
--depth2Maximum browse depth (1–10)
--timeout10Connection timeout in seconds
--auto-accepttrueAuto-accept untrusted server certificates
--usernameUsername for authentication
--passwordPassword for authentication
--security-policySecurity policy (e.g., None, Basic256Sha256, Aes128_Sha256_RsaOaep)
--security-modeSecurity mode: None, Sign, or SignAndEncrypt
--jsonfalseOutput as JSON

Examples:

# Browse the Objects folder (default)
opcsharp browse opc.tcp://localhost:4840

# Browse a specific node with depth 3
opcsharp browse opc.tcp://localhost:4840 --node "i=2253" --depth 3

# Browse a server that requires credentials
opcsharp browse opc.tcp://192.168.1.100:4840 --username myuser --password "mypass"

# Browse with explicit security policy
opcsharp browse opc.tcp://192.168.1.100:4840 --security-policy Basic256Sha256 --security-mode SignAndEncrypt

# Browse with JSON output
opcsharp browse opc.tcp://localhost:4840 --json

Example output:

Objects (i=85) [Object]
├── Server (i=2253) [Object]
│   ├── ServerStatus (i=2256) [Variable]
│   ├── ServiceLevel (i=2267) [Variable]
│   └── Namespaces (i=11715) [Object]
└── PLC1 (ns=4;s=PLC1) [Object]
    └── MAIN (ns=4;s=MAIN) [Object]
        └── counter (ns=4;s=MAIN.counter) [Variable]

read — Read Node Values

Reads the value, display name, status code, and source timestamp for one or more OPC UA nodes.

opcsharp read <endpoint> <nodeIds...> [options]

Arguments:

ArgumentDescription
endpointOPC UA server endpoint URL
nodeIdsOne or more Node IDs to read (e.g., i=2258, "ns=2;s=Temperature")

Options:

OptionDefaultDescription
--timeout10Connection timeout in seconds
--auto-accepttrueAuto-accept untrusted server certificates
--usernameUsername for authentication
--passwordPassword for authentication
--security-policySecurity policy (e.g., None, Basic256Sha256, Aes128_Sha256_RsaOaep)
--security-modeSecurity mode: None, Sign, or SignAndEncrypt
--jsonfalseOutput as JSON

Examples:

# Read the server's current time
opcsharp read opc.tcp://localhost:4840 i=2258

# Read multiple nodes
opcsharp read opc.tcp://localhost:4840 i=2258 i=2259

# Read a namespaced string node with credentials
opcsharp read opc.tcp://192.168.1.100:4840 "ns=4;s=MAIN.counter" --username myuser --password "mypass"

# Read with explicit security policy and credentials
opcsharp read opc.tcp://192.168.1.100:4840 i=2258 --security-policy Basic256Sha256 --username myuser --password "mypass"

# Read with JSON output
opcsharp read opc.tcp://localhost:4840 i=2258 --json

Note: Node IDs containing semicolons (e.g., ns=4;s=MAIN.counter) must be quoted to prevent the shell from interpreting ; as a command separator.

Example output:

┌─────────────────────┬─────────────┬──────────────────────────┬────────────┬──────────────────────────────┐
│ NodeId              │ DisplayName │ Value                    │ StatusCode │ Timestamp                    │
├─────────────────────┼─────────────┼──────────────────────────┼────────────┼──────────────────────────────┤
│ i=2258              │ CurrentTime │ 2026-03-13T14:45:19.959Z │ Good       │ 2026-03-13T14:45:19.9598494Z │
└─────────────────────┴─────────────┴──────────────────────────┴────────────┴──────────────────────────────┘

Supported NodeId formats:

FormatExampleDescription
i=Ni=2258Numeric NodeId in namespace 0
s=Names=MyVarString NodeId in namespace 0
ns=N;i=Mns=2;i=1001Numeric NodeId in namespace N
ns=N;s=Namens=4;s=MAIN.counterString NodeId in namespace N

check — Connectivity Check

Runs a step-by-step connectivity diagnostic against an OPC UA server. Each step is tested independently and reports pass/fail with timing.

opcsharp check <endpoint> [options]

Arguments:

ArgumentDescription
endpointOPC UA server endpoint URL

Options:

OptionDefaultDescription
--timeout30Connection timeout in seconds
--auto-accepttrueAuto-accept untrusted server certificates
--usernameUsername for authentication
--passwordPassword for authentication
--security-policySecurity policy (e.g., None, Basic256Sha256, Aes128_Sha256_RsaOaep)
--security-modeSecurity mode: None, Sign, or SignAndEncrypt
--jsonfalseOutput as JSON

Anonymous check (no credentials, no explicit security) runs these steps:

  1. DNS Resolution
  2. TCP Connection
  3. OPC UA Hello/ACK
  4. OpenSecureChannel
  5. CreateSession
  6. ActivateSession
  7. Read Server Status
  8. Close Connection

Authenticated check (with --username/--password) runs these steps:

  1. DNS Resolution
  2. TCP Connection
  3. Discover Endpoints — finds the best secure endpoint supporting UserName authentication
  4. Secure Connect — connects with the discovered security policy and credentials
  5. Read Server Status
  6. Close Connection

Examples:

# Anonymous connectivity check
opcsharp check opc.tcp://localhost:4840

# Authenticated check against a secured server
opcsharp check opc.tcp://192.168.1.100:4840 --username myuser --password "mypass"

# Check with explicit security policy
opcsharp check opc.tcp://192.168.1.100:4840 --security-policy Basic256Sha256

# Check with extended timeout
opcsharp check opc.tcp://192.168.1.100:4840 --timeout 60

Example output:

Checking opc.tcp://192.168.1.100:4840...

  ✓ DNS Resolution                          12ms
  ✓ TCP Connection                           8ms
  ✓ Discover Endpoints                     156ms
  ✓ Secure Connect                         423ms
  ✓ Read Server Status                      34ms
  ✓ Close Connection                        18ms

All checks passed.

init — Generate Client Code

Generates a C# code snippet for setting up an OpcSharp client. In interactive mode (terminal), it prompts for configuration. In non-interactive mode (piped/scripted), it uses defaults or the provided options.

opcsharp init [options]

Options:

OptionDefaultDescription
--endpointopc.tcp://localhost:4840OPC UA endpoint URL
--security-policyNoneSecurity policy (None, Basic256Sha256, Aes128_Sha256_RsaOaep, Aes256_Sha256_RsaPss)
--security-modeNoneSecurity mode (None, Sign, SignAndEncrypt)
--authAnonymousAuthentication type (Anonymous, Username, Certificate)
--session-nameMyOpcUaClientSession name
--outputWrite generated code to a file instead of stdout
--jsonfalseOutput as JSON

Examples:

# Interactive — prompts for all settings
opcsharp init

# Non-interactive with options
opcsharp init --endpoint opc.tcp://192.168.1.100:4840 --security-policy Basic256Sha256 --security-mode SignAndEncrypt --auth Username

# Save to file
opcsharp init --output MyClient.cs

Security Policy Names

The --security-policy option accepts these short names (case-insensitive):

NameFull URI
Nonehttp://opcfoundation.org/UA/SecurityPolicy#None
Basic128Rsa15http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15
Basic256http://opcfoundation.org/UA/SecurityPolicy#Basic256
Basic256Sha256http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
Aes128_Sha256_RsaOaephttp://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep
Aes256_Sha256_RsaPsshttp://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss
ECC_nistP256http://opcfoundation.org/UA/SecurityPolicy#ECC_nistP256
ECC_nistP384http://opcfoundation.org/UA/SecurityPolicy#ECC_nistP384
ECC_brainpoolP256r1http://opcfoundation.org/UA/SecurityPolicy#ECC_brainpoolP256r1
ECC_brainpoolP384r1http://opcfoundation.org/UA/SecurityPolicy#ECC_brainpoolP384r1
ECC_curve25519http://opcfoundation.org/UA/SecurityPolicy#ECC_curve25519
ECC_curve448http://opcfoundation.org/UA/SecurityPolicy#ECC_curve448

Full URIs are also accepted directly. If --security-policy is set but --security-mode is omitted, the mode defaults to SignAndEncrypt (or None for the None policy).

Use opcsharp discover to see which policies a server supports before connecting.


Global Options

All commands support these shared behaviors:

OptionDescription
--jsonMachine-readable JSON output, suitable for piping to jq or other tools
--helpShow help for any command
# Top-level help
opcsharp --help

# Command-specific help
opcsharp discover --help
opcsharp browse --help

Environment Variables and .env File

Instead of passing --username and --password on every command, you can set them via environment variables or a .env file. This keeps credentials out of your shell history.

Supported variables

VariableDescription
OPCUA_USERNAMEUsername for authentication
OPCUA_PASSWORDPassword for authentication

Precedence

Command-line arguments take priority over environment variables, which take priority over .env file values:

  1. --username / --password (CLI arguments — highest priority)
  2. OPCUA_USERNAME / OPCUA_PASSWORD (environment variables)
  3. Values from .env file in the current directory (lowest priority)

Using a .env file

Create a .env file in your working directory:

# .env
OPCUA_USERNAME=myuser
OPCUA_PASSWORD=mypassword

Then run commands without credential flags:

opcsharp browse opc.tcp://192.168.1.100:4840
opcsharp read opc.tcp://192.168.1.100:4840 "ns=4;s=MAIN.counter"
opcsharp check opc.tcp://192.168.1.100:4840

The .env file supports:

  • Comments starting with #
  • Quoted values ("value" or 'value')
  • Empty lines (ignored)

Warning: Do not commit .env files containing credentials to version control. Add .env to your .gitignore.

Using environment variables

export OPCUA_USERNAME=myuser
export OPCUA_PASSWORD='mypassword'

opcsharp browse opc.tcp://192.168.1.100:4840

Troubleshooting

Connection refused or timeout

Error: Connection refused
  • Verify the server is running and reachable: telnet <host> <port>
  • Check that the port is correct (default OPC UA port is 4840)
  • Ensure no firewall is blocking the connection
  • Try increasing --timeout

Server returned error: 0x80550000

Error: Server returned error: 0x80550000 - Unknown

The server rejected the session because it requires authentication. Use --username and --password:

opcsharp browse opc.tcp://server:4840 --username myuser --password "mypass"

Use discover first to see which authentication types the server supports:

opcsharp discover opc.tcp://server:4840

Bad_LicenseExpired (0x810E0000)

When reading PLC variable values, the server returns an empty value with status 0x810E0000:

┌──────────────┬─────────────┬───────┬────────────┬───────────┐
│ NodeId       │ DisplayName │ Value │ StatusCode │ Timestamp │
├──────────────┼─────────────┼───────┼────────────┼───────────┤
│ ns=4;s=MyVar │ MyVar       │       │ 0x810E0000 │ ...       │
└──────────────┴─────────────┴───────┴────────────┴───────────┘

This means the OPC UA server’s license has expired (e.g., Beckhoff TwinCAT TF6100 license). Standard server attributes like DisplayName still work, but reading PLC variable values requires an active license. Contact your PLC vendor to renew the license.

NodeId with semicolons not parsed correctly

Error: Invalid NodeId format: 'ns=4'

Your shell is splitting the NodeId on the semicolon. Wrap the NodeId in quotes:

# Wrong — shell splits on ;
opcsharp read opc.tcp://server:4840 ns=4;s=MAIN.counter

# Correct — quoted
opcsharp read opc.tcp://server:4840 "ns=4;s=MAIN.counter"

DNS resolution failed

✗ DNS Resolution    0ms
  No such host is known.
  • Verify the hostname is correct and resolvable: nslookup <hostname>
  • Try using the IP address directly instead of a hostname

Certificate trust errors

If you see certificate-related errors, the --auto-accept flag (enabled by default) should handle this. If you’ve explicitly disabled it, you may need to trust the server’s certificate or re-enable auto-accept.

Unsupported variant type

Error: Unsupported variant type: ExtensionObject

The node’s value uses a complex data type (ExtensionObject) that isn’t yet supported by the decoder. Try reading a simpler node, or use the SDK directly with custom type registration. See the Roadmap for planned type support.