Files
scadalink-design/src/ScadaLink.CLI/README.md
Joseph Doherty 1a540f4f0a feat: add HTTP Management API, migrate CLI from Akka ClusterClient to HTTP
Replace the CLI's Akka.NET ClusterClient transport with a simple HTTP client
targeting a new POST /management endpoint on the Central Host. The endpoint
handles Basic Auth, LDAP authentication, role resolution, and ManagementActor
dispatch in a single round-trip — eliminating the CLI's Akka, LDAP, and
Security dependencies.

Also fixes DCL ReSubscribeAll losing subscriptions on repeated reconnect by
deriving the tag list from _subscriptionsByInstance instead of _subscriptionIds.
2026-03-20 23:55:31 -04:00

33 KiB

ScadaLink CLI

Command-line tool for managing the ScadaLink SCADA system. Connects to a Central node via HTTP and routes commands through the Management API endpoint (POST /management), which dispatches to the ManagementActor. Authentication is handled server-side via LDAP.

Installation

dotnet build src/ScadaLink.CLI

The output binary is scadalink (or scadalink.exe on Windows).

Connection

Every command requires a connection to a running Central node. The management URL can be supplied three ways, evaluated in this priority order:

  1. --url flag on the command line
  2. SCADALINK_MANAGEMENT_URL environment variable
  3. managementUrl field in ~/.scadalink/config.json
scadalink --url http://central-host:5000 <command>

Docker: With the Docker setup, the Central UI (and management API) is available at http://localhost:9001:

scadalink --url http://localhost:9001 <command>

For HA failover, use a load balancer URL. The management API is stateless (Basic Auth per request), so any central node can handle any request without sticky sessions.

Global Options

These options are accepted by the root command and inherited by all subcommands.

Option Description
--url <value> Management API URL (e.g., http://localhost:9001)
--username <value> LDAP username for authentication
--password <value> LDAP password for authentication
--format <json|table> Output format (default: json)

Configuration File

~/.scadalink/config.json is loaded at startup. All fields are optional.

{
  "managementUrl": "http://localhost:9001"
}

For the Docker test environment, see docker/README.md for a ready-to-use config.

Environment Variables

Variable Description
SCADALINK_MANAGEMENT_URL Management API URL (overrides config file)
SCADALINK_FORMAT Default output format (overrides config file)

Output

All commands write JSON to stdout on success. Errors are written as JSON to stderr:

{ "error": "Human-readable message", "code": "ERROR_CODE" }

Exit codes:

Code Meaning
0 Success
1 Command error
2 Authorization failure

Command Reference

template — Manage templates

template list

List all templates with their full attribute, alarm, script, and composition definitions.

scadalink --url <url> template list

template get

Get a single template by ID.

scadalink --url <url> template get --id <int>
Option Required Description
--id yes Template ID

template create

Create a new template, optionally inheriting from a parent.

scadalink --url <url> template create --name <string> [--description <string>] [--parent-id <int>]
Option Required Description
--name yes Template name
--description no Template description
--parent-id no Parent template ID for inheritance

template update

Update an existing template's name, description, or parent.

scadalink --url <url> template update --id <int> [--name <string>] [--description <string>] [--parent-id <int>]
Option Required Description
--id yes Template ID
--name no Updated template name
--description no Updated description
--parent-id no Updated parent template ID

template delete

Delete a template by ID.

scadalink --url <url> template delete --id <int>
Option Required Description
--id yes Template ID

template validate

Run pre-deployment validation on a template (flattening, naming collisions, script compilation).

scadalink --url <url> template validate --id <int>
Option Required Description
--id yes Template ID

template attribute add

Add an attribute to a template.

scadalink --url <url> template attribute add --template-id <int> --name <string> --data-type <string> [--default-value <string>] [--tag-path <string>]
Option Required Description
--template-id yes Template ID
--name yes Attribute name
--data-type yes Attribute data type (e.g. Float, Int, String, Bool)
--default-value no Default value
--tag-path no Data connection tag path

template attribute update

Update an attribute on a template.

scadalink --url <url> template attribute update --template-id <int> --name <string> [--data-type <string>] [--default-value <string>] [--tag-path <string>]
Option Required Description
--template-id yes Template ID
--name yes Attribute name to update
--data-type no Updated data type
--default-value no Updated default value
--tag-path no Updated tag path

template attribute delete

Remove an attribute from a template.

scadalink --url <url> template attribute delete --template-id <int> --name <string>
Option Required Description
--template-id yes Template ID
--name yes Attribute name to delete

template alarm add

Add an alarm definition to a template.

scadalink --url <url> template alarm add --template-id <int> --name <string> --trigger-attribute <string> --condition <string> --setpoint <string> [--severity <string>] [--notification-list <string>]
Option Required Description
--template-id yes Template ID
--name yes Alarm name
--trigger-attribute yes Attribute that triggers the alarm
--condition yes Trigger condition (e.g. GreaterThan, LessThan, Equal)
--setpoint yes Setpoint value
--severity no Alarm severity (default: Warning)
--notification-list no Notification list name to notify on alarm

template alarm update

Update an alarm definition on a template.

scadalink --url <url> template alarm update --template-id <int> --name <string> [--condition <string>] [--setpoint <string>] [--severity <string>] [--notification-list <string>]
Option Required Description
--template-id yes Template ID
--name yes Alarm name to update
--condition no Updated trigger condition
--setpoint no Updated setpoint value
--severity no Updated severity
--notification-list no Updated notification list name

template alarm delete

Remove an alarm definition from a template.

scadalink --url <url> template alarm delete --template-id <int> --name <string>
Option Required Description
--template-id yes Template ID
--name yes Alarm name to delete

template script add

Add a script to a template.

scadalink --url <url> template script add --template-id <int> --name <string> --trigger-type <string> [--trigger-attribute <string>] [--interval <int>] --code <string>
Option Required Description
--template-id yes Template ID
--name yes Script name
--trigger-type yes Trigger type: OnChange, Periodic, OnAlarm
--trigger-attribute no Attribute name for OnChange trigger
--interval no Interval in milliseconds for Periodic trigger
--code yes Script source code (or @filepath to read from file)

template script update

Update a script on a template.

scadalink --url <url> template script update --template-id <int> --name <string> [--trigger-type <string>] [--trigger-attribute <string>] [--interval <int>] [--code <string>]
Option Required Description
--template-id yes Template ID
--name yes Script name to update
--trigger-type no Updated trigger type
--trigger-attribute no Updated trigger attribute
--interval no Updated interval
--code no Updated script source code (or @filepath)

template script delete

Remove a script from a template.

scadalink --url <url> template script delete --template-id <int> --name <string>
Option Required Description
--template-id yes Template ID
--name yes Script name to delete

template composition add

Add a feature module composition to a template.

scadalink --url <url> template composition add --template-id <int> --module-template-id <int> --instance-name <string>
Option Required Description
--template-id yes Target template ID
--module-template-id yes Feature module template ID to compose
--instance-name yes Instance name for the composed module (used in path-qualified addressing)

template composition delete

Remove a feature module composition from a template.

scadalink --url <url> template composition delete --template-id <int> --instance-name <string>
Option Required Description
--template-id yes Target template ID
--instance-name yes Instance name of the composed module to remove

instance — Manage instances

instance get

Get a single instance by ID.

scadalink --url <url> instance get --id <int>
Option Required Description
--id yes Instance ID

instance list

List instances, with optional filters.

scadalink --url <url> instance list [--site-id <int>] [--template-id <int>] [--search <string>]
Option Required Description
--site-id no Filter by site ID
--template-id no Filter by template ID
--search no Search term matched against instance name

instance create

Create a new instance of a template at a site.

scadalink --url <url> instance create --name <string> --template-id <int> --site-id <int> [--area-id <int>]
Option Required Description
--name yes Unique instance name
--template-id yes Template to instantiate
--site-id yes Site where the instance will run
--area-id no Area within the site

instance deploy

Deploy an instance to its site. Acquires the per-instance operation lock.

scadalink --url <url> instance deploy --id <int>
Option Required Description
--id yes Instance ID

instance enable

Enable a previously disabled instance.

scadalink --url <url> instance enable --id <int>
Option Required Description
--id yes Instance ID

instance disable

Disable a running instance without deleting it.

scadalink --url <url> instance disable --id <int>
Option Required Description
--id yes Instance ID

instance delete

Delete an instance. The instance must be disabled first.

scadalink --url <url> instance delete --id <int>
Option Required Description
--id yes Instance ID

instance set-bindings

Set data connection bindings for an instance's attributes.

scadalink --url <url> instance set-bindings --id <int> --bindings <json>
Option Required Description
--id yes Instance ID
--bindings yes JSON array of [attributeName, dataConnectionId] pairs (e.g. [["Speed",7],["Temperature",7]])

site — Manage sites

site get

Get a single site by ID.

scadalink --url <url> site get --id <int>
Option Required Description
--id yes Site ID

site list

List all registered sites.

scadalink --url <url> site list

site create

Register a new site.

scadalink --url <url> site create --name <string> --identifier <string> [--description <string>]
Option Required Description
--name yes Human-readable site name
--identifier yes Unique machine identifier used for cluster routing (e.g. site-a)
--description no Site description

site delete

Delete a site. Fails if any instances are assigned to it.

scadalink --url <url> site delete --id <int>
Option Required Description
--id yes Site ID

site deploy-artifacts

Push compiled artifacts to one or all sites.

scadalink --url <url> site deploy-artifacts [--site-id <int>]
Option Required Description
--site-id no Target site ID; omit to deploy to all sites

site area list

List all areas for a site.

scadalink --url <url> site area list --site-id <int>
Option Required Description
--site-id yes Site ID

site area create

Create an area within a site.

scadalink --url <url> site area create --site-id <int> --name <string> [--parent-area-id <int>]
Option Required Description
--site-id yes Site ID
--name yes Area name
--parent-area-id no Parent area ID for nested areas

site area update

Update an area's name or parent.

scadalink --url <url> site area update --id <int> [--name <string>] [--parent-area-id <int>]
Option Required Description
--id yes Area ID
--name no Updated area name
--parent-area-id no Updated parent area ID

site area delete

Delete an area. Fails if any instances are assigned to it.

scadalink --url <url> site area delete --id <int>
Option Required Description
--id yes Area ID

deploy — Deployment operations

deploy instance

Deploy a single instance (same as instance deploy).

scadalink --url <url> deploy instance --id <int>
Option Required Description
--id yes Instance ID

deploy artifacts

Deploy compiled artifacts to one or all sites (same as site deploy-artifacts).

scadalink --url <url> deploy artifacts [--site-id <int>]
Option Required Description
--site-id no Target site ID; omit for all sites

deploy status

Query deployment records, with optional filters and pagination.

scadalink --url <url> deploy status [--instance-id <int>] [--status <string>] [--page <int>] [--page-size <int>]
Option Required Default Description
--instance-id no Filter by instance ID
--status no Filter by deployment status string
--page no 1 Page number
--page-size no 50 Results per page

data-connection — Manage data connections

data-connection get

Get a single data connection by ID.

scadalink --url <url> data-connection get --id <int>
Option Required Description
--id yes Data connection ID

data-connection list

List all configured data connections.

scadalink --url <url> data-connection list

data-connection create

Create a new data connection definition.

scadalink --url <url> data-connection create --name <string> --protocol <string> [--configuration <json>]
Option Required Description
--name yes Connection name
--protocol yes Protocol identifier (e.g. OpcUa)
--configuration no Protocol-specific configuration as a JSON string

data-connection update

Update a data connection definition.

scadalink --url <url> data-connection update --id <int> [--name <string>] [--protocol <string>] [--configuration <json>]
Option Required Description
--id yes Data connection ID
--name no Updated connection name
--protocol no Updated protocol identifier
--configuration no Updated protocol-specific configuration as a JSON string

data-connection delete

Delete a data connection.

scadalink --url <url> data-connection delete --id <int>
Option Required Description
--id yes Data connection ID

data-connection assign

Assign a data connection to a site.

scadalink --url <url> data-connection assign --connection-id <int> --site-id <int>
Option Required Description
--connection-id yes Data connection ID
--site-id yes Site ID

data-connection unassign

Remove a data connection assignment from a site.

scadalink --url <url> data-connection unassign --connection-id <int> --site-id <int>
Option Required Description
--connection-id yes Data connection ID
--site-id yes Site ID

external-system — Manage external HTTP systems

external-system get

Get a single external system definition by ID.

scadalink --url <url> external-system get --id <int>
Option Required Description
--id yes External system ID

external-system list

List all external system definitions.

scadalink --url <url> external-system list

external-system create

Register an external HTTP system that scripts can call.

scadalink --url <url> external-system create --name <string> --endpoint-url <url> --auth-type <string> [--auth-config <json>]
Option Required Description
--name yes Display name
--endpoint-url yes Base URL of the external system
--auth-type yes Authentication type: ApiKey or BasicAuth
--auth-config no Auth credentials as a JSON string

external-system update

Update an external system definition.

scadalink --url <url> external-system update --id <int> [--name <string>] [--endpoint-url <url>] [--auth-type <string>] [--auth-config <json>]
Option Required Description
--id yes External system ID
--name no Updated display name
--endpoint-url no Updated base URL
--auth-type no Updated authentication type
--auth-config no Updated auth credentials as a JSON string

external-system delete

Delete an external system definition.

scadalink --url <url> external-system delete --id <int>
Option Required Description
--id yes External system ID

notification — Manage notification lists

notification get

Get a single notification list by ID.

scadalink --url <url> notification get --id <int>
Option Required Description
--id yes Notification list ID

notification list

List all notification lists.

scadalink --url <url> notification list

notification create

Create a notification list with one or more recipients.

scadalink --url <url> notification create --name <string> --emails <email1,email2,...>
Option Required Description
--name yes Notification list name
--emails yes Comma-separated list of recipient email addresses

notification update

Update a notification list's name or recipients.

scadalink --url <url> notification update --id <int> [--name <string>] [--emails <email1,email2,...>]
Option Required Description
--id yes Notification list ID
--name no Updated list name
--emails no Updated comma-separated list of recipient email addresses

notification delete

Delete a notification list.

scadalink --url <url> notification delete --id <int>
Option Required Description
--id yes Notification list ID

notification smtp list

Show the current SMTP configuration.

scadalink --url <url> notification smtp list

notification smtp update

Update the SMTP configuration.

scadalink --url <url> notification smtp update --host <string> --port <int> --auth-type <string> [--username <string>] [--password <string>] [--from-address <string>]
Option Required Description
--host yes SMTP server hostname
--port yes SMTP server port
--auth-type yes Authentication type: OAuth2 or Basic
--username no SMTP username (for Basic auth)
--password no SMTP password (for Basic auth)
--from-address no Sender email address

security — Security settings

security api-key list

List all inbound API keys.

scadalink --url <url> security api-key list

security api-key create

Create a new inbound API key. The generated key value is returned in the response and not stored in plaintext — save it immediately.

scadalink --url <url> security api-key create --name <string>
Option Required Description
--name yes Descriptive label for the key

security api-key update

Update an API key's name or enabled status.

scadalink --url <url> security api-key update --id <int> [--name <string>] [--enabled <bool>]
Option Required Description
--id yes API key ID
--name no Updated label
--enabled no Enable or disable the key (true or false)

security api-key delete

Revoke and delete an API key.

scadalink --url <url> security api-key delete --id <int>
Option Required Description
--id yes API key ID

security role-mapping list

List all LDAP group → role mappings.

scadalink --url <url> security role-mapping list

security role-mapping create

Map an LDAP group to a ScadaLink role.

scadalink --url <url> security role-mapping create --ldap-group <string> --role <string>
Option Required Description
--ldap-group yes LDAP group distinguished name or CN
--role yes ScadaLink role: Admin, Design, or Deployment

security role-mapping update

Update an LDAP role mapping.

scadalink --url <url> security role-mapping update --id <int> [--ldap-group <string>] [--role <string>]
Option Required Description
--id yes Mapping ID
--ldap-group no Updated LDAP group distinguished name or CN
--role no Updated ScadaLink role

security role-mapping delete

Remove an LDAP role mapping.

scadalink --url <url> security role-mapping delete --id <int>
Option Required Description
--id yes Mapping ID

security scope-rule list

List all site scope rules for role mappings.

scadalink --url <url> security scope-rule list [--role-mapping-id <int>]
Option Required Description
--role-mapping-id no Filter by role mapping ID

security scope-rule add

Add a site scope rule to a role mapping, restricting it to a specific site.

scadalink --url <url> security scope-rule add --role-mapping-id <int> --site-id <int>
Option Required Description
--role-mapping-id yes Role mapping ID
--site-id yes Site ID to scope the mapping to

security scope-rule delete

Remove a site scope rule from a role mapping.

scadalink --url <url> security scope-rule delete --id <int>
Option Required Description
--id yes Scope rule ID

health — Health monitoring

health summary

Return the current health state for all known sites as a JSON object keyed by site identifier.

scadalink --url <url> health summary

health site

Return the health state for a single site.

scadalink --url <url> health site --identifier <string>
Option Required Description
--identifier yes Site identifier (e.g. site-a)

health event-log

Query the site event log for a specific site. Events are fetched remotely from the site's local SQLite store.

scadalink --url <url> health event-log --site-identifier <string> [--from <datetime>] [--to <datetime>] [--search <string>] [--page <int>] [--page-size <int>]
Option Required Default Description
--site-identifier yes Site identifier
--from no Start timestamp in ISO 8601 format
--to no End timestamp in ISO 8601 format
--search no Keyword search term
--page no 1 Page number
--page-size no 50 Results per page

health parked-messages

Query parked (dead-letter) messages at a specific site.

scadalink --url <url> health parked-messages --site-identifier <string> [--page <int>] [--page-size <int>]
Option Required Default Description
--site-identifier yes Site identifier
--page no 1 Page number
--page-size no 50 Results per page

debug — Runtime debugging

debug snapshot

Request a point-in-time snapshot of a running instance's current attribute values and alarm states from the site. The instance must be deployed and enabled.

scadalink --url <url> debug snapshot --id <int>
Option Required Description
--id yes Instance ID

The command resolves the instance's site internally and routes the request to the correct site cluster. Returns all attribute values (name, value, quality, timestamp) and alarm states (name, state, priority, timestamp) at the moment the request reaches the site.


audit-log — Audit log queries

audit-log query

Query the central audit log with optional filters and pagination.

scadalink --url <url> audit-log query [options]
Option Required Default Description
--user no Filter by username
--entity-type no Filter by entity type (e.g. Template, Instance)
--action no Filter by action (e.g. Create, Delete)
--from no Start timestamp in ISO 8601 format
--to no End timestamp in ISO 8601 format
--page no 1 Page number
--page-size no 50 Results per page

shared-script — Manage shared scripts

shared-script list

List all shared script definitions.

scadalink --url <url> shared-script list

shared-script get

Get a single shared script by ID.

scadalink --url <url> shared-script get --id <int>
Option Required Description
--id yes Shared script ID

shared-script create

Create a new shared script.

scadalink --url <url> shared-script create --name <string> --code <string>
Option Required Description
--name yes Shared script name
--code yes Script source code (or @filepath to read from file)

shared-script update

Update a shared script's name or code.

scadalink --url <url> shared-script update --id <int> [--name <string>] [--code <string>]
Option Required Description
--id yes Shared script ID
--name no Updated script name
--code no Updated script source code (or @filepath)

shared-script delete

Delete a shared script.

scadalink --url <url> shared-script delete --id <int>
Option Required Description
--id yes Shared script ID

db-connection — Manage database connections

db-connection list

List all database connection definitions.

scadalink --url <url> db-connection list

db-connection get

Get a single database connection by ID.

scadalink --url <url> db-connection get --id <int>
Option Required Description
--id yes Database connection ID

db-connection create

Create a new database connection definition.

scadalink --url <url> db-connection create --name <string> --connection-string <string> [--provider <string>]
Option Required Description
--name yes Connection name
--connection-string yes Database connection string
--provider no Database provider (default: SqlServer)

db-connection update

Update a database connection definition.

scadalink --url <url> db-connection update --id <int> [--name <string>] [--connection-string <string>] [--provider <string>]
Option Required Description
--id yes Database connection ID
--name no Updated connection name
--connection-string no Updated connection string
--provider no Updated database provider

db-connection delete

Delete a database connection definition.

scadalink --url <url> db-connection delete --id <int>
Option Required Description
--id yes Database connection ID

api-method — Manage inbound API methods

api-method list

List all inbound API method definitions.

scadalink --url <url> api-method list

api-method get

Get a single inbound API method by ID.

scadalink --url <url> api-method get --id <int>
Option Required Description
--id yes API method ID

api-method create

Create a new inbound API method.

scadalink --url <url> api-method create --name <string> --code <string> [--description <string>]
Option Required Description
--name yes Method name (used as the URL path segment in POST /api/{methodName})
--code yes Script source code implementing the method (or @filepath to read from file)
--description no Method description

api-method update

Update an inbound API method.

scadalink --url <url> api-method update --id <int> [--name <string>] [--code <string>] [--description <string>]
Option Required Description
--id yes API method ID
--name no Updated method name
--code no Updated script source code (or @filepath)
--description no Updated description

api-method delete

Delete an inbound API method.

scadalink --url <url> api-method delete --id <int>
Option Required Description
--id yes API method ID

Architecture Notes

The CLI connects to the Central cluster using Akka.NET's ClusterClient. It does not join the cluster — it contacts the ClusterClientReceptionist on one of the configured Central nodes and sends commands to the ManagementActor at path /user/management.

The connection is established per-command invocation and torn down cleanly via CoordinatedShutdown when the command completes.

Role enforcement is applied by the ManagementActor on the server side. The CLI authenticates against LDAP using --username / --password, resolves LDAP group memberships, then maps groups to ScadaLink roles (Admin, Design, Deployment) via role mappings configured in the security settings. Operations require the appropriate role — for example, creating templates requires Design, deploying requires Deployment. In the test environment, use the multi-role user (password: password) which has all three roles.

Issues & Missing Features

If you encounter bugs, unexpected behavior, or missing features in the CLI, log them in cli_issues.md in the project root. Include a brief description, the command involved, and any relevant error output.