Scripting and command line

Start CytoWeave the way a pipeline needs, run an analysis on a folder of files without a window, and drive it from R, Python, Jupyter or a shell script with the same actions an AI agent uses.

Command line

usage
cytoweave [flags] [FCS files, folders, workspaces (.cwz), Gating-ML or FlowJo .wsp files...]
cytoweave mcp [flags]
cytoweave run [flags] [FCS files or folders...]
cytoweave verify [flags] certificate.acs
FlagDefaultEffect
--window app|browser|noneappOpen an app window (Chrome, Edge, Brave or Chromium, with its own profile), the default browser, or nothing
--no-openSame as --window none
--keep-runningKeep serving after the window is closed
--port8770Preferred port; the next free one is used if it is taken
--host127.0.0.1Interface to bind. Keep the default unless you mean to serve other machines (for example 0.0.0.0 on a trusted network), which turns off the DNS-rebinding check
--data-diruser config dirFolder of the workspace library
--no-libraryKeep workspaces in the browser's own storage instead
--remote-controlAccept actions from programs on this computer (below)
--devServe web/ from the working directory (for development)
--versionPrint the version

CytoWeave prints the address it serves, for example http://127.0.0.1:8770. With --window none, open that address in any browser yourself. Files named when CytoWeave is already running are handed to the open window.

Headless runs

cytoweave run applies an analysis template to FCS files without a window and writes its results to a folder. It is meant for a core's nightly runs, pipelines and continuous integration. A run:

  1. starts CytoWeave on a private port, with no workspace library;
  2. opens it in a headless Chrome (or Chromium, Edge or Brave);
  3. applies the analysis with the same code the window uses, writes the outputs, and stops.

Save a finished analysis as a template file (Workspace → Save as a template, downloaded as a .cwt file; see Templates), then:

$ cytoweave run --template panel.cwt --annotations samples.csv --output results/ plate-12/

The run opens the files (each folder becomes a group) and the annotations table. It then applies the template, with its channels matched by marker. It accepts what it applied: the run stands for you, so no proposal is left open and nothing is attributed to an agent. Finally it writes:

FileWhat it holds
tables.xlsxEvery table of the template, with the sheets that say where the numbers come from (columns, samples and their checksums, gating, methods)
<table>.csvEach table as the Tables view's CSV button writes it
report.pdfThe batch report of the template's last figure, a page per sample (or per --report-by annotation)
workspace.cwzThe workspace, to open in the window beside the FCS files and review or adjust
methods.txtThe methods paragraph with its references
run.jsonWhat the run read (each file's SHA-256), each step's outcome and message, every population's count in every sample, and what it wrote (sizes and SHA-256)
FlagDefaultEffect
--templateThe analysis template (.cwt) to apply
--outputThe folder for the outputs (made if missing)
--annotationsA CSV of sample annotations (the first column names the sample) or a plate layout (a well column, or plate maps)
--qcRun acquisition QC first, with a "QC pass" population above the template's
--reportpdfpdf, pptx or none
--report-bythe figure'ssample, or an annotation such as subject
--flowjoAlso write a FlowJo workspace (workspace.wsp)
--reviewAlso write a review report (review.html): the analysis as one HTML file, every number traced, for a PI or reviewer
--certificateAlso write a reproducibility certificate (certificate.acs) of the analysis with its files, which cytoweave verify checks
--stepsRun the steps of a JSON file instead (below)
--overwriteReplace outputs already in the folder (otherwise the run refuses before it starts)
--chromeCHROME, else one installedThe browser to run in
--timeout2hStop a run that takes longer

The exit status is:

Each step prints a line as it finishes.

Your own steps

--steps runs any of the agent actions in order: a JSON list of {"action": …, "args": {…}}. Paths are resolved as follows:

accept_proposals accepts what the steps before it proposed. Each step's result data goes into run.json. For example, QC, the template, a paired comparison and a table of counts:

steps.json
[
  {"action": "open_files", "args": {"paths": ["$inputs", "annotations.csv"]}},
  {"action": "run_qc", "args": {"addGate": true}},
  {"action": "apply_template", "args": {"templateFile": "panel.cwt"}},
  {"action": "accept_proposals"},
  {"action": "compare", "args": {"population": "Tregs", "groupBy": "condition", "pairBy": "subject"}},
  {"action": "export_table", "args": {"statistic": "count", "path": "counts.csv"}},
  {"action": "methods", "args": {"path": "methods.txt"}}
]
$ cytoweave run --steps steps.json --output results/ plate-12/

A run gives the same results as the same analysis done in the window. The validation checks this on the PBMC example, comparing each output with what the window's own buttons export and every count with an independent computation (Validation).

Verifying certificates

cytoweave verify verifies a reproducibility certificate without a window, as a run does: it checks every file's SHA-256, the workspace, the change log's chain and the certificate's fingerprint, computes every number again from the files and compares them.

$ cytoweave verify analysis.certificate.acs
CytoWeave 0.8.1: verifying analysis.certificate.acs in Google Chrome
Confirmed: all 468 numbers of "Panel B" were computed again from the 12 files and are identical. Fingerprint c1a6-4ec2-1429-735a.
Files: 12 of 12 match their SHA-256. Numbers: 468 identical of 468 (1.2 s).
FlagDefaultEffect
--dataA folder (or an FCS file) with the data, for a certificate made without it; may be repeated. Files are recognized by their checksums, whatever their names.
--reportAlso write what was found as JSON: the verdict, the files, the change log, the numbers checked and the first that differ
--overwriteReplace the report file if it exists
--chromeCHROME, else one installedThe browser to verify in
--timeout2hStop a verification that takes longer

The exit status is:

A run makes a certificate with --certificate, so a pipeline can verify its own results, for example in CI, or a core can certify each night's analysis. Agents and scripts use export_certificate and verify_certificate.

Remote control from your programs

cytoweave --remote-control accepts the actions of the MCP tools from programs on this computer. The window must be open: it performs each action with the same code as the user interface, so you watch the script work. A script's changes are proposals too, shown in the window under the script's name, for you to accept or reject. Actions reach the window one at a time.

$ cytoweave --remote-control

The R and Python clients

The clients in clients/ make every action a function, with its arguments and help, and find the running CytoWeave themselves. They are installed from the repository (they are not on CRAN or PyPI):

R
remotes::install_github("robert-mcdermott/cytoweave", subdir = "clients/r")
shell
$ pip install "git+https://github.com/robert-mcdermott/cytoweave#subdirectory=clients/python"
R
library(cytoweave)
cw_connect()                                  # finds the running CytoWeave
cw_open_files(c("/data/2026-09-30_panel1/"))  # each folder becomes a group
cw_auto_gate(method = "singlets", x = "FSC-A", y = "FSC-H", name = "Single cells")
frequencies <- as.data.frame(cw_statistics_table(statistic = "freqParent"))
states <- cw_differential_analysis("condition", groups = c("Unstimulated", "Stimulated"),
                                   pair_by = "subject", clusters = "FlowSOM cluster")
as.data.frame(states)                         # marker by cluster, lowest p first
python
import cytoweave

cw = cytoweave.connect()                      # finds the running CytoWeave
cw.open_example(id="pbmc-immunophenotyping")
print(cw.list_populations().message)
table = cw.statistics_table(statistic="freqParent").frame()   # a pandas DataFrame
cw.render_plot("CD3", population="T cells", file="t-cells.png")
cw.export_table("/tmp/frequencies.xlsx", statistic="freqParent")

Arguments are those of the MCP tools in snake case (group_by, pair_by); each function's help (?cw_differential_analysis, help(cw.differential_analysis)) lists them. Every result has the action's message and its data; as.data.frame() in R and .frame() in Python (with pandas) turn the table in it into a data frame. An action CytoWeave refuses is an error with its reason. cw_call() and cw.call() send any action by its name, and cw_tools() and cw.tools() list them.

Without arguments, the clients connect through the remote.json file CytoWeave writes to its data folder when remote control is on: its address and token, readable by you only, removed when CytoWeave stops. Give the address and token yourself, or set CYTOWEAVE_URL and CYTOWEAVE_TOKEN, or CYTOWEAVE_DATA_DIR when CytoWeave runs with --data-dir. The clients' version is CytoWeave's, and each release's clients are tested against that release.

Any language: JSON over HTTP

Each action is JSON posted to /api/remote/action, as {"action": …, "args": {…}, "client": …}; every reply has ok, a plain-language message and the data. GET /api/remote/tools lists the actions with their arguments.

python
import requests

URL = "http://127.0.0.1:8770/api/remote/action"

def act(action, client="Plate pipeline", **args):
    reply = requests.post(URL, json={"action": action, "args": args, "client": client}).json()
    if not reply.get("ok"):
        raise RuntimeError(reply.get("message") or reply.get("error"))
    return reply

act("open_example", id="pbmc-immunophenotyping")
act("auto_gate", method="singlets", x="FSC-A", y="FSC-H", name="Single cells")
print(act("list_populations")["message"])
for row in act("statistics_table", statistic="freqParent")["data"]["rows"]:
    print(row["sample"], row["meta"].get("condition"), row["values"])

Opening and writing files

open_files and the export actions make the program read or write files, so they also need the X-CytoWeave-Token header with the token CytoWeave prints when it starts (the clients send it):

python
TOKEN = "…"  # printed by cytoweave --remote-control, and in remote.json
requests.post(URL, headers={"X-CytoWeave-Token": TOKEN},
              json={"action": "open_files", "args": {"paths": ["/data/2026-09-30_panel1/"]}})

Paths must be absolute. Each folder becomes a sample group. Exports go only to the path given, in a folder that exists, and never replace a file unless overwrite is given.

What scripts are good for

The arguments of every action are those of the MCP tools; docs/MCP.md lists them, with the coordinate conventions for each gate type.

Security

Remote control is off unless you start CytoWeave with --remote-control (cytoweave mcp turns it on for its own session). The server accepts actions only from this computer, and actions that read or write files need the per-session token, which only you can read in remote.json. Leave --host at its default while remote control is on.

Where to go next