Skip to main content
Version: v5.6.1

The opschain CLI

Included from Basic tier

opschain is one binary carrying every surface: the operator and developer command tree, the server itself (opschain server start), the runner (opschain runner) and the embedded reference documentation (opschain docs). This page covers the CLI as a component — global flags, targeting, authentication, output and exit conventions. Each command's own manual lives under docs/reference/cli/ and is read with opschain docs cli/<command-path> (e.g. opschain docs cli/runs-create).

Global flags​

Persistent flags, accepted by every command:

FlagMeaning
-o, --output table|json|yamlOutput format (default table). A machine format suppresses tables, live rendering and progress chatter.
-q, --quietSuppress progress output; print identifiers and errors only.
--home <dir>The opschain home directory (default $OPSCHAIN_HOME, else the per-OS data directory).
--server <url>Target server URL (overrides OPSCHAIN_SERVER and the active context; default: local mode).
--localRun against the local repository, ignoring the active context.
--debugShorthand for --log-level debug.
--log-level debug|info|warn|errorMinimum log level (default info).
--log-file <path>Write logs to a rotated file instead of stderr (default rotation 100 MB / 30 days / 10 backups; server start re-reads rotation from the config.yaml logging: block).
--no-keychainNever use the OS keychain for secrets/tokens; use key/credential files instead.

The home directory and what lives in it​

--home → $OPSCHAIN_HOME → the per-OS default: ~/Library/Application Support/opschain (macOS), %LOCALAPPDATA%\opschain (Windows), $XDG_DATA_HOME/opschain else ~/.local/share/opschain (Linux). It holds the local store (runs, logs, artifacts — managed with opschain state, see opschain docs cli/state), the secret store, contexts.json, the credentials/ token-file fallback, and the runner's state directory (<home>/runner).

Contexts and targeting​

Every invocation resolves one execution target, in precedence order:

  1. --server <url> (an ad-hoc target),
  2. $OPSCHAIN_SERVER,
  3. the active named context (contexts.json in the home directory),
  4. otherwise local mode — the repository and per-user store on this machine.

--local short-circuits the whole chain — the escape hatch back to the local repository on a machine whose active context would otherwise make the local catalog unreachable. Combining it with --server is refused as contradictory. opschain context shows the resolution; opschain context use <name> switches the active context (local returns to local mode); opschain context list lists them. Contexts are created by opschain login --server <url> --context <name>.

Local vs server lanes​

Some commands are inherently local and never call an API: init, learn, docs, eula, version, state, config, context, server start / server configure / server backup / server restore, and doctor's host probes. opschain runner talks to the server named by its own --server flag, not the context. Everything else follows the resolved target: in local mode the resource verbs act on the local repository and store; against a server, run inspection, logs, artifacts and the catalog are served remotely, host-scoped services (the secret store, doctor) stay local, and store-backed verbs the server cannot serve refuse loudly instead of silently acting on the local store. opschain api sends raw requests to the targeted server (opschain docs cli/api).

Authentication and token storage​

opschain login verifies a token against the targeted server, stores it, and records a named context. With --username the credentials (password prompted, or read from stdin) are exchanged for a session token pair via the v2 AuthService Login procedure. Tokens are stored per normalized server URL in the OS keychain (service opschain), falling back to 0600 files under <home>/credentials/ when the keychain is unavailable — or always with --no-keychain. A stored refresh token (kept under a derived <server>#refresh slot in the same store) arms automatic renewal: on a 401 the access token is rotated into a fresh pair, persisted back, and the call retried once. opschain logout removes the stored tokens; opschain whoami shows who the stored token authenticates as; opschain passwd changes a local user's password. The admin plane has its own opschain admin login/logout pair.

Output conventions and exit codes​

  • Tables are the human default; -o json / -o yaml render the same data as one machine-readable document (YAML is derived from the JSON encoding, so the two always agree). Streamed sequences (--watch, --follow) render as NDJSON under json and ----separated documents under yaml.
  • TTY detection decides live rendering; OPSCHAIN_TTY=always|never overrides it and TERM=dumb forces plain output.
  • Exit codes: 0 OK, 1 run/command failed, 2 usage error, 3 cancelled, 4 timeout. A usage error also prints Run 'opschain --help' for usage.

Filtering list output (--filter)​

Every list command carries a repeatable --filter flag with one shared grammar — each command's manual page names the flag, this section defines it once:

--filter <column>=<value> keep rows whose column matches the value
--filter <column>!=<value> keep rows whose column does NOT match
--filter <column>=<a>,<b> comma = any-of (membership in the set)
  • Columns are the printed table headers, lowercased, with spaces, dashes and slashes folded to underscores (LAST SEEN → last_seen, CREATED-BY → created_by, STARTED/FROM → started_from) — the vocabulary is discoverable from the command's own output, and matches the machine formats' key style. A column a --wide flag adds is filterable only when --wide is given (the vocabulary is what the invocation prints). An unknown column is a usage error naming the valid columns for that command.
  • Matching is whole-cell and case-insensitive. A value without * is plain equality — never a substring match. * matches any run of characters (including none): --filter action=*deploy* finds the substring, --filter target=demo/* the prefix. The cell compared is exactly what the table prints (so - for an empty cell, RFC 3339 timestamps, true/false booleans).
  • Repeated terms AND; the only OR is the comma set within one term. Nothing richer exists — no ranges, no cross-column OR, no regular expressions.
  • Filters run before any --limit/--tail truncation and select the same rows whichever output format renders them (-o table|json|yaml).
  • Filters are applied client-side. Commands whose dedicated flags narrow server-side (e.g. events --errors --since, audit --type --username, triggers firings --status, admin runners list --group) still send only those flags to the server; --filter then narrows the fetched rows. Each command's manual page says which of its flags push down.
opschain runs list --filter status=error --filter action=*deploy*
opschain runs list --filter status=error,queued --filter target!=demo/*

The embedded reference documentation​

The reference set — component pages like this one, the data dictionary and the CLI manual — is embedded in the binary, so it always matches the opschain version you are running:

  • opschain docs prints the index; opschain docs <slug> one page.
  • opschain docs search <term> full-text searches the set.
  • opschain docs export [-o <dir>] writes the pages to disk (default directory opschain-reference) for intranets or printing.
  • Every command whose manual ships in the set carries a help trailer — Full manual: opschain docs cli/<slug> — so --help stays terse and the depth is one command away.
  • opschain docs cli/context / cli/login / cli/whoami — targeting and authentication commands in full.
  • opschain docs cli/state — managing the local store.
  • opschain docs cli/server-start / cli/server-configure — the server lane of the same binary.
  • opschain docs cli/runner — the runner lane.
  • opschain docs cli/api — raw API access against the targeted server.
  • opschain docs cli/docs — the docs command itself.