a3s-flow CLI
a3s-flow ships with @a3s-lab/flow-ui. It reads the same node manifests as the canvas cards, configuration panels, and node reference pages, so field names, defaults, ports, and runtime bindings stay aligned. The CLI works on workflow documents and standard streams. It does not connect to model providers, read credentials, or execute host tasks.
Install and verify
The second command should return JSON with ok set to true and list nodes, new, create, read, update, delete, validate, compile, and digest. If the shell cannot find the command, confirm that the dependencies are installed in the current project and invoke the local binary through npx or a project script.
A project script can call the locally installed binary directly.
Every command emits JSON. Exit code 0 means the command succeeded. Exit code 1 means the workflow structure or node settings were rejected. Exit code 2 means the invocation, arguments, or file operation was invalid. Automation should check both the process status and the top-level ok value.
Command reference
Use --pretty for readable output and --output <file> to write JSON to a file. Pass - as the input path to read standard input. --include-internal applies to catalog inspection and exposes iteration-start and loop-start. Those internal types belong only inside matching containers and cannot be created as public nodes with new.
Inspect and create a node
Inspect the catalog, read the target manifest, and then create an instance with a stable ID.
The node result is authoritative for field names, option values, and connection handles. Editors and scripts should not maintain a separate hand-written schema. The new command fills every manifest default and preserves the structure expected by validation. Once a run exists, the node ID is durable identity. Changing it can disconnect new graph state from committed steps, hooks, progress records, or child runs.
CRUD a workflow file
Use create for a safe first file (or pass --from <file|-> to copy and validate
an existing DSL). It refuses to replace an existing path unless
--overwrite is supplied, creates parent directories, and writes through a
same-directory temporary file before rename. read returns the validated DSL,
deterministic plan, and both digests in one response.
update accepts one focused edit per invocation, or a JSON array passed through
--operations when several graph changes must be committed together. For a
generated or large patch set, pass --operations - and send one JSON operation
per line (NDJSON) on stdin, or pass --operations @operations.ndjson to stream
an NDJSON file without loading it into the command line; Flow parses and applies each operation as it arrives,
then validates and publishes one atomic snapshot. Node configuration is JSON and
only manifest-owned fields are changed; unknown semantic extensions and
presentation fields remain intact. Use --if-digest <sha256> to reject a stale
writer whose base document has changed. The candidate is validated before the
atomic replace, so a rejected or conflicting edit leaves the original file
unchanged. Add --dry-run to receive the candidate summary without writing it.
Both transports and direct typed callers share a 10,000-operation bound; each
NDJSON record - including an ignored whitespace record - is limited to 1 MiB.
Workflow files and byte/text stream chunks use fatal UTF-8 decoding, so
malformed input is rejected before a candidate can be published.
Operation-specific flags are rejected when they do not match the selected
operation, instead of being silently ignored.
Command-specific flags are checked the same way, so a typo cannot turn into a
successful no-op on another command.
When a hosted adapter derives an idempotency key from an operation, use the
package's canonicalizeFlowCliWorkflowUpdate helper before writing the
operation to its journal. It emits compact, deterministic UTF-8 JSON and
normalizes only wire-equivalent defaults; the final graph-dependent validation
still belongs to the update boundary.
Use --set-edge <id> --source <id> --target <id> to redirect an existing edge
in place. Optional --source-handle and --target-handle replace only the
handles that are supplied; omitted handles, the edge ID, and unknown semantic or
presentation fields are preserved. Use --clear-source-handle or
--clear-target-handle to remove a handle explicitly (or null in a JSON
operation). This avoids a remove/add cycle that could break references to the
edge.
Use --parent <container-id> with --add-node to place a public node inside
an existing iteration or loop scope. A new container is publishable only
after its matching internal start node and at least one executable child have
been added, so create those dependent nodes in one JSON operation array or
NDJSON stream. JSON operations use parentId; iteration accepts only an
iteration-start child and loop accepts only a loop-start child. The
intermediate incomplete container is kept in the candidate clone and is never
written to disk.
Use --move-node <id> --parent <container-id> to relocate an existing public
node while preserving its stable ID, configuration, presentation fields, and
unknown extensions. Omit --parent to move it back to the top level. JSON and
NDJSON use {"kind":"move-node","id":"node-id","parentId":"container-id"};
use parentId: null for the top level. Internal start nodes must stay under
their matching container, and parent cycles are rejected before publication.
Remove files only with explicit confirmation. Repeating the command is safe and
reports deleted: false when the file is already absent.
Create the sample document
The sample registers graph structure only. It does not execute task.run. A host must provide that task handler and choose an event store, scheduler, and worker topology. For a real project, change the workflow name and node IDs before creating the first persistent run.
Validate, compile, and digest
Run the three commands in this order after every semantic field or edge change.
Validation checks the document envelope, public node types, field constraints, port connections, duplicate IDs, dangling edges, self edges, ordinary cycles, and container scope. Successful compilation proves that the top-level graph and each iteration or loop child canvas have deterministic order. Digests ignore position, title, description, dimensions, and selection state while binding executable node settings and edges. If a host needs an integrity pin, store the digest in release metadata instead of writing it back into the workflow document.
Standard input and CI
In CI, validate first and retain the compiled plan and digest as build artifacts when review requires them. Rejected output contains code, path, and message for every issue. Repair the field or edge named by the path instead of deleting unknown extension fields. For imported workflows, separately review task names, runtime entry points, public callbacks, and host bindings because the CLI does not make authorization or credential decisions.
Custom node boundary
The CLI ships with the official built-in registry and does not load host application modules. A workflow containing a custom type will fail CLI validation with flow.node.unknown_type. Keep that rejection in place. Projects with custom nodes should provide a typed release command that imports the project catalog and calls compileA3SFlowWorkflowDagForPublication. See Custom nodes for the registration and publication contract.
Diagnosing failures
unknown_node means the installed package does not expose the requested public type, so inspect nodes before changing the document. flow.node.internal_scope_required means an internal start marker has escaped its matching container. Graph errors usually point to an incorrect handle, a cross-scope edge, or a back edge. Field errors identify the exact node data path under workflow.graph.nodes.
For a file-read failure, check the working directory and supplied path first. When standard input never completes, the upstream command has probably kept its output open; write the document to a temporary file and validate it separately. After repair, rerun validation, compilation, and digesting so the final plan and release document come from the same check.
