ncode

CLI docs Workflows

ncode CLI Features

Workflows

A workflow turns a job you do again and again into a program: review the changes from four angles, verify each finding, write a report. It runs agents in fixed phases, records every step so a stopped run can resume exactly where it was, and shows its phases in the side panel while it works.

Built-in workflows#

NameWhat it does
review-changesreviews the uncommitted changes from several angles (Review → Verify → Report) and keeps only the findings that survive an adversarial check
researchone-pass research inside the conversation: sweeps a few angles, reads the best pages and writes research.md into the project

For a multi-round research with an HTML report, use Deep research instead.

Running a workflow#

text
/workflow review-changes
/workflow summarize-changes base=main

/workflow <name> starts a workflow (the second line runs one of your own); arguments follow as key=value. A workflow run starts at once, beside any turn that is running. Saved workflows also appear in the / list as commands of their own.

You can also start one from the library: /workflows, or Workflows in the Ctrl+P palette, lists every workflow and its runs. A row opens a form for the workflow's arguments: arrow keys cycle choices and switches, Enter starts it, Esc cancels. A value the workflow does not accept stays in the form with the error next to it.

Controlling a run#

text
/workflow pause <run>
/workflow resume <run>
/workflow stop <run>
/workflow save <run>

pause and resume hold and continue a run, and stop ends it. Because every step is recorded, a run that resumes picks up where it was instead of starting over.

Letting the assistant write one#

  • /create-workflow <what it should do> writes a new workflow with the assistant.
  • A message that talks about a workflow is sent as /create-workflow by itself; Ctrl+S sends it as a plain message instead (see Composer).
  • In Workflow mode, your next message authors and launches a workflow.
  • In Ultra mode (/ultra), the assistant turns big tasks into workflows on its own.

Where workflows live#

ScopeFolder
This project.swarm_code/workflows/ in the project (commit it to share with your team)
You, in every projectworkflows/ inside ~/Library/Application Support/SwarmCode
Built inshipped with ncode

Reports a workflow writes go under .swarm_code/workflows/runs/<run>/ in the project.

The workflow language#

What a workflow is#

A workflow is a small program that runs agents in a fixed, repeatable order: first review, then verify, then report, for example. It is written in Elixir as a single .exs file: a meta map followed by plain calls.

elixir
meta = %{
  name: "summarize-changes",
  description: "Summarize the uncommitted changes in plain words",
  phases: ["Read", "Write"],
  budget: 4,
  args: %{base: %{type: :string, default: "", doc: "Git ref to compare with"}}
}

phase("Read")
files = host(:changed_files, base: args.base)
if files == [], do: complete(%{summary: "Nothing changed."})

phase("Write")
summary = agent("Summarize the changes in these files: #{Enum.join(files, ", ")}", name: "writer")
path = write_report("summary.md", summary || "No summary.")
complete(%{summary: "Wrote #{path}"})

The meta map#

KeyMeaning
namethe workflow's name; it also becomes a slash command
descriptionone line shown in lists
phasesthe phase titles, in order, shown as the run's progress
budgetthe most agents one run may start (1 to 1,024); without it, the workflow agent budget setting applies (128 by default)
max_livehow many of its agents may work at the same time (1 to 64); without it, the max live workflow agents setting applies (16 by default)
argsnamed arguments, each with type, default and doc; the program reads them as args.<name>

Functions#

FunctionWhat it does
phase(title)marks the start of a phase
log(text)adds a line to the run log (up to 500 lines)
agent(prompt, opts)runs one agent and returns its final text, or nil if it failed
panel(items, fun)runs fun for every item at the same time, one agent each, and returns the results in item order (nil for a failed slot)
host(op, opts)reads the project safely (see below)
present?(x)true when x is not nil; filter panel results with it
budget()%{total:, spent:, remaining:} agent slots of this run
fingerprint(value)a stable 16-character fingerprint, for removing duplicates
json_encode(value)the value as compact JSON
write_report(filename, text)saves a report in the run's folder and returns its path
read_report(filename)reads a report back, or nil
last_error()the error of the most recent failed agent call, or nil
integrate(result)merges an isolated agent's changes into the project
await_user(question, opts)pauses the run with a question and returns your answer when you resume; options: offers choices
pause(kind, message)stops the step with a reason, for example pause(:no_progress, "Every reviewer failed")
complete(value)ends the run successfully with value as its result

agent/2 options:

  • schema: a JSON-schema-like map; the agent must answer with a matching object, which you get back as a map;
  • name: the label shown for the agent;
  • capability: what the agent may do: :read_only (the default: read and search), :read_write (may also create, edit, move and delete files), :execute (may also run commands), :all (every tool a workflow agent can have) or :none (no tools: it answers from the prompt alone);
  • model: and provider: (by name) and effort: ("low", "medium", "high" or "max") to run this agent on something other than the workflow's default;
  • isolation: :worktree to give the agent its own copy of the project, and max_turns: to cap how many steps it may take.

Reading the project with host#

A workflow never touches files or the shell directly. It asks host(op, opts), and every answer is recorded so a run can be replayed and resumed exactly:

:changed_files, :git_diff, :git_log, :glob, :files, :subdirs, :read_file, :list_dir, :exists?, :dir?, :grep, :now.

Rules a workflow must follow#

Before a workflow is saved or run, a smoke check parses it, checks its arguments and runs the path they select with stand-in agents. It rejects:

  • direct file-system and shell access: the File module, System.cmd, System.shell, :os.cmd, Path.expand, Path.absname, Path.wildcard (use host instead);
  • anything that differs between two runs: clocks, random numbers, unique integers, Process.sleep (use host(:now) for the time);
  • a path that finishes without starting a single agent, when checked against a real project.

A running script that grows past 512 MB of memory is stopped.