CLI Reference¶
The dcs command-line tool communicates with the DCS Gateway REST API.
Installation¶
Download the dcs binary for your platform from the Releases page, or use the
web terminal in the gateway UI which has the CLI pre-installed.
Configuration¶
The CLI resolves the gateway URL and default site in this order: flag > environment variable > config file.
| Setting | Flag | Env var | Config command |
|---|---|---|---|
| Gateway URL | --gateway <url> |
DCS_GATEWAY_URL |
dcs config set-gateway <url> |
| Default site | --site / -s <name> |
DCS_SITE |
dcs config set-site <name> |
| Auth token | DCS_AUTH_TOKEN |
dcs login |
|
| Extra request headers | dcs config set-header <name> <value> |
Config file location: ~/.dcs/config.yaml (override with --config).
DCS_AUTH_TOKEN overrides the stored token outright (no refresh, no expiry
warnings): it hands the CLI a short-lived gateway session token without
touching ~/.dcs/config.yaml, for non-interactive use (CI jobs, capture
rigs, scripts). Interactive use should prefer dcs login.
Initial setup¶
dcs config set-gateway https://<gateway-url>
dcs config set-site houston-plant
dcs login # required when the gateway runs with OIDC or LDAP auth
dcs config show
Global Flags¶
| Flag | Short | Description |
|---|---|---|
--gateway <url> |
Gateway base URL | |
--site <name> |
-s |
Site name (required for site-scoped resources) |
--output <format> |
-o |
Output format: table (default), json, or yaml |
--config <path> |
Config file path |
-o yaml on a dcs get <resource> <name> detail view exports a clean
Kubernetes manifest via the gateway export endpoint (not supported for
formulas).
Confirmation Prompts¶
The commands that destroy a resource or move a field output ask before they
act: every dcs delete subcommand, dcs formula delete, dcs io write, and
dcs io release. Each takes --yes / -y to answer in advance.
An unconfirmed command exits non-zero and does nothing. That covers the declined answer and the case with no one there to answer at all: a script, a CI step, or an agent session whose stdin is a redirect reads EOF, sees the prompt abort, and gets a failure it can act on:
$ dcs io write wago-750-352 coil.7 true </dev/null; echo "exit=$?"
Write value true to channel coil.7 on IO module wago-750-352 in site "bench-site"? [y/N]: Error: confirmation required but stdin is not a terminal; pass --yes to confirm non-interactively
exit=1
Pass --yes for any non-interactive caller. A piped answer
(echo y | dcs io write …) is honoured as well.
Command Index¶
Every visible top-level command. Commands without a dedicated section on this
page are summarized here. Run dcs <command> --help for their subcommands
and flags.
| Command | Purpose |
|---|---|
get |
Display one or many resources |
create |
Create a resource |
apply |
Apply a resource from a YAML or JSON file |
command |
Send a state-machine command to a resource |
execute |
Launch ad-hoc procedural elements (Phase, Operation, UnitProcedure) on a Unit |
mode |
Set the ISA-88 mode on a resource |
delete |
Delete a resource |
alarm |
Manage ISA-18.2 alarms (ack, shelve, unshelve) |
audit |
Audit trail commands (trace, export, verify, archive-integrity) |
change-control (alias cc) |
Change-control (21 CFR Part 11 §11.10(k)) commands (propose, history, verify) |
batch |
Batch production record commands (record, finalize, events, messages) |
recipe |
Recipe lifecycle, approval, and version history commands (approve, reject, release, activate, withdraw, history, diff, revert) |
formula |
Manage a master recipe's formulas (list, get, create, delete). Every subcommand is site-scoped and needs --site |
config |
Manage dcs CLI configuration |
tag |
Read and write control module tags (set) |
watch |
Stream live events from the DCS gateway |
login |
Authenticate with the DCS gateway (OIDC device code or LDAP credentials) |
logout |
Clear stored authentication tokens |
auth |
Inspect authorization policy and entitlements (policy, entitlements) |
simulate |
Run a simulation batch against a recipe |
mes |
MES integration commands, ISA-95 Level 3/4 boundary (apikey, work-orders, status) |
backup |
Back up DCS resources (crds, audit) |
restore |
Restore DCS resources from backup (crds) |
health |
Show system health and diagnostics |
historian |
Query historical process data (tags, alarms, states, list-tags) |
io |
Commissioning I/O module operations (list, read, write, release, discover) |
opcua |
Commissioning client for third-party OPC UA servers (endpoints, browse, read, write, subscribe) |
status |
Show operational status overview |
runtime |
Manage unit runtime pods (restart <unit> --reason <text>) |
unit |
Unit-level equipment infrastructure operations (failover, ADR 0006) |
validate |
Validate Structured Text or SFC charts (st, sfc) |
qualify |
Run Installation / Operational / Performance Qualification protocols (iq, oq, pq, dr) |
admin |
Administrative commands (demo provisioning, site repair) |
migrate |
Migrate procedural template manifests across schema breaks |
ui |
Run the DCS gateway UI on this laptop against the active kubeconfig context |
edit |
Edit CRD YAML files in a local directory with the visual editors — no cluster required |
diff |
Show the human-readable semantic diff between two CRD YAML files |
version |
Print the dcs CLI version |
Commands¶
dcs login¶
Authenticate with the DCS gateway. The CLI queries the gateway's auth configuration and picks the matching flow:
- oidc — OIDC device-code flow: the CLI prints a verification URL and user code, opens the browser, and polls until you complete sign-in.
- ldap — prompts for username and password and authenticates against the gateway's LDAP login endpoint.
- none — login is not required, and the command is a no-op.
dcs login
dcs login --no-browser # print the verification URL instead of opening a browser
| Flag | Description |
|---|---|
--no-browser |
Do not attempt to open the verification URL in a browser |
In ldap mode both prompts read from standard input. The credentials can therefore be piped for non-interactive use (CI seeding, capture rigs, air-gapped automation):
printf '%s\n%s\n' "$DCS_USERNAME" "$DCS_PASSWORD" | dcs login
Echo suppression applies only when standard input is a terminal. A piped
password is taken as the whole line, spaces included. Where a pre-issued
gateway token is already available, prefer DCS_AUTH_TOKEN over piping a
password.
Tokens are stored in the CLI config file and attached to every subsequent
request. Expired OIDC tokens are refreshed automatically when a refresh token
is available. Otherwise the CLI prompts you to run dcs login again. Use
dcs logout to clear stored tokens.
If the deployment fronts the gateway with an authenticating proxy, the CLI
must present the proxy's credential headers before dcs login can reach the
gateway. Configure them with dcs config set-header. See
Security Operations.
dcs auth¶
Inspect authorization policy and entitlements (ADR 0024).
dcs auth entitlements # the calling identity's resolved effective action set
dcs auth policy # active role→action resolution (requires supervise)
dcs auth policy --actions # …with every effective action listed per role
entitlements prints the action-catalog names the
current identity may perform, one per line. policy renders, per configured
role, the permission tiers, any allow/deny refinements from the
deployment roles file, and the size of the effective action set they resolve
to. This is the audit-facing view of what the running gateway enforces.
| Flag | Description |
|---|---|
--actions |
policy only: list every effective action per role |
dcs get¶
List or get detail for any resource type. List output uses table format by
default, and detail output is JSON (-o yaml exports a Kubernetes manifest).
dcs get <resource> [name] [flags]
Resources and aliases:
| Resource | Aliases | Site-scoped | Columns |
|---|---|---|---|
enterprises |
ent |
no | NAME, SITES, DESCRIPTION |
sites |
site |
no | NAME, ENTERPRISE, LOCATION, AREAS |
areas |
area |
yes | NAME, SITE, PROCESS CELLS, DESCRIPTION |
processcells |
pc |
yes | NAME, AREA, UNITS, DESCRIPTION |
units |
unit |
yes | NAME, STATE, PROCESS CELL, CONTROLLER, RUNTIME |
controlmodules |
cm |
yes | NAME, TYPE, PARENT, STATE, TEMPLATE, FB NETWORK |
iomodules |
io |
yes | NAME, CONTROLLER, PROTOCOL, ADDRESS, STATE, CHANNELS |
controlprograms |
cp, fbnetworks, fb |
yes | NAME, UNIT, MODE, STATE, BLOCKS, SCANS |
templates |
tpl |
no | NAME, TYPE, SCAN INTERVAL, INPUTS, OUTPUTS, BLOCKS |
functionblocktypes |
fbt, fbblocktypes, functionblocktype |
no | NAME, INPUTS, OUTPUTS, BLOCKS |
blocktypes |
bt |
no | NAME, CATEGORY, DESCRIPTION |
controllers |
ctrl |
yes | NAME, ADDRESS, PHASE, NODE |
batches |
batch |
yes | BATCH ID, NAME, PHASE, STATE, RECIPE, MESSAGE |
batchrecords |
batchrecord, br |
yes | NAME, BATCH ID, PHASE, OUTCOME, RECIPE, COMPLETED |
masterrecipes |
mr |
yes | NAME, SITE RECIPE, TARGET CELL, PHASE, STEPS |
controlrecipes |
cr |
yes | NAME, MASTER RECIPE, BATCH, PHASE, STEPS |
formulas |
formula |
no | SITE, TYPE, RECIPE, FORMULA, BATCH SIZE, PARAMS, MATERIALS |
procedures |
proc |
yes | NAME, STATE, PROGRESS |
unitprocedures |
up |
yes | NAME, UNIT, STATE, PROGRESS |
operations |
op |
yes | NAME, UNIT PROCEDURE, STATE, PROGRESS |
phases |
phase |
yes | NAME, STATE, STEP, OPERATION, UNIT |
phasetemplates |
pt |
yes | NAME, CAPABILITY, DESCRIPTION |
operationtemplates |
ot |
yes | NAME, DESCRIPTION, STEPS |
unitproceduretemplates |
upt |
yes | NAME, DESCRIPTION, STEPS |
proceduretemplates |
proct |
yes | NAME, DESCRIPTION, STEPS |
alarmdefinitions |
ad, alarmdef |
yes | NAME, SOURCE, CONDITION, SEVERITY, ENABLED |
alarms |
alarm |
yes | NAME, SOURCE, TYPE, SEVERITY, STATE, MESSAGE, AGE |
auditrecords |
audit, ar |
yes | NAME, ACTION, TARGET KIND, TARGET NAME, RESULT, COMPONENT, TIMESTAMP |
simulationpresets |
simpresets, simpreset |
yes | NAME, DESCRIPTION, BEHAVIORS, ADDRESS NAMES |
fbnetworks / fb are aliases of controlprograms. Both query the
same control programs.
phases lists only live batch-instance phases. The hand-authored library
Phase definitions in the recipe library are omitted, because they are
authoring artifacts and the command lists runtime state. The STEP column is the phase's
currently executing SFC step, the same active step the HMI chart highlights.
dcs get phases <name> drills into one phase: it prints the active SFC step
and, for that step's outgoing transition, the condition ST plus the live value
of every variable the condition reads, the same state the HMI's transition
code panel shows (e.g. open_media.T >= chargeTime, with open_media.T ticking
toward chargeTime). That answers "why is this phase holding, and how close is
it?" from the shell. --active prints the same detail for whichever phase is
running now, so you don't have to type its generated instance name first.
-o json/-o yaml are unaffected and return the full phase object.
Live-data resources (special handling, outside the table above):
| Resource | Description |
|---|---|
tags (tag) |
Live tag/IO values; scope with --cm, --io, or --unit/-u, or omit to browse all site tags |
runtime |
Unit runtime diagnostics (requires --unit/-u) |
health |
System health overview |
Tag shorthand (dot notation):
dcs get <cm>.<tag> # read a single control module tag (e.g. agitator-1.PV)
dcs get <cm>. # list all tags for a control module
| Flag | Short | Description |
|---|---|---|
--unit |
-u |
Unit name (for tags and runtime resources) |
--io |
IOModule name (for tags; resolves the runtime automatically) |
|
--cm |
ControlModule name (for tags; resolves unit/runtime automatically) |
|
--active |
For phases: show each running phase's active SFC transition and its live variables |
Examples:
# List all enterprises
dcs get enterprises
# List units in table format
dcs get units -s houston-plant
# Get unit detail as JSON
dcs get units reactor-1 -s houston-plant
# Export a unit as a Kubernetes manifest
dcs get units reactor-1 -s houston-plant -o yaml
# List batches in JSON format
dcs get batches -s houston-plant -o json
# Use an alias
dcs get cp -s houston-plant
# Live tags for a unit
dcs get tags -u reactor-1 -s houston-plant
# Why is the running phase holding? Show its transition condition + live variables
dcs get phases --active -s houston-plant
dcs create¶
Create a resource using flags.
dcs create <resource> [flags]
Subcommands: enterprise, site, area, processcell, unit,
controlmodule, controller, iomodule, batch, controlprogram (cp),
functionblocktype (fbt), procedure (proc), unitprocedure (up),
operation (op), phase, alarmdefinition (ad),
simulationpreset (simpreset).
dcs create enterprise¶
dcs create enterprise --name acme-pharma --description "ACME Pharmaceuticals"
| Flag | Required | Description |
|---|---|---|
--name |
yes | Enterprise name |
--description |
no | Description |
dcs create site¶
dcs create site --name houston-plant --enterprise acme-pharma --location "Houston, TX"
| Flag | Required | Description |
|---|---|---|
--name |
yes | Site name |
--enterprise |
yes | Parent enterprise |
--description |
no | Description |
--location |
no | Location |
dcs create area¶
dcs create area --name granulation-area -s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | Area name |
--description |
no | Description |
dcs create processcell¶
dcs create processcell --name granulation-cell-1 --area granulation-area -s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | Process cell name |
--area |
yes | Parent area |
--description |
no | Description |
dcs create unit¶
dcs create unit --name reactor-1 --process-cell granulation-cell-1 \
--controller plc-controller-1 --protocol modbus --endpoint 10.0.1.100:502 \
-s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | Unit name |
--process-cell |
yes | Parent process cell |
--description |
no | Description |
--controller |
no | Controller to run the runtime on |
--protocol |
no | Device protocol (simulation, modbus, ethernetip, opcua) |
--endpoint |
no | Protocol-specific endpoint |
dcs create controlmodule¶
dcs create controlmodule --name temp-sensor-1 \
--parent-name reactor-1 --parent-kind Unit \
--template-ref basic-temp-input \
-s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | Control module name |
--parent-name |
yes | Parent resource name |
--parent-kind |
yes | Parent kind: Unit |
--template-ref |
yes | Control module template reference |
--description |
no | Description |
dcs create controller¶
dcs create controller --name plc-controller-1 --labels dcs.io/device=plc-io -s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | Controller name |
--labels |
no | Comma-separated key=value labels |
dcs create iomodule¶
dcs create iomodule --name turck-io-1 \
--controller-ref plc-controller-1 --protocol modbus --address 10.0.1.100:502 \
-s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | I/O module name |
--controller-ref |
yes | Controller reference |
--protocol |
yes | Protocol (modbus, ethernetip, opcua, simulation) |
--address |
yes | Network address |
dcs create batch¶
dcs create batch --batch-id BATCH-2026-001 --recipe api-granulation-cell1 -s houston-plant
| Flag | Required | Description |
|---|---|---|
--batch-id |
yes | Unique batch identifier |
--recipe |
yes | MasterRecipe name |
--formula |
no | Formula name from the master recipe |
dcs create controlprogram¶
Create an IEC 61131-3 control program (FBD or Structured Text) deployed to a unit runtime.
dcs create controlprogram --name pid-loop --unit reactor-1 --scan-interval 100ms -s houston-plant
dcs create controlprogram --name temp-ctrl --unit reactor-1 --st-source "OUT := SP - PV;" -s houston-plant
dcs create controlprogram --name temp-ctrl --unit reactor-1 --st-file program.st -s houston-plant
Aliases: cp
| Flag | Required | Description |
|---|---|---|
--name |
yes | Control program name |
--unit |
yes | Target unit name |
--scan-interval |
no | Scan cycle interval (default: 200ms) |
--cm |
no | Control module reference |
--st-source |
no | Inline Structured Text source code (mutually exclusive with --st-file) |
--st-file |
no | Path to Structured Text source file |
dcs create functionblocktype¶
Create a composite function block type definition (IEC 61131-3).
dcs create functionblocktype --name cascade-pid --description "Cascade PID" --inputs SP,PV --outputs CV
Aliases: fbt
| Flag | Required | Description |
|---|---|---|
--name |
yes | Function block type name |
--description |
no | Block type description |
--inputs |
no | Data input port names (comma-separated) |
--outputs |
no | Data output port names (comma-separated) |
dcs create procedure¶
Create a procedure (ISA-88 procedural model).
dcs create procedure --name api-granulation-proc --recipe-ref api-granulation-cell1 \
--unit-procedures granulate-up,dry-up -s houston-plant
Aliases: proc
| Flag | Required | Description |
|---|---|---|
--name |
yes | Procedure name |
--description |
no | Description |
--recipe-ref |
no | Recipe reference |
--execution-mode |
no | Sequential or Parallel (default: Sequential) |
--mode |
no | Automatic, Semi-Automatic, or Manual (default: Automatic) |
--unit-procedures |
no | Child UnitProcedure names (comma-separated) |
dcs create unitprocedure¶
Create a unit procedure (ISA-88 procedural model).
dcs create unitprocedure --name granulate-up --unit reactor-1 \
--procedure-ref api-granulation-proc --operations charge-op,mix-op -s houston-plant
Aliases: up
| Flag | Required | Description |
|---|---|---|
--name |
yes | Unit procedure name |
--unit |
no | Target unit name |
--description |
no | Description |
--procedure-ref |
no | Parent procedure reference |
--operations |
no | Child Operation names (comma-separated) |
dcs create operation¶
Create an operation (ISA-88 procedural model).
dcs create operation --name mix-op --unit-procedure-ref granulate-up \
--phases dose-api,agitate -s houston-plant
Aliases: op
| Flag | Required | Description |
|---|---|---|
--name |
yes | Operation name |
--description |
no | Description |
--unit-procedure-ref |
no | Parent unit procedure reference |
--phases |
no | Child Phase names (comma-separated) |
dcs create phase¶
Create a phase (ISA-88 procedural model).
dcs create phase --name dose-api --operation-ref mix-op --unit-ref reactor-1 \
--timeout 600 -s houston-plant
| Flag | Required | Description |
|---|---|---|
--name |
yes | Phase name |
--description |
no | Description |
--operation-ref |
no | Parent operation reference |
--unit-ref |
no | Unit to run on |
--timeout |
no | Timeout in seconds |
dcs create alarmdefinition¶
Create an alarm definition.
dcs create alarmdefinition --name reactor-temp-high \
--source-kind ControlModule --source-name temp-sensor-1 \
--condition TagHigh --tag-name PV --threshold 85 \
--type Equipment --severity High --message "Reactor temperature high" \
-s houston-plant
Aliases: ad
| Flag | Required | Description |
|---|---|---|
--name |
yes | Alarm definition name |
--source-kind |
yes | Source kind: Unit, ControlModule, etc. |
--source-name |
yes | Source resource name |
--condition |
yes | Condition type: StateEquals, TagHigh, TagLow, TagHighHigh, TagLowLow, TagDeviation, TagTrue, TagFalse |
--type |
yes | Alarm type: Equipment or System |
--severity |
yes | Alarm severity |
--message |
yes | Human-readable alarm message |
--state-value |
no | State value (for StateEquals condition) |
--tag-name |
no | Tag name (for tag-based conditions) |
--threshold |
no | Threshold value |
--setpoint |
no | Setpoint (for TagDeviation) |
--deadband |
no | Deadband/hysteresis |
--debounce-seconds |
no | Activation debounce in seconds |
--priority |
no | ISA-18.2 priority (1-4) |
dcs create simulationpreset¶
Create a reusable equipment simulation template. Presets define behavior models using generic address names that are mapped to real IOModule addresses when used by a simulation profile.
dcs create simulationpreset --name simple-tank \
--description "Basic tank with level and temperature" \
--behavior "level:TankLevel:inFlowAddr=inlet_flow,outFlowAddr=outlet_flow,capacity=500" \
--behavior "temperature_pv:TemperatureRamp:spAddr=temperature_sp,ratePerSec=2.0" \
-s houston-plant
# Seed the built-in presets (reactor-vessel, mixing-tank, control-valve, cip-skid, heat-exchanger)
dcs create simulationpreset --seed-builtins -s houston-plant
Aliases: simpreset
| Flag | Required | Description |
|---|---|---|
--name |
yes, unless --seed-builtins |
Preset name |
--description |
no | Human-readable description |
--behavior |
yes, unless --seed-builtins |
Behavior template address:Type:param=val,param=val (repeatable) |
--seed-builtins |
no | Create the built-in equipment presets |
dcs apply¶
Create a resource from a YAML or JSON manifest file, similar to kubectl apply.
dcs apply -f manifest.yaml
dcs apply -f - # read from stdin
cat manifest.yaml | dcs apply -f -
| Flag | Short | Required | Description |
|---|---|---|---|
--file |
-f |
yes | Path to YAML/JSON file (use - for stdin) |
dcs command¶
Send an ISA-88 state machine command to a resource.
dcs command <Kind> <name> <Command> [--reason <text>] -s <site>
Kind: Batch, or Phase / Operation / UnitProcedure when that resource
is the root of an ad-hoc execution. ISA-88 state commands
flow through the Batch resource, so a procedural element owned by a batch (or a
child of a larger ad-hoc run) is rejected. Command its owner instead. Physical
equipment is never commanded directly, and Unit is refused by the CLI before
the request is sent.
Name: a Batch answers to either of its two handles: the resource name
(batch-6jrkm, the NAME column of dcs get batches) or the batch ID you gave it
at creation (--batch-id, the BATCH ID column). The CLI resolves the ID onto the
resource before sending the command, and the resource name wins when a name and
some other batch's ID collide. A batch ID two live batches share is ambiguous and
refused by name, so address one of them by its resource name. Every other kind is
addressed by resource name only.
Resolution reads the site's batch list. Where the CLI cannot read it (no grant, an outage), a handle that is already a legal resource name is sent through unchanged, because the server can still answer for it. A handle that is not a legal resource name (every batch ID carrying an uppercase letter is one) is refused here instead. The command endpoint takes a resource name, so sending the handle unresolved could only return a Kubernetes naming complaint about an identifier the operator never thought of as a Kubernetes name. The refusal carries the list error, which is the half that says whether to fix a grant or wait out an outage.
Valid commands: Abort, Hold, Pause, Reset, Restart, Resume, Start, Stop
| Flag | Required | Description |
|---|---|---|
--reason |
for Abort, Hold, Reset, Stop |
Justification recorded in the 21 CFR Part 11 audit trail; must meet the deployment reason policy minimum length |
Examples:
dcs command Batch BATCH-2026-001 Start -s houston-plant
dcs command Batch BATCH-2026-001 Hold --reason "Foam excursion on reactor-1, per SOP-OP-021" -s houston-plant
dcs command Batch BATCH-2026-001 Abort --reason "Deviation DEV-0142: charge overshoot" -s houston-plant
dcs execute¶
Launch an ad-hoc procedural element on an idle Unit without creating a Batch. See Ad-Hoc Execution for the full guide and rules.
dcs execute phase --unit <unit> --template <PhaseTemplate> [--param k=v ...] -s <site>
dcs execute operation --unit <unit> --template <OperationTemplate> [--param k=v ...] -s <site>
dcs execute unitprocedure --unit <unit> --template <UnitProcedureTemplate> --reason <text> -s <site>
All three subcommands share these flags:
| Flag | Required | Description |
|---|---|---|
--unit |
yes | Target Unit name |
--template |
yes | Template name |
--param |
no | Parameter override key=value (repeat for multiple) |
--timeout |
no | Override the template's TimeoutSeconds |
--reason |
unitprocedure only (in production mode) |
Audit-trail justification |
operation requires the OperationTemplate to have spec.category = equipment
and the user to have the dcs-lead-operator group (or higher). unitprocedure
additionally requires a fresh OIDC token in production mode for the 21 CFR Part
11 electronic signature.
Examples:
# Operator: take an ad-hoc sample
dcs execute phase --unit reactor-1 --template take-sample --param volume_ml=10 -s houston-plant
# Lead operator: weekly CIP cycle
dcs execute operation --unit reactor-1 --template cip-cycle --param caustic_temp_c=80 -s houston-plant
# Lead operator: full SIP+CIP+leak-test sequence in production
dcs execute unitprocedure --unit reactor-1 --template full-cleaning-cycle \
--reason "weekly CIP per SOP-CL-014" -s houston-plant
dcs mode¶
Set the ISA-88 mode on a procedural or equipment resource.
dcs mode <Kind> <name> <Mode> -s <site>
| Kind family | Kinds | Valid modes |
|---|---|---|
| Procedural | Procedure, UnitProcedure, Operation, Phase |
Automatic, Semi-Automatic, Manual |
| Equipment | Unit, ControlModule |
Automatic, Manual |
Example:
dcs mode Phase dose-api Manual -s houston-plant
dcs unit failover¶
Re-bind a unit's runtime to a designated standby node
(ADR 0006). ISA-88
state commands do not live under dcs unit. They flow through the
Batch resource (dcs command Batch …), and this group covers equipment
infrastructure operations.
dcs unit failover <unit> -s <site> # list eligible targets + availability state
dcs unit failover <unit> -s <site> --to-node <node> --reason "<justification>"
Without --to-node, prints the unit's availability mode, current node
and lease state, and the eligible failover targets (resolved from
spec.availability.failoverTargets, where nodes must be enrolled via the
dcs.io/site label and Ready). With --to-node, requests the failover:
the physical operator fences the old binding, re-binds the runtime pod
to the target, and redeploys the control program from the control-plane
source of truth. Recovery is an ISA-88 Restart. The outcome lands on the
unit's FailoverRequest status condition.
| Flag | Purpose |
|---|---|
--to-node <node> |
Target standby node; omit to list eligible targets |
--reason <text> |
Required with --to-node; recorded in the audit trail and must meet the deployment reason policy |
--confirm-fenced |
One-writer certification: you certify the current node is powered off or disconnected from the field network. Required in Autonomy mode; overrides a still-held lease in Failover mode (planned maintenance) |
--allow-colocation |
Permit a target that already hosts another unit's runtime (co-location guard refuses otherwise) |
See the Failover Runbook for the full operational procedure and HA and Failure Modes for when to use it.
dcs delete¶
Delete a resource with confirmation prompt.
dcs delete <resource> <name> [flags]
All delete subcommands support --yes / -y to skip the confirmation prompt.
A prompt that is declined or cannot be answered exits non-zero and deletes
nothing (see Confirmation Prompts).
Resources: enterprise, site, area, processcell, unit,
controlmodule, iomodule, batch, template, masterrecipe,
controlrecipe, fbnetwork, controlprogram, functionblocktype,
procedure, unitprocedure, operation, phase, alarmdefinition,
alarm, simulationpreset, controller
fbnetwork and controlprogram delete the same resource. alarm deletes an
alarm instance (admin cleanup of orphans, since alarms are normally managed
by the alarm-operator).
Examples:
dcs delete unit reactor-1 -s houston-plant
dcs delete enterprise acme-pharma -y
dcs delete batch batch-001 -s houston-plant
dcs watch¶
Stream live events from the DCS gateway via Server-Sent Events (SSE), or poll
REST endpoints with --interval when SSE/MQTT is unavailable.
dcs watch [channel] [flags]
Channels: tags (use --unit to filter), alarms, states, all
(default when no channel is given).
| Flag | Short | Description |
|---|---|---|
--unit |
-u |
Filter tag events to a specific unit (required when polling tags) |
--interval |
-i |
Poll interval (e.g. 2s). Switches the transport from SSE to REST polling |
Examples:
dcs watch -s houston-plant # SSE: all events
dcs watch tags --unit reactor-1 -s houston-plant # SSE: tag changes for a unit
dcs watch alarms -s houston-plant # SSE: alarm events
dcs watch tags -u reactor-1 -i 2s -s houston-plant # poll tag values every 2s
dcs watch states -o json -s houston-plant # machine-readable output
A GAP line means the gateway shed events this connection was too slow to
take, and the stream is no longer a complete record from that point on. Tag
values recover on their own within one 200 ms republish. Alarms and states
publish on transition only, so re-read those with dcs get alarms and
dcs get units. What scrolled past is stale the moment a frame was shed. See
scada-integration.md.
dcs simulate¶
Execute a recipe against simulated equipment for development and IQ/OQ
validation. Creates a simulation Batch (all units forced to the simulation
driver), watches it to completion, prints a simulation summary (outcome,
wall-clock vs. simulated duration), and deletes the Batch unless --keep is
set.
dcs simulate <master-recipe-name> [flags] -s <site>
| Flag | Description |
|---|---|
--time-scale |
Simulation time multiplier (e.g. 10.0 for 10x; default 1.0) |
--step-through |
Hold after each SFC step transition |
--seed |
RNG seed for deterministic simulation (0 = random) |
--keep |
Keep the simulation Batch after completion |
Example:
dcs simulate api-granulation-cell1 --time-scale 10 -s houston-plant
dcs audit¶
Query the 21 CFR Part 11 audit trail.
dcs audit trace¶
Display the complete audit trail for a batch execution chain, in chronological order. The correlation ID is typically the batch ID.
dcs audit trace BATCH-2026-001 -s houston-plant
dcs audit export¶
Export audit records to JSON or CSV for regulatory review. Records are fetched from both active (Kubernetes) and archived (historian) storage.
dcs audit export --from 2026-01-01 --to 2026-03-01 -f audit-q1.json
dcs audit export --format csv --action Approve -f approvals.csv
dcs audit export --format json --target-kind Batch --from 2026-01-01
| Flag | Short | Description |
|---|---|---|
--action |
Filter by action (Create, Approve, etc.) | |
--target-kind |
Filter by target resource kind | |
--component |
Filter by actor component | |
--from |
Start date (RFC3339 or YYYY-MM-DD) | |
--to |
End date (RFC3339 or YYYY-MM-DD) | |
--format |
Output format: json (default) or csv |
|
--file |
-f |
Output file path (default: stdout) |
--allow-partial |
Accept an export the gateway could not read the archived records for |
An archive the gateway cannot reach shortens the export without changing its
shape: a range old enough to have been archived comes back empty, which in the
file is indistinguishable from a range in which nothing happened. The gateway
declares which halves it read, and this command acts on that declaration. The
export is still written, and then the command exits non-zero with the reason on
stderr. Pass --allow-partial to accept the gap deliberately.
The warning goes to stderr and never into the document itself. That keeps
dcs audit export --format json | jq parseable. A gateway too old to make the
declaration is reported as unverified. That is not the same as incomplete, so
it does not fail the command.
dcs audit verify¶
Check electronic signatures on audit records against the current HMAC signing
key store (21 CFR Part 11 §11.70). The default mode confirms that every signed
record's keyID still resolves in the store. That is the check a key rotation
puts at risk. It does not recompute digests, because an AuditRecord does not
retain the payload that was signed. With --archived, recomputes digests of
archive batches signed by the audit-archiver and verifies manifest signatures.
Exit code 1 if any verification fails.
dcs audit verify
dcs audit verify --archived --since 2026-01-01T00:00:00Z
| Flag | Description |
|---|---|
--site |
Limit to a specific site (default: all sites; ignored with --archived) |
--archived |
Verify archived audit batches in place of active records |
--since |
Lower bound for archive batch start time, RFC3339 (requires --archived) |
--until |
Upper bound for archive batch start time, RFC3339 (requires --archived) |
dcs audit archive-integrity¶
Read and trigger the gateway's archive-integrity verifier, which fetches every archive manifest from the historian and checks each against its recorded digest.
status reports the most recent verification. It reads in-memory scheduler
state, so it is empty until the first run completes and is cleared by any
gateway restart.
run performs one verification immediately and prints the verdict. The
scheduler's first run fires one interval after boot and the interval has a
15-minute floor, so a gateway that has just started has no answer for at
least that long. That is the right cadence for a background sweep, and the
wrong one when you have just restored an archive and need to know whether it
verifies. The run is synchronous and exits 1 if any manifest fails. It writes
the same AuditRecord a scheduled run writes, so an on-demand check is as
auditable as a scheduled one. A run requested while another is in flight is
refused, with no duplicate started.
dcs audit archive-integrity status
dcs audit archive-integrity run
The archive-integrity:run action is admin by default. Grant it to
another role through that role's allow list. See
Security Operations.
dcs change-control¶
Propose changes through change control, and inspect and verify the
change-control audit trail. Alias: dcs cc.
dcs change-control propose¶
Wrap a manifest document into a ChangeRequest and submit it for approval.
A direct write of the resource is exactly what this path replaces. This is
the CLI counterpart of the gateway's Promote flow: the plant model is
declarative YAML, so the file you edit (with any editor, tracked in git) is
the change you propose. The change is realised only after an authorised
approver signs the ChangeRequest in the approval queue.
The proposed document replaces the target's spec when the ChangeRequest
applies. Propose from a file that matches the cluster's current state apart
from the change you intend: a git-managed site tree, where a stale copy
would silently revert someone else's landed change.
# Single-document file
dcs change-control propose -f recipe.yaml --reason "CCR-1042: raise hold temperature"
# Multi-document site file — pick one document
dcs change-control propose -f sites/plant-01/08a-phase-templates.yaml \
--target phasetemplate/ferment-hold \
--reason "CCR-1042: reduce recirculation pump speed during the hold"
| Flag | Short | Description |
|---|---|---|
--file |
-f |
Path to a YAML/JSON manifest (use - for stdin) |
--reason |
Justification recorded on the ChangeRequest (e.g. a change-control ticket) |
|
--target |
kind/name of the document to propose from a multi-document file |
|
--backend |
direct-apply | git-pr | webhook | in-cluster-queue (default: the deployment default) |
|
--operation |
Create | Update | Delete (default: Update) |
dcs change-control history¶
Show the change-control admission audit chain for a resource.
dcs change-control history ControlProgram cp-fill --site pharma-1
dcs change-control verify¶
Walk the AuditRecords produced by the change-control admission webhook and confirm every record carries the required §11.10(k) fields. Exit code 1 if any record is incomplete, which suits a scheduled job or CI pipeline.
dcs change-control verify
dcs change-control verify --site-filter pharma-1
dcs historian¶
Query historical tag values, alarm events, and state transitions from the
historian. Time values support RFC3339, date-only (2026-04-10), and
relative durations (1h, 2d).
Common flags (tags, alarms, states):
| Flag | Description |
|---|---|
--from |
Start time (default: 1h) |
--to |
End time (default: now) |
--batch |
Batch ID (switches to the batch-specific endpoint) |
--limit |
Maximum number of results (default: 100) |
--offset |
Pagination offset |
dcs historian tags¶
dcs historian tags --tag TT-101 -s houston-plant
dcs historian tags --unit reactor-1 --agg avg --interval 5m -s houston-plant
dcs historian tags --batch BATCH-2026-001 -s houston-plant
| Flag | Description |
|---|---|
--tag |
Filter by tag address |
--unit |
Filter by unit name |
--agg |
Aggregation function (avg, min, max, last, first) |
--interval |
Aggregation interval (1m, 5m, 15m, 1h, 1d) |
dcs historian alarms¶
dcs historian alarms --severity Critical -s houston-plant
dcs historian alarms --source-name reactor-1 --from 24h -s houston-plant
| Flag | Description |
|---|---|
--source-kind |
Filter by source resource kind |
--source-name |
Filter by source resource name |
--alarm-name |
Filter by alarm name |
--severity |
Filter by severity (Critical, High, Medium, Low) |
dcs historian states¶
dcs historian states --kind Unit --name reactor-1 -s houston-plant
dcs historian states --from 7d -s houston-plant
| Flag | Description |
|---|---|
--kind |
Filter by resource kind (Unit, Phase, etc.) |
--name |
Filter by resource name |
dcs historian list-tags¶
List distinct tag names (unit/address pairs) known to the historian for the given site.
dcs historian list-tags -s houston-plant
dcs io¶
Commission I/O wiring: list the modules a site carries, read and write single
channels, and discover what a device actually presents. Reads and writes go
through the gateway to the io-probe pod on the module's Controller, which
holds the driver connection. A simulation module is served by its unit runtime
instead, because that is where the simulated process state lives.
dcs --site newark-plant io list
dcs --site newark-plant io list wago-750-352
dcs --site newark-plant io read wago-750-352 DI0
dcs --site newark-plant io write wago-750-352 DO2 true
Channels are named or raw. The <channel> argument accepts either a
channel name the IOModule declares in spec.channels (DI0) or the raw
driver address behind it (discrete.0). The gateway resolves a declared name
to its address before the driver sees it, and read prints both so the
mapping it used is on the screen:
CHANNEL ADDRESS VALUE QUALITY
DI0 wago-750-352:discrete.0 true Good
An identifier the module declares no channel for is passed to the driver as a
raw address, with no refusal. That fall-through is what makes commissioning
possible: you read addresses off a coupler before anyone has written them into
spec.channels, and dcs io discover exists to turn what you find into that
channel list. When the driver then rejects the address, the error names the
channels the module does declare, so a mistyped name does not read as a
protocol fault.
A write is refused while a unit is executing through the module. io write
addresses a channel below the tag model, so there is no control module to carry
an ISA-88 equipment mode and no mode to consult. The gateway asks the question
it can answer instead, which is whether a Unit that reads and writes through
this IOModule is running a batch or an ad-hoc phase. If one is, the write is
refused and the refusal names the unit and the control module that binds it.
The mid-batch way to move an output is the modelled one: put the control module
in Manual and write the tag, which is what ISA-88 Table 1 describes. io read
is unaffected, and so is a write to a module no executing unit touches.
Subcommands:
| Subcommand | Purpose |
|---|---|
list [name] |
List the site's IOModules, or show one module's protocol, state and declared channels |
read <module> <channel> |
Read one channel, by declared name or raw driver address |
write <module> <channel> <value> |
Write one channel. Prompts for confirmation unless --yes is given; an unconfirmed write exits non-zero, see Confirmation Prompts |
release <module> <channel> |
Clear the force a previous write placed on a simulation channel, so its configured behaviors drive it again. Simulation modules only — a write to real hardware simply becomes the device state |
discover <module> |
Ask the device what channels it presents, which is the input to the module's spec.channels |
dcs opcua¶
Commission against a third-party OPC UA server: discover endpoints, browse the
address space, and verify reads, writes and subscriptions. Unlike every other
command on this page, dcs opcua talks directly to the OPC UA server, and no
gateway sits in the path. It needs no --gateway, no site, and no login. It
connects through the same client code the serviceBinding reconciler uses, so
a security tuple proven here is proven for the CR that will carry it.
Start with endpoints, which is a metadata-only call needing no credentials:
dcs opcua endpoints opc.tcp://192.168.10.50:4840
Every other subcommand opens a session and requires either an explicit
security tuple or --insecure (SecurityPolicy=None, SecurityMode=None,
for anonymous exploration only and never as a default):
dcs opcua browse opc.tcp://192.168.10.50:4840 --insecure --depth 3
dcs opcua read opc.tcp://192.168.10.50:4840 "ns=4;s=Tank1.Level" --insecure
A secured session exercises certificate negotiation the way an IOModule or
serviceBinding will. The server must trust-list the client certificate
first, and a rejection tells you so explicitly.
dcs opcua read opc.tcp://192.168.10.50:4840 "ns=4;s=Tank1.Level" \
--security-policy Basic256Sha256 --cert client.pem --key client.key \
--server-cert-pin 6f3a…9c04
dcs opcua write opc.tcp://192.168.10.50:4840 "ns=4;s=Tank1.Setpoint" 72.5 \
--security-policy Basic256Sha256 --cert client.pem --key client.key
dcs opcua subscribe opc.tcp://192.168.10.50:4840 "ns=4;s=Tank1.Level" \
--interval 500ms --security-policy Basic256Sha256 --cert client.pem --key client.key
Shared flags (all subcommands):
| Flag | Description |
|---|---|
--security-policy |
Security policy short name (None, Basic256Sha256, …) |
--security-mode |
Message security mode (None, Sign, SignAndEncrypt; defaults to SignAndEncrypt when a policy other than None is set) |
--auth |
User token type: anonymous (default), username, certificate |
--username, --password |
Credentials for --auth username (password also via DCS_OPCUA_PASSWORD) |
--cert, --key |
PEM client certificate and private key (required for Sign/SignAndEncrypt and --auth certificate) |
--server-cert-pin |
Expected SHA-256 fingerprint of the server certificate; the connection is refused on a mismatch |
--timeout |
Connect and per-request timeout (default 10s) |
--insecure |
Connect with None/None in place of an explicit tuple |
Subcommands:
| Subcommand | Purpose |
|---|---|
endpoints <url> |
List every endpoint with its security policy, mode, level, user token types, and server certificate fingerprint (the --server-cert-pin value) |
browse <url> |
Walk the address space from --node (default i=85, ObjectsFolder) down --depth levels, printing node IDs, browse names, data types and current values — the fields an IOModule or serviceBinding CR needs. --max-nodes bounds the walk and says so when it truncates |
read <url> <node-id>… |
Read the given nodes in a single Read service call |
write <url> <node-id> <value> |
Write a value and read it back. Without --type (Bool, Int, UInt, Double, String), the type is inferred from the node's current value |
subscribe <url> <node-id>… |
Subscribe at --interval (default 1s) and print data changes until interrupted |
Each failure mode is distinguished: a security tuple the server does
not offer points you at endpoints, an untrusted client certificate names the
server's trust list, a rejected identity names the credential flags, and an
unknown node ID points you at browse.
dcs backup¶
Export DCS custom resources to YAML files, and the historian time-series database to a plain-SQL dump, for backup and disaster recovery.
dcs backup crds [-o <file>] [-s <site>] # all DCS custom resources
dcs backup audit [-o <file>] [-s <site>] # all AuditRecord CRs (21 CFR Part 11)
dcs backup historian [-o <file>] # the historian database, via pg_dump
dcs backup verify <file> # integrity + completeness, before every restore
| Flag | Short | Description |
|---|---|---|
--output |
-o |
Output file path (default: dcs-crds-<timestamp>.yaml / dcs-audit-<timestamp>.yaml / dcs-historian-<timestamp>.sql) |
--allow-partial |
Accept an export that could not read every kind, or a dump that was cut short (exit 0 on a known gap) |
--site/-s is optional for backup: without it, all sites are exported.
Every export ends with a completeness footer, and the command exits non-zero
when the gateway could not read a kind (usually a missing rule in its
ClusterRole). The file is still written, so --allow-partial accepts a known
gap during an incident. Verification with dcs backup verify re-checks the
same footer alongside the SHA-256, because an intact file can still be
missing a kind. See
Backup and Recovery.
dcs backup historian¶
dcs backup historian is the one backup subcommand that does not go through
the gateway. It runs pg_dump inside the historian database's primary Pod and
streams the result to the local file. What it needs is therefore a kubeconfig
with exec rights in the namespace the chart is installed in, and no gateway
token at all. No gateway route could serve it: the gateway proxies historian
queries to the collector, and only the database Pod holds both the credentials
and a pg_dump built against its own server version.
| Flag | Description |
|---|---|
--kubeconfig |
Path to a kubeconfig file (default: $KUBECONFIG or ~/.kube/config) |
--context |
Kubeconfig context to use (default: the kubeconfig's current context) |
--system-namespace |
Namespace the chart is installed in (default: discovered from the cluster) |
--cluster |
CloudNativePG cluster to dump, required when the namespace holds more than one |
Four things it settles that an out-of-band kubectl exec leaves to the
operator:
- It dumps the primary. A dump taken from a standby succeeds and is as stale as that standby's replication lag, which is the quantity the operator is trying to bound. A cluster carrying only replicas is refused.
- It refuses an ambiguous namespace. The disaster-recovery procedure
stands a restore cluster beside the live one, so during the incident that
matters most there are two primaries. Name one with
--cluster. - It says whether the file is whole. The dump is streamed out of a Pod,
and an evicted Pod or a dropped connection leaves a file that is valid SQL
as far as it goes and restores without complaint. The command checks for
pg_dump's own completion marker and exits non-zero without it. So doesdcs backup verify, which re-reads the marker from the file. - It writes the integrity manifest. A shell redirection writes none, so an out-of-band dump could not be verified before a restore at all.
The dump covers every site. The historian is one database for the whole
install and the site is a column in it, so --site cannot narrow this export
and the command says so when one is passed. An installation pointed at an
external PostgreSQL through historian.database.externalURL has no Pod to
exec into. The command names that case in its refusal, so the answer is never
a bare "nothing found".
The output is plain SQL, restored with psql. That is the format the
DR runbook drill
exercised, and a custom-format dump would need TimescaleDB's
timescaledb_pre_restore() and timescaledb_post_restore() around
pg_restore without buying the operator anything.
dcs restore¶
Restore DCS custom resources from a multi-document YAML backup file created by
dcs backup, applying each document via the gateway apply endpoint.
dcs restore crds -f dcs-crds-20260315-120000.yaml
| Flag | Short | Required | Description |
|---|---|---|---|
--file |
-f |
yes | Path to YAML backup file |
Each document is reported as applied, skipped, or failed, and the command exits non-zero only when something failed. Skips are export-only kinds that the backup captures as evidence but the gateway does not re-apply. See Backup and Recovery for the list and the reason each carries. Documents throttled by the gateway's write budget are retried with backoff, and the failure count leaves them out.
dcs edit¶
Open the DCS visual editors (ST / SFC / FBD, recipes, physical model) against a local working tree of CRD YAML files, with no Kubernetes cluster in the loop. This is filesystem authoring mode. Every Save writes the edited resource back to its YAML file on disk: no cluster, no etcd, no network required. The editor is git-agnostic. Review and commit changes with your own git tooling.
Features that need live equipment (runtime tag values, diagnostics, historian
trends) are unavailable and grayed out. Connect a cluster with dcs ui to
use them.
dcs edit [directory] # defaults to the current directory
| Flag | Default | Description |
|---|---|---|
--port <n> |
8200, falling back to ephemeral | Local listen port |
--bind-address <ip> |
127.0.0.1 |
Listen address; keep loopback for single-user mode |
--no-browser |
off | Print the URL but do not auto-open a browser |
Examples:
# edit the YAML tree in ./plant, opens a browser
dcs edit ./plant
# current directory, fixed port, no auto-open (useful for SSH-forwarded UIs)
dcs edit --port 8200 --no-browser
dcs diff¶
Render the human-readable semantic diff between two versions of a CRD YAML file ("Mash Hold: hold time 30 min -> 45 min"), using the gateway's own diff renderers. Convenient as a git difftool. Informational only: it creates no audit record and no electronic signature, and the 21 CFR Part 11 review-of-record stays in the connected Promote / ChangeRequest flow.
Each file must contain a single resource. Exit status is 0 when the files are
semantically identical and 1 when they differ, so dcs diff composes in
scripts like diff and git diff --exit-code.
dcs diff <old.yaml> <new.yaml>
dcs diff --format json old.yaml new.yaml # machine-readable
| Flag | Description |
|---|---|
--format |
Output format: semantic (default) or json |
dcs migrate¶
Rewrite legacy phase / phase-template manifests to match the current schema. Each subcommand handles one breaking change.
dcs migrate readback¶
Migrates parameters[].readback and outputs[].source to the current model
(issue #250): readbacks are hoisted into separate outputs, WriteActual()
calls are rewritten into bare ST assignments, and outputs[].captureOn is
dropped. Pass one or more paths (file or directory). Without --write the
rewritten content is printed to stdout. With --write files are replaced in
place.
dcs migrate readback ./templates/ # preview
dcs migrate readback --write ./templates/ # rewrite in place
| Flag | Description |
|---|---|
--write |
Rewrite files in place (the default prints to stdout) |
dcs ui¶
Boot the gateway UI on this laptop against the active kubeconfig context
and open a browser. The CLI binary embeds the static UI assets. A
single dcs install is therefore the whole laptop-mode runtime: no extra
container, no kubectl proxy, no separate gateway binary needed.
dcs ui [flags]
This is the entry point for topology D:
each engineer runs the UI against their own kubeconfig context (kind,
k3d, Docker Desktop, or a remote dev cluster they have credentials
for). Auth mode is none and the local user is treated as a cluster
admin. Cluster authorization is whatever your kubeconfig grants.
| Flag | Default | Description |
|---|---|---|
--kubeconfig <path> |
$KUBECONFIG or ~/.kube/config |
Kubeconfig file to load |
--context <name> |
current-context | Kubeconfig context to use |
--system-namespace <ns> |
discovered from the cluster | Namespace the DCS operators run in, which the system-health rollup queries. Discovered from the app.kubernetes.io/part-of: cloud-native-dcs label the chart applies; pass it explicitly when a cluster carries more than one install. |
--port <n> |
8200, falling back to ephemeral | Local listen port |
--bind-address <ip> |
127.0.0.1 |
Listen address (loopback by default for security) |
--no-browser |
off | Print the URL but do not auto-open a browser |
Examples:
# default kubeconfig and context
dcs ui
# specific cluster
dcs ui --kubeconfig ~/.kube/dev --context kind-dev
# fixed port, no auto-open (useful when forwarded over SSH)
dcs ui --port 8200 --no-browser
When running inside a Pod (pod-mode gateway), the in-cluster service
account is auto-detected via /var/run/secrets/kubernetes.io/serviceaccount/token
and dcs ui is unused. The deployed dcs-gateway binary is the
production entry point.
dcs config¶
Manage persistent CLI configuration.
dcs config set-gateway <url> # Set default gateway URL
dcs config set-site <name> # Set default site
dcs config set-header <name> <value> # Set an extra HTTP header sent with every gateway request
dcs config unset-header <name> # Remove an extra header
dcs config show # Show current configuration
set-header is for deployments that front the gateway with an
authenticating proxy expecting credential headers. The value may reference
an environment variable with ${VAR} syntax. It is expanded when the CLI
runs, so secrets stay out of the config file. show redacts literal header
values and prints ${VAR} references as-is. See
Security Operations
for the full flow.
dcs config set-header My-Proxy-Client-Secret '${PROXY_CLIENT_SECRET}'
dcs admin heal-site¶
Audit a site and recreate any missing tenant resources (RBAC, ResourceQuota, NetworkPolicies, secrets, scenario manifests). The heal path is the same idempotent provisioning pipeline that runs at sandbox provisioning time, exposed here so operators can trigger it without forcing the user through a browser re-login.
dcs admin heal-site <siteName>
Authorization:
- Admins (
dcs-admingroup) may heal any site. - Non-admins may only heal the site matching their
dcs-site-*group (self-heal).
If the Site CR does not yet exist, heal-site falls through to the full
bootstrap provisioning path and returns state=provisioning with
existed=false.
dcs version¶
Print the CLI version.
dcs version