Skip to main content
Version: v5.7.0

3.1 Your first change

Included from Basic tier

After this you can: create a change against a node, follow it to completion, list and inspect its run, and read its logs.

Before you start — tick each one:

  • Lesson 0.1 — Install and sign in (opschain learn 0.1)
  • Lesson 1.2 — Build and change your own (opschain learn 1.2)

One more thing the checklist cannot tick for you: the project needs a git remote the server can fetch before its first change — that is where the server reads the action from when the target is a project or an environment. Lesson 3.3 (opschain learn 3.3) explains remotes and the identity policy in full; section 1 below gives you the one command you need now, so you can do that lesson properly afterwards.

In the GUI: the Actions tab on a node page opens the Run form, and the run page follows the change with its live log viewer.

A change is one action executed against one estate node, with the server keeping the record: who ran what, where, when, with which inputs, and every log line. In lesson 2.1 you ran an action on your own machine; this lesson runs the same hello action on a server, where runners execute it and the record outlives your terminal. The outcome you are working towards is one successful change you can find again by its id.

1. Give the project a remote and an environment​

On a server the action comes from somewhere the server can read. For a project or environment target that is the project's git remote: the repository you scaffolded in lesson 2.1 (opschain init created .opschain/actions/hello.yaml), pushed somewhere the server can fetch it.

opschain git-remotes create acme --name origin \
--url https://git.example.com/acme/estate.git \
--username ci-bot --password-env ACME_GIT_TOKEN
created git remote acme/origin (01a13f0e-…-example)

The password rides an environment variable, never the command line (lesson 3.3 covers every credential shape). A remote is unusable until the git identity policy allows it: a security administrator allow-lists it, and marks it the default identity for the project, with

opschain security git-policies put --project acme --remote origin --default
created git identity policy entry acme/origin (default)

— the change in step 2 names that remote and revision in its payload (git_remote_name: origin, git_rev: main), and the policy is what lets the server act on it. Lesson 3.3 explains the policy in full.

Two more things the record will show you. The change runs as the identity that creates it, so sign in as an everyday operator with rights on the project (lesson 7.2 creates one) rather than the bootstrap admin, whose every act is break-glass. And the server does not execute the step itself: a runner does (lesson 6.2 starts one) — with none online the change queues, by name, until one is.

Then the environment the change targets, exactly as lesson 1.2 built it:

opschain nodes create acme/environments/dev
created environment /projects/acme/environments/dev (01a13f10-…-example)

2. Create a change and follow it​

On a server the positional argument is the node path and --action names the action. --follow keeps the CLI attached: it polls the change, prints each status transition, and exits with the run's outcome (0 success, 1 failed, 3 cancelled, 4 timed out):

opschain runs create change acme/environments/dev --action hello --follow
created change 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33 (hello on acme/dev) — pending
run 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33 pending
run 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33 pending → running
run 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33 running → success

The first line is the change the server created; the rest are its transitions. The target reads acme/dev — the CLI renders a run's target as <project>/<environment> (the node path's codes, the /projects/…/environments/ scaffolding dropped); you still name the full path when you create. Without --follow you get the first line only and the change runs on regardless — the server executes it on a runner, not in your terminal. If the line reads queued — no online runner currently serves this run, no runner is online for the target yet: lesson 6.2 starts one.

Where the action comes from depends on the target: a project or environment target runs an action from the repository behind the project's git remote (the hello above); an asset runs its template's actions (lesson 3.4). A project with several remotes names the one to use with a payload file:

opschain runs create change acme/environments/dev --action hello -f payload.yaml
# payload.yaml
git_remote_name: origin
git_rev: main

Useful creation flags, all overlaying -f:

  • --override k=v — property overrides for this run only. Dots nest and values parse as JSON when valid: --override app.replicas=3. (The layered property model is lesson 1.3.)
  • --metadata k=v — free-form metadata recorded on the change, e.g. --metadata comments="ticket OPS-123".
  • -i key=value — a typed run input the action declares (lesson 2.2).
  • --skip-step <path> — skip a step and its subtree (repeatable); --starting-step <path> skips everything before that step.

3. List and inspect runs​

opschain runs list
ID KIND ACTION TARGET STATUS CREATED DURATION
01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33 change hello acme/dev success 2026-10-12T08:00:14Z 4.1s

opschain runs show <run-id> gives you the header and the step tree:

opschain runs show 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33
Run: 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33
Kind: change
Action: hello
Target: acme/dev
Status: success
Commit: 5d5af8d9c82be2f9c87cf001e041e9e8fd112ae0
Created: 2026-10-12T08:00:14Z
Started: 2026-10-12T08:00:15Z
Finished: 2026-10-12T08:00:19Z
Duration: 4.1s

✔ hello — success (4.1s)
└─ ✔ say_hello — success (3.8s)

Commit is the exact revision the server pinned from the remote — the record says precisely which code ran. runs show --events appends the audit trail inline (creation, every step transition, every approval or cancellation with its actor); the same trail is in the events feed, where every row carries the run's correlation id — lesson 5.1 reads it there. As everywhere, -o json turns any of this into a stable machine shape.

4. Read the logs​

opschain logs 01a13f12-7c1e-7a40-9e0d-4b2f8e1d2c33
[hello/say_hello] hello from opschain

Lines are prefixed [step/path] so interleaved steps stay readable. The variants you will use most:

opschain logs <run-id> --step hello/say_hello # one step's lines only, prefix dropped
opschain logs <run-id> --follow # stream live until Ctrl-C
opschain logs <run-id> --download run.log # write to a file instead

For big logs, --limit reads one page and prints a --cursor to resume from. The same command is registered as opschain runs logs, a running run's output is readable while it runs, and a workflow run's id plays back every run its steps spawned (lesson 4.2).

Check yourself​

  • Run opschain runs show <run-id> --events for the change you just created: which event type records it finishing, and what status does opschain runs list show for it?
  • Does opschain runs show report success, and does opschain events --filter node=*dev* show api:changes:create, api:steps:success and api:changes:success on your environment, in that order? That is exactly what the Academy's first-governed-change exercise reads — after the remote, the identity policy, the payload's git_remote_name/git_rev and a runner were in place.
  • Verified version: opschain academy runs the first-governed-change exercise against this lesson — it reads the change's creation and success events from the server and expects the latest change on your environment to report success.

What you learned​

  • A server change needs a target node and a source of actions: a git remote on the project for project/environment targets, a template for assets.
  • runs create change <node-path> --action <name> --follow creates the change, prints each transition and exits with the run's outcome.
  • runs list and runs show <run-id> find the run again, with the exact commit it ran; --events appends its audit trail.
  • opschain logs <run-id> reads the step-prefixed log, live or to a file.

Next: lesson 3.2 — Gates, retry, cancel (opschain learn 3.2), or back to your track (opschain learn).