CLI Quick Start
The csy command-line interface is a first-class, supported client — not a developer scaffold. It authenticates against the same schemes the browser uses, drives the same server-side UI session the browser drives, and runs declarative scenarios for CI. This page walks you from CLI access to rendering a view in your terminal and importing a tenant file.
For the full command reference, see the CLI client guide. For a first run-through in the free sandbox, see the Quick Start.
What you will do
Section titled “What you will do”- Get the CLI and point it at an endpoint.
- Authenticate — interactively (OIDC) or with an API key for automation.
- Open
csy uiand render a view in the terminal. - Import a tenant configuration from YAML.
Prerequisites
Section titled “Prerequisites”- CLI access, arranged through a beta engagement (below).
- A Consystence endpoint you can reach — a cloud cell or a site server.
- Credentials for that endpoint: a member account (interactive login) or an API key (automation).
Get the CLI
Section titled “Get the CLI”The CLI is a single .NET 10 binary named csy. CLI access is arranged through a beta engagement: contact us.
Running csy with no arguments prints a branded splash; csy --help lists the command groups, among them account, ai, api-key, auth, config, context, controller, display, electrical, instance, org, sequence, server, site, status, tenant, trend-import, and ui. Live operational reads — current tag values, historian trends, active alarms, the command audit — live under the instance and site groups; see the CLI reference.
Point the CLI at an endpoint
Section titled “Point the CLI at an endpoint”The CLI works in contexts. A context is one endpoint — its server URL, its type (cell, site, edge, or account), an optional tenant slug, and its own stored credential. The auth-mode is derived from the type, so you never pick a login flow by hand.
# Define a context for a cloud cellcsy context add demo \ --server https://acme.consystence.com \ --type cell \ --tenant acme
# Make it currentcsy context use demo
# Inspect what is definedcsy context listcsy context currentAuthenticate
Section titled “Authenticate”Interactive login (OIDC → Bearer)
Section titled “Interactive login (OIDC → Bearer)”For a cell context, csy auth login runs OIDC against Entra External ID and stores a Bearer token. With a browser present it uses an authorization-code + PKCE loopback flow; for headless hosts add --device for the OIDC device-authorization grant (RFC 8628).
# Headless / SSH — enter the code at the displayed URLcsy auth login --deviceInitiating device code flow...
Enter code: ABCD-EFGHAt: https://microsoft.com/devicelogin
Waiting for authentication...Login successful (context 'demo').Token expires at: 2026-06-29 11:42:00ZThe verification URL is taken verbatim from the identity provider’s device-authorization response — for the Consystence CIAM tenant (Entra External ID) that is Microsoft’s device-login page, not a consystence.com address.
The refresh token is stored in your OS keyring (Windows Credential Manager / macOS Keychain / libsecret), with a plaintext-file fallback only where no keyring exists. The short-lived access token is refreshed automatically against the identity provider — no re-login.
For a site context the same command takes the site sign-in path, which needs an email and PIN:
Check and decode your session at any time:
csy auth status # mechanism + credential source (no server call; never prints the credential)csy auth whoami # decode the stored token locally (oid, tid, preferred_username)csy auth logout # clear this context's credential, keep the context definedNon-interactive (API key)
Section titled “Non-interactive (API key)”For CI, scripts, and partner automation, use a tenant API key. A tenant owner or admin creates keys in the web console’s API keys view, with csy api-key create, or at POST /api/admin/api-keys; each key is shown in plaintext exactly once and prefixed csk_. A key is read-only by default: it reads tenant and site data, its role decides which reads it may make, and every write is refused. An operator key (--class operator) covers one person and one native site for at most 30 days, and can issue commands and acknowledge alarms on that site. See API keys.
The key is sent as the X-Api-Key header. Provide it three ways, in precedence order:
# 1. Explicit flag (wins over everything — an operator overriding CI)csy --token csk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx auth status
# 2. Environment variable (typical for CI)export CONSYSTENCE_TOKEN=csk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxcsy auth status
# 3. Stored in the context configAn API key is the credential itself — there is no refresh, and it is never printed back by auth status.
Render a view in the terminal
Section titled “Render a view in the terminal”csy ui is the CLI renderer: it consumes the server’s semantic UI tree over the wire format — a peer of the browser’s wire renderer, which consumes the same L1/L2 protocol on the same /hubs/ui-wire hub — so a view renders as text instead of DOM. It connects over SignalR to /hubs/ui-wire with the credential the CLI already resolved and drives the same server-side UI session the browser drives. For the architecture, see the multi-renderer pipeline.
flowchart LR CLI["csy ui<br/>(terminal)"] -->|"SignalR /hubs/ui-wire"| Hub["UI wire hub"] Hub --> Session["Server-side<br/>UI session"] Session -->|"wire format (L1 render, L2 patch)"| Hub Hub -->|"text patches"| CLI
Open the REPL, optionally with an initial route:
csy ui admin/api-keysInside the REPL these verbs are available (type help to list them):
| Command | Action |
|---|---|
goto <route> | Open a view (e.g. goto admin/api-keys) |
show | Re-render the current view |
inspect | Dump the semantic tree (ids, pointIds, types) |
actions | List invocable actions on the current view |
action <n|id> | Invoke an action by index or actionId |
chat <message> | Message the assistant (needs a chat view, e.g. goto assistant/chat) |
refresh | Poll the server for changes |
wait [seconds] | Watch for changes (default 30 s) |
wait until <p> | Block until a predicate holds: rows <pointId> <n> | row-absent <id> | row-present <id> | view <id> |
quit / exit | Leave the REPL |
For CI, run a view non-interactively from a declarative YAML scenario instead of the REPL:
csy ui --script scenario.csy.yaml --no-colorScript mode is single-shot and deterministic, and exits with a meaningful code: 0 = all steps passed, 1 = a step failed, 2 = a scenario or connect error. This is the surface that replaces browser click-throughs for integration testing.
Import a tenant file
Section titled “Import a tenant file”A tenant configuration (org, sites, devices, tags) is portable as a single YAML file. Importing it targets an existing tenant; the tenant’s slug is part of the route (the --org flag) and you must be its owner or admin. To get a file to start from, export one from a site you can reach (csy tenant export, at the end of this section), edit it, and import it back.
First select the tenant (or pass --org on each call):
csy tenant select acmecsy tenant currentCheck the file before importing it. --dry-run sends it to the server, which parses, validates and diffs it against the current model (plant-affecting changes first) and changes nothing. The plan it prints replaces any earlier plan for the tenant that was never applied. With no tenant selected, or against a site server or an older server, the CLI validates the file locally only and says so.
csy tenant import tenant.yaml --dry-runParsed: org=acme, 2 site(s), 14 device(s)Server dry run: plan <plan-id> (import) for tenant acme, site(s) SITE-01, SITE-02. Nothing was changed. <n> plant-affecting, <n> access, <n> policy, <n> model-only, <n> presentation, <n> declared but not applied.…To apply exactly this plan (before <expiry> UTC, and only while the model is unchanged): csy tenant import-apply <plan-id> --org acme --confirm "<phrase>"To discard it instead: csy tenant import-discard <plan-id> --org acmeA plan with blockers exits non-zero, so csy tenant import tenant.yaml --dry-run && csy tenant import tenant.yaml stops at a blocker.
Then import for real (use --force to overwrite existing entities, and --org to override the selected tenant):
csy tenant import tenant.yaml --org acmeParsed: org=acme, 2 site(s), 14 device(s)Import successful.The server rejects a file whose org.slug does not match the route, so a mis-targeted import fails cleanly rather than writing to the wrong tenant. To produce a YAML file from a live site, use the inverse:
csy tenant export --site SITE-01 --org acme --output tenant.yamlNext steps
Section titled “Next steps”- CLI client guide — full command reference and scripting patterns.
- Quick Start — a first walkthrough in the free sandbox.
- Authentication — the credentials behind
auth login. - Cloud onboarding — sign in, get a free sandbox, or join your organisation’s tenant.