For AI agents: a documentation index is available at https://www.plungeai.com/docs/llms.txt. Append .md to any page URL, or send Accept: text/markdown, to get markdown. Setup instructions for agents are at https://www.plungeai.com/docs/agents.md. One ozk_ key opens every plane, models included.

Documentation Index: fetch the complete documentation index at /llms.txt. Use this file to discover all available pages before exploring further.

A workflow is a file of tasks that oceancode runs in a fixed order: which agent does what, which tasks run at once, where a check or your approval stops the run. No model picks the next step. Five ship with oceancode — Spec, Build, Review, Secure and Research — beside Goal and Race, and you can write your own or have the agent write one.

A workflow and a mode

A work mode decides how agents work together on your prompt (23). There are two kinds:

  • A way of working (kind: mode: Model, Auto, Solo, Delegate, Pair, Orchestrate) shapes the lead's ordinary turn: which sub-agents it may call, whether it edits, which limits apply. You talk to the lead as usual.
  • A workflow (kind: workflow) takes the turn's place. Every prompt you send is one run: the prompt becomes the run's input ({input}), the turn answers at once (spec ×3 — started run <id>), the tasks run in the background, and the result comes back into the session when the run ends (crates/ocean-session/src/run/workflow/goal.rs:57).

Under a workflow a follow-up question, or /workflow new, starts a run too. To talk to the agent again, switch back: F4 → Model, or /mode default.

Picking one

F4 or /mode opens the picker (How should the agents work?). The list has three parts: the six ways of working; after a ── workflows ── divider the built-in workflows Spec, Build, Review, Secure, Research, Goal and Race; after ── custom ── your own files, modes and workflows alike, by name. The highlighted entry's picture and cost are on the right and its description under the list.

KeyWhat it does
EnterRun this workflow for this session's prompts.
dMake it the current agent's default (agents.<id>.mode in your user oceancode.json).
eCopy a built-in to edit: a workflow to .oceancode/workflows/<id>-copy.yaml, a mode to .oceancode/modes/<id>-copy.yaml, renamed <id>-copy and labelled <Label> (copy).
nClose the picker and put /workflow new in the prompt, before anything you had typed (see Writing your own).
EscClose without a change.

Typed forms: /mode spec sets this session's workflow and /mode default clears it. "mode": "spec" in oceancode.json, or agents.<id>.mode, makes one the default (02).

The five

Spec — research, then a spec you approve

        you: task
 ┌────────▼────────┐
 │ Brief · general │
 └────────┬────────┘
   ┌──────┼──────┐
 ┌─▼──┐ ┌─▼──┐ ┌─▼───┐
 │code│ │docs│ │prior│  explore ×3
 └─┬──┘ └─┬──┘ └─┬───┘
   └──────◇──────┘ validate · review ↺ ≤ 2
 ┌────────▼────────┐
 │ Spec ✎ · general│ → .oceancode/plans/
 └────────┬────────┘ ◇ you approve
  1. brief (general) restates the task: the goal in one sentence, what is in and out of scope, the questions a spec must answer. No code.
  2. research: three explore agents at once, evidence as path:line only — code (where it is handled, what it calls, which tests cover it), docs (the rules that apply: CLAUDE.md, AGENTS.md, docs/), prior (a feature shaped like this one, its tests, its guide page).
  3. validate (review, a verdict) opens every path:line and passes only when each says what the scout claims. On a failure the three scouts correct their evidence against the findings and validate checks again; two passes at most.
  4. spec (general) writes the spec in the plan-file shape — Goal · Research findings · Approach · one fenced todo block, one buildable step per row · Verification per to-do · Open questions — and saves it as .oceancode/plans/<date>-spec-<run>.md.
  5. approve: a question card shows the spec. Approve goes on; Stop ends the run blocked · not approved, and the file stays.
  6. report (general): three lines — where the spec is, how many to-dos, and that Build with that path builds it.

Cost ≈ 3–5×. Needs an interactive session. Limits: 4 at once, 20 per turn, depth 1.

Build — to-dos from the spec, build, tests, review

        you: spec path
 ┌─────────▼─────────┐
 │ To-dos · general  │ → the builder's list
 └─────────┬─────────┘
 ┌─────────▼─────────┐
 │ Build ✎ · builder │◀──┐◀──┐
 └─────────┬─────────┘   │   │
           ◇ tests ──fail┘   │ ↺ ≤ 3
 ┌─────────▼─────────┐       │
 │ Review · review   │──fix──┘ ↺ ≤ 2
 └─────────┬─────────┘
           ▼ report · general ──▶ you
  1. plan (general) reads the spec your prompt names, else the newest file in .oceancode/plans/, and replies with its path and its todo block (adding a verification line to any row without one). It edits nothing.
  2. build (builder) gets those rows as its to-do list and carries them out in order, running every check the spec names. While rows are open it is resumed, three times at most; a row still open fails the run.
  3. tests, three passes at most: your test_command runs, and on a failure builder fixes the cause, never the test. After the third pass the run goes on with the last result, which review and the report read.
  4. review, two passes at most: review tries to refute the change against the spec — did every row land, is anything outside the spec, can every new test fail? — and builder fixes those findings, nothing else.
  5. report (general): the files changed, the commands with their pass lines, what is open.

Cost ≈ 2–5×. Needs test_command in oceancode.json; runs headless. Limits: 4 at once, 30 per turn, depth 2 (the builder may call a helper such as explore).

Review — three lenses, a judge, a verdict

          you: the change
      ┌──────────┼──────────┐
┌─────▼─────┐┌───▼────┐┌────▼────┐
│correctness││ scope  ││  tests  │ review ×3
└─────┬─────┘└───┬────┘└────┬────┘
      └──────────┼──────────┘
             ┌───▼───┐
             │ judge │ merges, evidence only
             └───┬───┘
                 ▼ verdict ──▶ you
  1. lenses: three review agents at once, each answering a verdict — correctness (it reads the diff, staged and unstaged, and the code it touches: the wrong assumption, the missing case, the error path), scope (does the change do what was asked and only that?), tests (can each test fail, does one cover each new branch, is any check only claimed?).
  2. verdict (judge): approve, request changes or block in one line, then the findings as path:line, worst first, without duplicates or anything uncited.

Your prompt names the change and what was asked. Nothing edits. Cost ≈ 3–4×. Runs headless. Limits: 3 at once, 10 per turn, depth 1.

Secure — threat model, four lenses, a verdict

        you: change
 ┌────────▼────────┐
 │ Surface·explore │ inputs, secrets, sinks
 └────────┬────────┘ review ×4 with
   ┌──────┼───────┬──────┐ security-audit
┌──▼───┐┌─▼────┐┌─▼───┐┌─▼────┐
│secret││inject││authz││supply│
└──┬───┘└─┬────┘└─┬───┘└─┬────┘
   └──────┼───────┴──────┘
      ┌───▼───┐
      │ judge │──▶ approve · changes · block
      └───────┘
  1. surface (explore) maps the change's attack surface without judging it: every input from outside, secret or credential, auth or tenant check, shell, SQL or HTML sink and external call, as path:line.
  2. lenses: four review agents at once, each given the security-audit skill and answering a verdict — secrets (keys in code, logs or responses, weak crypto, bad randomness), injection (shell, SQL, path traversal, templates, unsafe deserialization, XSS: each input traced to its sink), authz (authentication, authorization and tenant boundaries), supply (a new dependency, a changed lockfile, a download or install step, an external call the change does not explain).
  3. verdict (judge): approve, request changes or block, then each finding as path:line with its exploit path, keeping only findings a lens cited with more than 80 % confidence.

Nothing edits. Cost ≈ 4–6×. Runs headless; the lenses want the security-audit skill (Requirements). Limits: 4 at once, 10 per turn, depth 1.

Research — a sweep, verified claims, a cited report

       you: question
 ┌────────▼────────┐
 │ Plan ≤ 4 asks   │
 └────────┬────────┘
   ┌──────┼──────┐
 ┌─▼──┐ ┌─▼──┐ ┌─▼──┐ researchers, read-only
 │ q1 │ │ q2 │ │ q3 │ claims with sources
 └─┬──┘ └─┬──┘ └─┬──┘
   └──────◇──────┘ verifiers re-check
 ┌────────▼────────┐ every claim
 │ Report · cited  │──▶ you
 └─────────────────┘

Research has no tasks of its own: it runs the built-in script deep-research (workflow: deep-research), which splits your question into independent ones (four by default), sends one read-only researcher per question for claims with their sources, has every claim re-checked against its source, and writes a report that cites only what survived. Its runs are listed as deep-research.

Cost ≈ 4–8×. Runs headless. It sets no limits: the workflow bounds apply (workflows.max_concurrent_agents, workflows.agent_budget, 02).

Goal, Race and Pipeline

Goal (loop until proven done) and Race (attempts, a judge ranks, you pick) are the two older workflows; they are described in 23. Pipeline (spec, your approval, build, review) left the picker: Spec and Build do its two halves with more checks. It is still built in, and "mode": "pipeline" in oceancode.json still runs it; /mode pipeline is refused, as /mode takes only the picker's ids.

While it runs

  • The badge. The prompt's top border names the workflow and how many agents its first parallel task runs — spec ×3, build, review ×3, secure ×4, research — and, while a run is active, the task it is on: spec ×3 · validate (crates/ocean-protocol/src/diagram.rs:841).
  • The transcript row. Workflow spec: <your prompt> [brief ✓ · research ● …] follows the tasks as they start (✓ done, ● running) and ends as Workflow spec done in 2m: …, failed, cancelled or paused.
  • The dock. Its Workflows section (Workflows 1) lists each running run with its agents beneath it; open an agent's row to watch it (19).
  • Workflow Runs. /workflow runs opens the runs pane (a text overview in minimal mode); /workflow pause, resume and stop control a run, and a paused or stopped run keeps its journal, so it can be resumed.
  • Question cards. An approve task puts a card in the prompt's place: Approve?, the result it shows (Spec's spec), and the options Approve and Stop. A pick task (Race) lists the attempts in the judge's order with its reasons, and None. 1–9 choose (19).
  • The hand-back. When the run ends, its status and its last task's output land in the session as a <workflow> message, and the agent is woken to read it, so the session's next answer is the run's result. A workflow that cannot run here answers your prompt at once with the reason and starts nothing.

Requirements

WorkflowNeedsHeadless
Specan interactive session, for the approve cardno
Buildtest_command in oceancode.json, for the testsyes
Reviewnothing moreyes
Securenothing more; the security-audit skill, see belowyes
Researchnothing moreyes
Goalnothing moreyes
Racea git project, test_command, an interactive session for the pickno

Every workflow needs workflows on (workflows.enabled, the default). An interactive session is one that can show you a question card (the pager, an editor); a headless one (oceancode run, a client without cards) cannot. A workflow whose need is unmet answers the prompt with the reason — spec needs an interactive session, build needs a test_command in oceancode.json — and Auto never picks it (crates/ocean-session/src/run/mode.rs:123).

Secure's skill. Each of Secure's four lenses names the skill security-audit. oceancode ships no skill bodies: it finds this one where it finds every skill (09) — the project's .oceancode/skills/ or .claude/skills/ (this repository ships security-audit in its root .claude/skills/), or your ~/.oceancode/skills/ or ~/.claude/skills/ (crates/ocean-capabilities/src/discover.rs:74). Its SKILL.md body goes in front of each lens's prompt. Without it each lens gets one line instead — (Skill "security-audit" was not found; go on without it.) — and runs on its prompt alone (crates/ocean-session/src/run/workflow/host.rs:626).

Auto and workflows

Under Auto, Jev picks a mode for each prompt from those that can run here, the workflows among them; each option shows its summary and its when_to_use (Spec: "a task needs a spec before anything is built"). When Jev cannot answer, the rules pick, and five rules on the prompt's first word come before the four of Auto (crates/ocean-protocol/src/auto_route.rs:31):

  1. spec, specify, design → Spec;
  2. build, implement, when the prompt also names .oceancode/plans/ or the word spec → Build;
  3. review → Review;
  4. secure, security, audit → Secure;
  5. research, compare, investigate → Research.

The first word counts whole and in any case. A rule whose workflow cannot run here is passed over, so a headless design the cache falls through to the other rules. The badge says who decided: auto → review · rules: asks for a review. Auto decides per prompt, so only the prompts it gives a workflow start a run.

Writing your own

A workflow is one YAML file, .yaml or .yml:

  • .oceancode/workflows/<name>.yaml in the project: every session and everyone who works in the repository gets it.
  • ~/.config/oceancode/workflows/<name>.yaml (the user config directory): yours, in every project.

A way of working (kind: mode) goes in a modes/ folder beside it instead, which also still reads JSONC (*.jsonc, *.json, with flow written out and no kind). The folders are watched: a saved file is listed under ── custom ── at once. A file is skipped, with the reason in the engine log, when its name is taken (a built-in; a workflow script's name: a .rhai beside it with the same stem, any .rhai whose meta.name it is, or the built-in scripts deep-research, goal, pipeline and diagram), when it is the other kind for its folder, or when an earlier file holds its name (the project's wins). A file that does not parse or validate is left out, and the workflow tool's unknown-diagram error names it with the reason (crates/ocean-app/src/modes.rs:36).

Three ways to start

  • Copy one. e on a built-in in the picker writes .oceancode/workflows/<id>-copy.yaml.
  • Ask for one. /workflow new <what it should do> (or n in the picker) asks the agent to write it. It follows the workflow-author skill, which this repository ships in its root .oceancode/skills/workflow-author/; in another project, copy the skill into that project's .oceancode/skills/ or your ~/.oceancode/skills/. The agent writes the YAML, checks it with the workflow tool (source: {type: "yaml", yaml} with validate_only: true), fixes what the check names (three rounds at most), then saves it with save: {scope: "project"} or "user".
  • Write it. oceancode workflow schema prints the JSON Schema of a workflow or mode file.

The check reads the file as the catalog does, validates it against the agents this session knows, checks what the session can run, then runs it once on a stand-in host: every question takes its first option, every command exits 0, every verdict passes (crates/ocean-session/src/run/workflow/launcher_yaml.rs:73). A save does the same, asks you once for the file, and writes it. It is refused when the file exists and replace: true is not set, when the name is taken (a built-in, a workflow script, a pager /workflow op — new, runs, pause, resume, stop, save — or a file listed from elsewhere), outside the two workflow folders, and when a line looks like it holds a key (sk-, AKIA or Bearer followed by 16 or more key characters, or -----BEGIN; crates/ocean-session/src/run/workflow/launcher_yaml.rs:104). A workflow is shared text: it never holds a key, and a command takes its secrets from the environment it runs in.

To run a saved workflow: /mode <name> and a prompt, or the workflow tool with source: {type: "name", name: "diagram"}, args: {diagram: "<name>", task: "<the input>"}.

The file

kind: workflow                 # workflow (tasks, or a script) or mode (the lead's turn)
name: lint-review              # the id: the file's stem, /mode lint-review, the badge
label: Lint review             # the picker's title
description: lint, three lenses, a verdict
when_to_use: a change exists and the linter must pass first
agents: { review: {}, judge: { model: openai/gpt-5 } }
tasks: []                      # the tasks, in order (next section)
limits: { at_once: 3, per_turn: 10, depth: 1 }
picture: []                    # lines drawn in the picker
cost: "≈ 3–4×"
KeyWhat it holds
kindRequired in YAML: workflow or mode. It must agree with flow.
nameRequired: ^[a-z][a-z0-9-]*$, the key for /mode, the config's mode, the badge and the file's stem.
labelRequired: the picker's title.
descriptionThe picker's line and the text under the list. summary, when set, is a shorter line beside the label; one of the two is required.
when_to_useOne sentence; Jev reads it under Auto.
flowLeave it out: script for a workflow, lead for a mode (auto is Auto's alone).
agentsEvery agent a task names, each with options: model and effort (pins, see Models), isolate: copy (the agent works in its own copy of the project: needs git, never inside a loop; every writing agent in a parallel needs it), max (at most this many at once), keep (a mode's lead resumes the same child).
tasksThe tasks, in order.
workflowInstead of tasks: a workflow script's name (Research: deep-research). Never both.
limitsat_once 0–64, per_turn 1–1000, depth 1–4 (1: task agents start no sub-agents), race_n 1–8 (copies of a parallel that names neither n nor models). Your subagent.max_* settings win.
pictureLines drawn in the picker; keep to 12 lines of 44 cells, as the built-ins do. Left out, the picker draws one line per task.
costShown in the picker, against working alone.
pickerfalse hides it from the picker.
lead_writes, lead_promptA mode's only: false takes the lead's edit tools; text added to the lead's prompt.

An agent is any agent oceancode knows; an unknown one's error lists them. general and builder write; explore, review and judge are read-only; your own markdown agents count too. The shipped workflows use only these five.

The four task types

- type: task                   # one agent, one prompt
  id: build                    # its result's name; default: the agent's id
  agent: builder
  prompt: |
    Carry out the to-dos:
    {plan}
  schema: verdict              # verdict, ranking or deliverables: the reply is that JSON
  model: openai/gpt-5          # this task only
  condition: '!tests.pass'     # runs only when it holds; quote a leading !
  skills: [security-audit]     # SKILL.md bodies put before the prompt
  todo: { from: plan }         # the todo block of an earlier reply, or a list of rows
  save: spec                   # writes the reply to .oceancode/plans/<date>-spec-<run>.md
- type: parallel               # different tasks at once
  id: scouts                   # required
  schema: verdict              # for subtasks that name none
  subtasks:
    - { type: task, id: code, agent: explore, prompt: "Read the code. {input}" }
    - { type: task, id: docs, agent: explore, prompt: "Read the docs. {input}" }
- type: parallel               # copies: one agent, one prompt, n times
  id: checks
  agent: review
  prompt: "Refute the change. {input}"
  n: 3                         # 1–8; else one copy per model; else limits.race_n; else 3
  models: [openai/gpt-5, openai/gpt-5-mini]
- type: loop                   # repeats its tasks
  max: 3                       # passes, at least 1
  until: tests.pass            # ends it when this holds
  tasks:
    - { type: gate, gate: tests }
    - { type: task, id: fix, agent: builder, condition: '!tests.pass', prompt: "Fix the cause: {tests.output}" }
- type: gate                   # approve, pick, tests or check
  gate: check
  id: lint
  command: cargo clippy --all-targets -- -D warnings
  expect: Finished             # passes on exit 0 with this text in the output's last 4 KiB
  • task: agent and prompt are required. todo needs an agent that writes; the agent is resumed while rows are open, three times at most, and a row still open fails the task. save runs once, so never on a subtask or inside a loop, and never replaces a file. effort is read on a task too, but only the agent's effort is applied.
  • parallel: id is required. With subtasks, each a type: task, every result is saved under its own id and the set under the parallel's; it takes no agent, prompt, n or models, and every subtask id is unique in the file. Without, it runs copies of one agent with one prompt.
  • loop: max and tasks are required; until is optional.
  • gate: see Gates. A gate and a parallel take condition too.

A failed task or subtask ends the run as failed; copies end it only when none succeeds. A failing gate does not stop the run: follow it with a fix under condition: '!<id>.pass' inside a loop until: <id>.pass.

Templating, conditions and schemas

  • {input} is the prompt the run started with. {id} is a saved result as text: a plain reply as itself, a schema reply as JSON, a parallel as a JSON list. {id.field} is one field ({review.findings}, {tests.output}; on a parallel, each member's), and {id.file} the plan file a save wrote. A name nothing has saved stays as typed, braces and all.
  • A condition reads name.field or !name.field, both words lowercase letters and _ only — so a result a condition reads needs such an id (fix_two, not fix2). It holds when the field is true; on a parallel, when it is true for every member that answered in a schema; for a name nothing has saved, never, so !review.pass runs before any review. There is no &&, == or number. Quote it: a bare ! starts a YAML tag, and a tag is refused.
  • schema: verdict asks for {pass, findings}, ranking for {order, reasons} (attempt numbers, best first: what a pick gate shows), deliverables for {deliverables}. The reply is held to its schema, asked again a bounded number of times.

Gates

Gates are local: the cloud engine never waits for a person.

gateKeysResultNeeds
approveshow: a saved result shown with the question (else the input)Stop ends the run blocked · not approvedan interactive session
pickfrom: an earlier parallel's id; show: a ranking resultapplies the chosen copy and ends the runan interactive session; copies (isolate: copy)
testscommand (else the config's test_command); each: run in every copy of a parallel{pass, exit, output} under its id, else teststest_command when it names no command
checkcommand (required), expect{pass, exit, output} under its id, else checknothing

With each the result stays on each copy, so that gate takes no expect and no id.

Aliases

The work-mode files before 2026-11-02 used other words. They are still read, so every older file parses; write the first column. A word and its alias together are refused.

WriteAlso read
nameid (top level)
taskssteps
a task's idas
promptdo
condition: x (runs the task when x holds)unless: '!x' (skips it when x holds)
{input}{task}
type: task, type: gatea task keyed by agent, a gate keyed by gate
type: parallelparallel: { … } with as beside it
type: looploop: { max, until, steps }

An error names where it is and what was meant, counting the top-level list as tasks even when the file wrote steps (crates/ocean-protocol/src/diagram_read.rs:21):

mode draft: tasks[2].unles: unknown field, expected one of `type`, `id`, …; did you mean `unless`?

From the cloud engine's words

A local file has the shape of a bare CNL document (orchestration/cnl-engine/). What the local engine lacks is the registry, SharedMemory and CEL; what it adds is loop and gate.

Cloud (CNL)This file
the workflow: envelope with name, description, taskstop-level kind: workflow, name, label, description, tasks
type: agent, type: harness (goal, mission)type: task with agent and prompt
a task's idid
parallel with subtaskstype: parallel with subtasks
validatea verdict task or parallel in a loop with until: <id>.pass
condition (CEL)condition: "name.field" or "!name.field"
retrytype: loop with max
{input}, {task_id}{input}, {id}, {id.field}
a harness's skillsskills
allowed_tools, posture: read_onlythe agent: explore, review and judge are read-only
sequentialthe top-level tasks, which run in order
batch, dynamic, debate, output, version, inputs, followup, timeout, budgetnone (budgets: the config's workflows.*)

Models

A cheap model for the scouts and a strong one for the builder or the judge:

  • agents.<id>.model and effort pin an agent in every task;
  • a task's model pins that task;
  • models: [a, b, c] on a copies parallel runs one copy per model;
  • the workflow tool's args.models: {<agent id>: <model>}, when it launches diagram, wins over an agent's pin.

A model is provider/model, as /model lists it. The session's /subagent model wins over every pin; with no pin, a task runs the config's agents.<id>.model, else subagent.model, else the session's model. The picker tags each agent with its pin.

What is and is not enforced

The file is data the engine runs (crates/ocean-session/src/run/workflow/builtins/diagram.rhai), so these hold whatever an agent says:

  • The order. The tasks run as written; no model picks the next one, and a replayed run never decides again. A failed task ends the run.
  • The gates. An approve gate waits for you, and Stop ends the run. A tests or check gate passes only on exit 0 (and expect in the output). A pick applies only the copy you chose.
  • The answers. A reply in a schema is checked against it, and a condition or until reads its fields; a loop ends at max.
  • The to-dos. Rows are in the agent's list before it starts, it is resumed while they are open, and a row still open fails the task.
  • The saves. One new file under .oceancode/plans/, never elsewhere, never over another.
  • The limits. At once, per turn and depth bound the run's agents (23); explore, review and judge have no edit tools.
  • The rules of the file. An unknown key or agent, a malformed condition, todo on a read-only agent, save in a loop or a subtask, a writer in a parallel without isolate: copy: each is refused before anything runs, and a workflow whose needs are unmet never starts.

These are judgement, which no file can hold:

  • the quality of a spec, a review or a report;
  • a builder's "done" beyond the tests and its to-do rows, which it closes itself;
  • the honesty of verdict.pass: a model can pass what it should not, so a second lens or a check gate is the guard;
  • what a skill's text does: skills adds text to the prompt, not rules;
  • a {name} that names nothing: it stays in the prompt as typed, and validation does not catch it;
  • which sub-agents a task's agent calls: a mode's allow-list shapes only the lead's own calls (crates/ocean-session/src/run/orchestration.rs:679), which is why Spec, Review and Secure set limits.depth: 1 (Build: 2).

See also

Planned: TI-34

The docs assistant is not available yet. You can hand these docs to your own assistant instead.