Skip to content

steerium

steerium is an open-source, local-first TypeScript workflow orchestrator for deterministic code, AI calls, and coding agents, with recorded, replayable runs.

v0.5.0 · open source (MIT) · runs on your machine

Write the workflow.Not the runner.

steerium gives you the primitives — triggers, steps, providers — and a local daemon that keeps them live, records every run, and can replay it. What goes inside the function is entirely yours: deterministic code, a coding agent, or both in the same run.

npm install -g steerium

Needs Node 22.13+

.steerium/workflows/review.tsproject workflow
import { defineWorkflow, github } from "steerium";
export default defineWorkflow({
name: "review",
on: github.prOpened({ repo: "acme/app" }),
async run(ctx) {
const { pr } = ctx.event;
const review = await ctx.step("review", () =>
ctx.agent.run({
provider: "claude", // the CLI you already log into
allowedTools: ["Read", "Grep", "Bash"],
prompt: `Review PR #${pr.number} against ${pr.baseBranch}.
Correctness bugs only — skip style nits.`,
}),
);
const { token } = ctx.connector<{ token: string }>("github");
await github.comment(token, pr.repo, pr.number, review.text);
},
});
every run recorded·replayable·runs as you, in your repo

01 Ideas

Nine ideas, to show the shape

None of these are features — they’re just workflows, each a single file someone wrote in .steerium/workflows/. Some call an agent, some are only git and a schedule. Yours will be different, and that’s the point.

github.prOpened()

Review every PR as it opens

An agent reads the diff inside the real checkout — not a pasted patch — and posts a review comment.

linear.ticketMoved()

Turn a ticket into a branch

Plan with a cheap API call, then let a coding agent take a first pass and push it for you to judge.

schedule.cron("0 16 * * 5")

Write Friday’s changelog

Read the week’s commits, draft release notes, and save them as an artifact you can actually diff.

schedule.every(6h)

Prune merged branches

No AI anywhere in this one. It’s git fetch --prune and a loop — automation doesn’t have to mean agent.

github.issueOpened()

Triage new issues

Summarize it, guess a label, and ask the reporter for the repro steps they left out.

approvals.responded()

Draft it, but ask me first

The agent drafts and stops. You reply “approve” and a second workflow commits and pushes.

schedule.cron("0 9 * * 1")

Bump deps, but only if green

Update, run the suite, open a PR when it passes and a note to yourself when it doesn’t.

github.prOpened()

Keep the docs honest

When a PR touches the public API, have an agent check whether the docs still describe reality.

schedule.cron("0 8 * * *")

Yesterday, summarized

Commits landed, tickets closed, and PRs still waiting on you — as a digest before you open your laptop.

defineTrigger() · defineProvider() · defineConnector()

…and whatever yours actually is

If the trigger you need isn’t in the box, write it — a queue, a file watcher, an internal webhook, a device on your network. Same for providers and connectors: the built-ins are written against the public API you get, so there’s nothing to fork and nothing to wait for.

See how the built-ins are built

02 The code

Four real workflows, start to finish

No DSL, no YAML, no visual builder. These are copy-pasteable files from the examples directory.

03 Mix

Deterministic and agentic, in one function

There is no “AI workflow” mode. ctx.step() wraps a shell command and a coding agent exactly the same way, so a workflow can be plain code, entirely agent-driven, or move between the two as many times as it needs.

Start deterministic. Most automations begin as git, fs, and an npm package. Nothing about steerium asks you to add a model.

Reach for an agent at the step that needs judgement. Summarizing, drafting, deciding, writing code — a call, not a rewrite.

Both land in the same record. Step status, output, logs, artifacts, and replay work identically whichever kind of step produced them.

release-notes.tsschedule.cron("0 16 * * 5")
  1. codecollectgit log --since=1.week --oneline
  2. agentdraftanthropic · group 42 commits into notes
  3. codewriteprepend CHANGELOG.md, commit
  4. agentopen-prclaude · push the branch, summarize it

one workflow · one run record · one replay

04 Scope

Global or in the repo. Same runner.

Some automation belongs to you, some belongs to a codebase. steerium runs both from one daemon, with one API and one run history — the only difference is where the file lives and what cwd it runs with.

Global

~/.steerium/workflows/

  • runs with cwd = ~/.steerium

  • automation that isn’t about one repo
  • digests, drafting, cross-repo chores
  • travels with steerium config export

Project

<repo>/.steerium/workflows/

  • runs with cwd = the repo root

  • committed alongside the code it automates
  • arrives with git clone, reviewed in PRs

  • what makes agent workflows natural

one steerium daemon

the same defineWorkflowone SQLite run historyone CLIone control APIone browser UI

Project config merges over global, and project wins. Run steerium start inside a repo that has a .steerium/ and the daemon scopes itself to that project automatically — no registration, works in a fresh clone.

05 Model

Three primitives — and you can replace all of them

The built-ins hold no privileged access. Every one of them is written against the same public API you get, so anything shipped is a worked example rather than a wall.

Trigger

Emits events.

  • cron & intervals
  • GitHub, Linear, Jira
  • webhooks (HMAC-verified)
  • approval replies
  • manual fires

defineTrigger — implement start(ctx, emit) and you get persistent state for dedup cursors and webhook registration for free.

Workflow

Handles one event.

  • an async function
  • steps, logs, artifacts
  • any npm package
  • shell, git, fs
  • yours

defineWorkflow — there is nothing to extend here, because there was never a DSL in the way.

Provider

Runs an AI or agent call.

  • openai, anthropic

  • claude, codex

  • mock (the default)

  • chosen per call
  • bring your own

defineProvider — a local model, an internal inference service, a different agent. Register it in config; workflows just name it.

  1. 1 an event arrives

  2. 2 deduped and persisted

  3. 3 your function runs, step by step

  4. 4 the run is recorded, ok or error

  5. 5 replay it later against the exact same event

No automatic retries, deliberately: agents commit code, push branches, and leave comments, so a blind retry duplicates all of it. steerium replay <runId> is the explicit re-run.

And you don’t have to write any of it by hand.

A workflow is a plain TypeScript file with a typed API and no DSL to learn, which makes it the kind of thing a coding agent is genuinely good at producing. Point Claude Code or Codex at your repo, describe the automation in a sentence, and let it write the file, fire it once against the mock provider, and read the run record to check its own work.

06 Start

Running in four commands

The default provider is mock — deterministic, offline, no key. You can watch the whole loop work before pointing it at a real model.

Once the daemon is up, 127.0.0.1:4319 serves a small browser UI: run history streaming live, per-step logs, artifacts, cancel, replay.

Read the getting started guide
$ steerium init # scaffold ~/.steerium
$ steerium workflow run hello # fire one workflow, right now
$ steerium logs # every run is on the record
$ steerium start # daemon: triggers, API, browser UI

Build something that runs itself.

Install it, scaffold a workflow, and have something of your own running in the next five minutes.