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:
- the
--server <url>flag; - the
OPSCHAIN_SERVERenvironment variable; - your active context (set by
opschain login, switched withopschain context use); - 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 ofopschain 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 withopschain 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 doctorshows it andopschain state resetclears a project's slice (opschain docs storage, "Local mode"). - Resolve secrets through its own local secret store
(
opschain secret set|get|ls), so asecret-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)andnode.list(glob)read the run's own snapshot (the working copy, or the--refcommit) 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 thesecret-env://NAMEreference 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,triggersandadminfamilies refuse by name without a server target. - No approvals and no inbox. A
wait:step prompts you in your terminal (or--approve-allanswers 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 now | local (--local) |
| prove a commit before pushing it | local (--local --ref <ref>) |
| run against a real node, with the record kept | server (lesson 3.1) |
| be approved, notified, audited, or verified | server |
| try a pack action offline | local (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:
| Posture | What it is | What 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 store | Developing 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 GUI | Running, 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
--localrun 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, thenOPSCHAIN_SERVER, then the active context, then local;--localforces 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).