Skip to main content
Version: v5.7.0

0.2 Local mode and server mode

Included from Basic tier

After this you can: say which lane a command runs on, what the local lane can and cannot evidence, tell the three postures the binary runs in apart, and choose the lane for the job.

Before you start — tick each one:

  • Lesson 0.1 — Install and sign in (opschain learn 0.1)

In the GUI: nothing — local mode has no GUI; the server lane is the one the browser shows.

Every opschain command runs on one of two lanes. The local lane runs work from the repository in your current directory, on your machine, with no server. The server lane talks to an OpsChain server's API, which keeps the record. The two share one binary, one action-file format and most verbs — and differ in exactly the things that make a run evidence. This lesson draws that line so you always know which side of it you are on.

1. How a command picks its lane​

The target resolves in this order:

  1. the --server <url> flag;
  2. the OPSCHAIN_SERVER environment variable;
  3. your active context (set by opschain login, switched with opschain context use);
  4. otherwise, local mode.

The global --local flag forces local mode for one invocation, ignoring the active context — the usual way to iterate in a repository while you are logged in to a server. See which lane you are on:

opschain context list
NAME SERVER ACTIVE
local (local mode)
opschain-dev http://127.0.0.1:8443 *

With opschain-dev active, opschain runs list reads the server; opschain runs list --local reads your machine.

2. What the local lane can do​

  • Run actions off your working tree — opschain run <action> --env dev (the alias of opschain runs create change <action> --env dev --local) snapshots your working copy (uncommitted edits included) and runs it attached to your terminal, exit code as outcome. --ref <git-ref> runs a clean commit instead. Lesson 2.1 starts here.
  • Plan anything with --plan --local, and browse the catalog your repository defines with opschain actions list --local.
  • Keep its own history: runs, steps, logs, artifacts and the property layers runs discovered, in a per-user SQLite store under your opschain home (<opschain home>/local/opschain.db) with its own generated keyset (local/keys.env) encrypting sensitive values at rest. Nothing to start, nothing to configure; opschain state doctor shows it and opschain state reset clears a project's slice (opschain docs storage, "Local mode").
  • Resolve secrets through its own local secret store (opschain secret set|get|ls), so a secret-vault:// reference works unchanged on your laptop.
  • Mount the bundled common pack and run its actions offline (lesson 2.4); git-sourced packs mount from the local pack cache after one opschain packs fetch.
  • Read the repository from expressions — node.content(path) and node.list(glob) read the run's own snapshot (the working copy, or the --ref commit) under the same rules as a server (opschain docs expressions).
  • Pass your shell's variables into steps with --env-passthrough NAME,NAME, and source secrets from the environment with the secret-env://NAME reference scheme — the CI pattern (lesson 3.5).
  • Retry a failed change or workflow run with opschain runs retry.

The target of a local run is an environment code from your repository's .opschain/config.yaml — not a node on any server.

3. What the local lane cannot do​

  • No users and no sign-in. Nothing records who ran a local run; there is no whoami, no identity, no access rules.
  • No audit history. A local run keeps its own step transitions and logs, but the estate-wide audit events a server records (api:auth:login, api:projects:create, every approval decision — lesson 5.1) do not exist here.
  • No estate. No nodes, templates, triggers, schedules, maintenance windows or runners — the nodes, properties show|edit|history, settings, triggers and admin families refuse by name without a server target.
  • No approvals and no inbox. A wait: step prompts you in your terminal (or --approve-all answers it); approval policies, quorums and the approvals inbox are server things (lesson 2.3).
  • No notifications, no chains across runs, and no change: steps that spawn a child change on another node (lesson 2.2) — local mode refuses those by name.
  • No GUI. The browser shows a server.

The consequence that matters for the Academy: a local run is not evidence. The Academy agent decides whether an exercise was done by reading a server's state and audit events, so every verified exercise — including the authoring ones — ends with work on a server. --local is where you get it right first.

4. Choosing the lane​

You want to…Lane
write or fix an action and see it run nowlocal (--local)
prove a commit before pushing itlocal (--local --ref <ref>)
run against a real node, with the record keptserver (lesson 3.1)
be approved, notified, audited, or verifiedserver
try a pack action offlinelocal (the bundled common pack)

Lessons 2.1–2.8 stay on the local lane; lesson 3.1 is where the same action first runs on a server.

5. Three postures, not two​

"Server" above means a server on PostgreSQL. The same binary also starts a server with no store configured, on an embedded SQLite database — which makes three postures, each for a different job:

PostureWhat it isWhat it is for
The local lane (--local)The engine in your terminal: one implicit principal, your repository's .opschain/ tree as the estate, history in <opschain home>/local/opschain.db, secrets in the home's local secret storeDeveloping actions and workflows, evaluating them before they reach a server, and CI jobs (--local --approve-all -o json, the exit code as the verdict)
A server on the SQLite store (server start, no store)The run engine, the runner and agent fleet, licensing and the home's local secret store behind the HTTP API — nothing to provision. Bound to loopback (127.0.0.1:8443) unless --listen says otherwise, a startup notice naming the posture, and no GUI (the root URL answers a page saying the GUI needs PostgreSQL)Development harnesses and tests: GUI development against its API, end-to-end suites, a runner-fleet playground
A server on PostgreSQL (store: postgres://…)The product: users and access rules, the estate, templates, workflows, triggers, notifications, governance, the audit history and the GUIRunning, governing and evidencing real work

Say it plainly: a server on the SQLite store is not an evaluation posture for the estate features. It holds no users, no estate, no templates, no workflow catalog, no notifications and no governance — every one of those families answers "PostgreSQL required" by name, there is nobody to sign in as, and the GUI is not served. To evaluate what the Academy teaches from lesson 1.1 on, start a server on PostgreSQL — lesson 0.1 shows the one-command way, the opschain-trial Docker Compose; to try an action or a workflow with nothing to provision at all, the local lane is the posture built for it.

Check yourself​

  • Name two things a --local run cannot produce that a server run does (hint: who ran it, and who was told).
  • Which of the three postures would you pick to try an action with nothing to provision, and which to evaluate approvals and notifications?

What you learned​

  • A command's lane is --server, then OPSCHAIN_SERVER, then the active context, then local; --local forces local for one call.
  • Local mode runs your working tree with its own store, keyset and secret store, and no server.
  • Local mode has no users, no audit history, no estate, no approvals, no notifications and no GUI — so a local run is never evidence.
  • Three postures: the local lane (develop, evaluate actions and workflows, CI), a server on the SQLite store (a development harness — the run engine, the fleet, licensing and secrets behind the API; loopback-bound, labelled at startup, no GUI, no estate and not an evaluation posture), and a server on PostgreSQL (the product).
  • Author and rehearse locally; run, govern and verify on a server.

Next: lesson 0.3 — Your tools: contexts, output formats, the API, the docs (opschain learn 0.3), or back to your track (opschain learn).