ctermdocs HomeBlogSign in

Workflows

A workflow is a chain of steps you draw on a canvas in a project's Workflows tab: a prompt into a Claude session, a skill, a subagent, a shell script, a yes from you, a notification. cterm runs the steps in order, each one's result the next one's input, when you press Run or when a routine's time comes, and shows on the canvas where the run is.

What it is for

A routine sends one prompt on a schedule. Much of the work you hand to Claude is a few steps, though: look for new job offers, write them into a file, tell me on my phone; or read the week, run the tests, ask me before shipping and say when it is done. A workflow writes that chain down once:

  • Each step does one thing, and you see on the canvas what it is and how it went.
  • Each step's result feeds the next, so a summary from one session can become the body of a notification, or a script's output the reason an approval gives you.
  • A step can wait for you: an approval puts an entry in the project's queue, and the run goes on only when you press Approve.
  • It runs without a tab open, by hand or from a routine, and keeps every run with each step's result.

How to use it

Make a workflow

In the project page's Workflows tab, click New workflow. A draft opens with one prompt step selected and the cursor in its title. Give the workflow a name and, if you like, a line saying what it is for.

Add step adds a step of each kind next to the ones you have:

  • Prompt types a prompt into a Claude session; the answer is the result.
  • Skill types /skill with its arguments into a Claude session; the answer is the result.
  • Agent asks a Claude session to run one of its subagents on a task; what the subagent reports is the result.
  • Script runs a shell command in the project folder; its output is the result. Only an admin's run executes it.
  • Approval puts an entry in the project's queue and waits for a yes; a bin stops the run.
  • Notification sends a notification to your devices, by default with the result of the step before.

Join the steps

Drag from a step's right dot onto another step to join them: the arrow says the second runs after the first and reads its result. A step with two arrows coming in waits for both and reads both results, each under its step's title. Steps with nothing coming in start at once, and steps that are ready at the same time run side by side. cterm refuses a link that would make a loop.

Drag a step to move it. Click a step or an arrow to select it; Delete (or Backspace) removes it.

Fill in a step

Click a step and the inspector beside the canvas shows its fields: its Kind and Title, then the Prompt, the Skill and its Arguments, the Agent and its Task, the Command, the Why of an approval or the Body of a notification. Delete step removes it.

Write {{input}} where the result of the step before should go. Without it, a prompt, skill or agent step gets the result added at the end under a line saying which step it comes from. A script never has it in its command: it reads it on its standard input.

A prompt, skill or agent step also has a Session:

  • A fresh session, started for the step on the project's defaults and named after the workflow and the step.
  • The session of an earlier step, to keep a conversation going from one step to the next.
  • A session of the project by name, such as the "Job search" session you already work in.

Save and run

Nothing is kept until you click Save; Discard goes back to the saved workflow. The bar says what is missing while the draft cannot be saved, such as a prompt step with no prompt.

Run starts a run as you. It waits while there are unsaved changes ("save first") and while a run of the same workflow is going. While it runs, each step on the canvas shows its state: a tick when done, a pulsing border while running, red with the reason when it failed, dimmed when skipped. The line under the bar says how the newest run stands. Stop ends a running run.

When a run fails

A step that fails stops the run: the steps already running finish, the rest are skipped, and the line says where and why; with push notifications on, your devices are told too. Fix what went wrong, then click Resume from that step: the steps that were done keep their results, and the run goes on from the failed one.

Answer an approval

An approval step's entry waits in the project's queue, first in the project page's Now strip and in the master view's Waiting for a yes, saying which workflow and step it comes from. It offers Approve, approve with a note (the note reaches the next step) and Bin…; there is no Changes…, since there is no session to rework the thing. A bin stops the run at that step with your reason, and Resume from asks again.

Read the runs

Under the canvas, Runs lists the workflow's runs, newest first. The newest one opens on its steps: how each went, how long it took, its result (a long one folded after eight lines, with more), and Open the session on a step that ran in a session of the list.

Run it on a schedule

In the Routines tab, make a routine and pick the workflow under Run a workflow in Send it into; the prompt is not used then. Each time comes, the routine starts a run of the workflow as the routine's owner; while a run of it is still going, that time is skipped.

How it works

A workflow is a file of the project, .cterm/workflows/<name>.json, made from its name when you first save it. It goes into git with the rest of the project, and you or a session can write one by hand:

{
  "name": "Morning search",
  "description": "New offers into offers.md, then a note on my phone.",
  "steps": [
    { "id": "s1", "kind": "prompt", "title": "Find offers",
      "text": "Look for offers posted since yesterday that fit my profile; add the good ones to offers.md with the link and why.",
      "session": { "kind": "session", "name": "Job search" } },
    { "id": "s2", "kind": "approval", "title": "Apply?", "why": "New offers:\n{{input}}" },
    { "id": "s3", "kind": "notify", "title": "Tell me", "body": "Applying to: {{input}}" }
  ],
  "links": [{ "from": "s1", "to": "s2" }, { "from": "s2", "to": "s3" }]
}

A step's kind is prompt, skill, agent, script, approval or notify; a session is { "kind": "fresh" }, { "kind": "session", "name": … } or { "kind": "step", "step": … }. Steps without x and y are laid out by the canvas. The tab follows the folder, so a file written by a session shows at once; one that does not read is listed with its error and its text. cterm checks a workflow when it is saved and again when a run starts: names, links that point at real steps, no loop (workflows.ts).

cterm's daemon runs each step itself (workflow-runner.ts): it types prompts and skills into the session the step names, as the account that started the run, and takes the answer from the end of that turn; it runs a script with sh -c in the project folder with the project's environment, for at most ten minutes; it adds an approval to the queue; it sends a notification through Web Push. A result is kept up to 64 KB. Whoever works in the project (its owner and members) may save, run, resume and stop its workflows; an admin may also stop a run. A workflow with a script step runs only for an admin: anyone else's Run is refused with "this workflow runs a script: only an admin runs it".

Runs are rows in cterm's store, ~/.cterm/cterm.db (workflow-runs.ts), each with the workflow as it was, and go 90 days after they end. If cterm restarts while a run goes, the run is marked failed at the steps that were running, with "cterm restarted while the step ran", and Resume from takes it up again.

Scenarios

You draw three steps: a prompt into your "Job search" session asking for the offers posted since yesterday, an approval "Apply?" whose why shows them, and a notification. In Routines you run the workflow at 08:00 on weekdays. At breakfast your phone says something waits for a yes; you read the offers on the project page and press Approve, or Bin… with "nothing good today".

A release check

A prompt reads the week's commits, a script runs npm test 2>&1 | tail -20, and both feed an approval "Ship it?" whose why shows the summary and the tests' last lines, then a notification "Week done". When the tests fail the run stops at the script with its exit code; you fix them and click Resume from Run the tests.

A workflow written by a session

You ask a session to "write a workflow that collects today's news about our sector into news/today.md and tells me". It writes .cterm/workflows/news-round.json, and the Workflows tab shows it at once, ready to run or to change on the canvas.

Written in docs/site/pages/workflows.md and built by docs/site/build.mjs.