Workflows

Workflow CLI command reference

Every Workflows CLI command with its flags, selectors, JSON output, and exit behavior, for deploying definitions and driving instances.

@sanity/workflow-cli deploys workflow definitions, inspects instances, and recovers stuck runs from a terminal or a CI job. This page lists every command with its arguments, flags, output, and exit behavior. For the setup every command here assumes, installing the CLI, authenticating, and writing sanity.workflow.ts, see Configure and deploy workflow definitions.

Run a command with npx @sanity/workflow-cli <command>. That form needs no install and uses the copy in your project when one is there. The package ships a single binary named sanity-workflows, so a project-local install runs the same commands as sanity-workflows <command>. Every command id also nests under the workflows topic, which is what lets a host CLI mount the package and surface the same command as <host> workflows <command>. Flags and behavior on this page are verified against @sanity/workflow-cli 0.32.0.

Select a deployment, a tag, or an instance

Three flag names appear across the CLI and they do not mean the same thing on every command. --deployment and --tag are always mutually exclusive, and every command that accepts both rejects the pair. Commands that take an instance id need neither, because an instance id is globally unique and carries its own tag.

Commands

--deployment

--tag

deploy

The one deployment to deploy.

Every deployment carrying the tag. A tag is an environment group, so this is a fan-out, not a picker.

start, definition diff, definition delete

The one deployment to act on.

The deployment carrying the tag, while the tag names exactly one.

abort, set-stage, reset-activity, fire-action, diagnose

Narrows where the instance is looked up. Optional.

Narrows where the instance is looked up. Optional.

list, show, tail, definition list, definition show

Not accepted.

A query filter, which also narrows which resources are searched.

nuke

The deployment to reset, or with --instance, which deployment to look the instance up in.

The tag to reset, while it names exactly one deployment. Not valid with --instance.

The deploy row is the one that surprises people. On the other commands that select a deployment — start, definition diff, and definition delete--tag resolves to exactly one deployment and errors when it cannot. On deploy it deploys every deployment carrying the tag instead. On the instance-keyed commands it is only a narrower: it limits which resources are searched, and never has to resolve to one deployment.

With no selector at all, a command that needs one deployment falls back to the sole deployment when the config declares exactly one. When several are declared, an interactive terminal prompts for one and a non-interactive shell fails with Multiple deployments configured — pass --deployment or --tag. (deploy adds , or --all-tags to deploy every deployment to that message.) Read commands need no selector in any case: untagged, they span every distinct resource the config mentions.

An instance id looks like prod.wf-instance.a1b2c3d4e5f6. When the id carries a leading tag segment the CLI probes the resources under that tag first and falls back to the full fan-out on a miss, so the prefix is a speed hint and never a requirement. If several resources hold the same id the command fails and lists them rather than picking one.

Read the output as JSON

--json is available on start, fire-action, list, show, diagnose, definition list, and definition show. The other commands have no JSON mode. One payload convention runs across all of them:

  • Write commands emit the operation envelope, where instanceId carries the document _id.
  • show commands print the fetched document exactly as stored.
  • List commands print the row view of the table, each row annotated with the resource it came from, under a top-level truncated flag.

List commands treat --json as all-or-nothing across resources. The rendered path tolerates a resource the token cannot read, notes the failure in place, and prints the rest; the JSON path rejects the whole read instead, so a script never mistakes a partial listing for a complete one.

Exit codes

Every command exits 0 on success. The CLI sets two other codes itself, and hands anything it does not recognize to oclif, which prints a stack trace and chooses its own.

Code

When

0

The command completed. A write that found nothing to change also exits 0 and says so.

1

The failure path the CLI owns: no sanity.workflow.ts, an invalid config, no matching deployment, definition, or instance, contradictory flags, a rejected engine write, a refused destructive command, a rejected auth token, or a reader-floor acknowledgement that does not cover the submitted definitions. Also the exit for a multi-target run in which at least one target failed.

130

You interrupted an interactive prompt with Ctrl+C. This is the Unix 128 + SIGINT convention.

Set by oclif

Anything else, including an unknown flag or a flag value of the wrong type. These print a stack trace rather than the one-line error the CLI renders, which is how you can tell them apart.

Multi-target runs are deliberately tolerant. deploy --all-tags continues past a deployment that failed, prints a summary naming each failure, and exits 1; deploys are idempotent, so re-running is safe. list and definition list do the same across resources. A run with a single target rethrows instead of summarizing, and an authentication rejection stops any run at once, because a dead token is never local to one target.

Commands

Each entry names the command, one representative invocation, and its complete argument and flag contract. Arguments are positional and shown in upper case; flags marked required have no default the command can fall back to.

deploy: validate, diff, and ship definitions

deploy validates the definitions in the selected deployment, then writes them to the resource that the workflowResource of that deployment names. Validation runs offline before any network write, so a run spanning several deployments cannot leave a partial deploy behind a broken batch. Definitions are content-addressed: deploying an unchanged definition creates no new version, which is what makes re-running a failed deploy safe.

On deploy alone, --tag deploys every deployment carrying the tag rather than resolving to one. A deploy that creates new definition versions also shares those documents with Sanity by default in every environment; --no-share-defs opts out for one run.

  • sanity-workflows deploy(--deployment, --tag, --all-tags, --dry-run, --check, --only, --share-defs / --no-share-defs): Rendered output only

    Validate, diff, and deploy the definitions in the selected deployment to the resource it binds.

    Parameters

    • --deployment

      string

      Deployment name, the unique identity of one deployment in the config. Mutually exclusive with --tag.

    • --tag

      string

      Workflow environment tag, for example prod or test. On deploy this deploys every deployment carrying the tag, not one, because a tag is an environment group. Mutually exclusive with --deployment.

    • --all-tags

      boolean

      Deploy every deployment in the config. Default false. Mutually exclusive with --deployment and --tag.

    • --dry-run

      boolean

      Validate, then diff each definition against the deployed version and print the diff. Writes nothing. Default false.

    • --check

      boolean

      Validate the definitions and stop. Never contacts the dataset and never resolves a token, so it runs offline and unauthenticated. Default false. Combining it with --dry-run fails with Pass either --check or --dry-run, not both.

    • --only

      string

      Limit deploy, check, or dry-run to one definition by name. Every targeted deployment must declare it; a name no deployment declares fails with No definition named "<name>". before any deployment picker runs.

    • --share-defs / --no-share-defs

      boolean

      Share the definition documents this deploy newly creates with Sanity: the full document verbatim, plus the project and dataset it was deployed to. Never content documents, instances, or your auth token. Sharing is the default in every environment, CI, non-TTY, and DO_NOT_TRACK included. A failed share warns and never fails the deploy.

start: create an instance from a deployed definition

start creates a workflow instance from a definition already deployed under the selected deployment. Supply a value for each field the definition declares with initialValue: {type: 'input'} using --field name=value. Values are parsed as JSON and fall back to a plain string, so a reference field takes a JSON object carrying the global id and type of the document.

If the engine creates and primes the instance but its first auto-advance fails, start reports the run as started rather than failed, because the instance exists. It settles on the next tick, or you can re-run with --instance-id set to the reported id, which resumes the earlier attempt instead of creating a duplicate.

  • sanity-workflows start NAME(NAME, --deployment, --tag, --version, --field, --instance-id, --json): `{instanceId, definition, version, currentStage, completedAt}` with `--json`

    Start a workflow instance from a deployed definition, seeding its input-sourced fields.

    Parameters

    • NAME

      string

      The workflow definition name, as declared by defineWorkflow.

    • --deployment

      string

      Deployment name, the unique identity of one deployment in the config. Mutually exclusive with --tag.

    • --tag

      string

      Workflow environment tag, for example prod or test. Selects the deployment to act on while the tag names exactly one; a tag spanning several fails and asks for --deployment. Mutually exclusive with --deployment.

    • --version

      integer

      Definition version to start from. Defaults to the highest deployed version.

    • --field

      string[]

      Initial value for one declared input-sourced field, as name=value. Repeatable. Each value is JSON-parsed and falls back to a plain string; reference kinds take a JSON object with a global document reference id and a document type.

    • --instance-id

      string

      Start under this instance id. The id is the idempotency key of the start: passing the id of a start that failed partway resumes it, and an already-settled start replays as a no-op. Omit it to mint a fresh id.

    • --json

      boolean

      Emit structured JSON on stdout instead of the rendered view.

fire-action: resolve an activity, or list what can be fired

fire-action fires one action on one activity of the current stage of an instance. Omit --action and it lists every action on that stage instead, each marked fireable or not with the reason it is disabled and the params it takes. Passing --action without --activity fails and asks for the activity.

The write is attributed to whoever the configured token authenticates. There is no impersonation flag, and the engine resolves the acting identity from the token rather than from anything you pass. Firing an action on an activity that is no longer active changes nothing and says so.

  • sanity-workflows fire-action INSTANCEID(INSTANCEID, --activity, --action, --param, --deployment, --tag, --json): `{instanceId, activity, action, changed, cascaded, currentStage, ranOps}` with `--json`

    Fire an action to resolve a waiting activity, or list the actions available on the current stage of the instance.

    Parameters

    • INSTANCEID

      string

      The workflow instance id.

    • --activity

      string

      The activity the action belongs to. Required to fire; omit --action to list instead.

    • --action

      string

      The action to fire. Omit it to list the actions available on the instance.

    • --param

      string[]

      An action param as key=value. Repeatable. Values are JSON-parsed and fall back to a plain string; the engine validates each against the declared type of the param.

    • --deployment

      string

      Narrows the instance search to the resource that deployment targets. Never required: an instance id is globally unique. The tag partition still comes from the loaded instance, not from this flag. Mutually exclusive with --tag.

    • --tag

      string

      Narrows the instance search to the resources deployed under that tag. Never required. Mutually exclusive with --deployment.

    • --json

      boolean

      Emit structured JSON on stdout instead of the rendered view.

list: find instances

list lists workflow instances, in-flight only unless you pass --include-completed. Untagged it spans every distinct resource the config mentions, and prints a banner per resource when it spans more than one. --tag here is a query filter, not a deployment selector: it filters rows and narrows which resources are searched.

When the read spans several resources, one the token cannot read is noted in place, the rest still render, and the run exits 1. --limit caps rows per resource at 50 by default; the output says when a page was clipped.

To find work assigned to a person or offered to their roles, pass --assignment-user, repeat --assignment-role for their project roles, and select the held and routed states. Replace ACCOUNT_USER_ID with the person’s account-global user ID, not a project membership ID. Replace editor with a project role they hold.

Each JSON row includes assignment: {unrouted, routed, held} counts for active activities in the current open stage. held counts direct assignments to that person; routed counts unassigned work offered through their supplied roles. unrouted counts work with neither a person nor a role selected. These counts do not mean the person can perform an action. Without --json, the same counts appear in the assignment u/r/h column.

  • sanity-workflows list(--tag, --include-completed, --failed, --definition, --document, --assignment-user, --assignment-role, --assignment-state, --limit, --json): `{instances, truncated}` with `--json`

    List workflow instances across the resources the config mentions.

    Parameters

    • --tag

      string

      Workflow environment tag, for example prod or test. A query filter that also narrows which resources are searched. Omit it to span every resource the config mentions.

    • --include-completed

      boolean

      Include completed and aborted instances. Default false, which lists in-flight instances only.

    • --failed

      boolean

      Only instances with at least one activity in the failed status, in any stage. Default false.

    • --definition

      string

      Only instances of this workflow definition, matched against the definition field of the instance.

    • --document

      string

      Only instances that reference this document. Takes a resource-qualified global document reference, for example dataset:YOUR_PROJECT_ID:production:article-1.

    • --assignment-user

      string

      Account-global user ID for viewer-scoped assignment filtering and counts.

    • --assignment-role

      string

      A literal project role held by the viewer. Repeat for multiple roles. Requires --assignment-user; role aliases do not add inbox ownership.

    • --assignment-state

      string

      Include unrouted, routed, or held activities. Repeat for multiple states. Requires --assignment-user. Routed means offered through a supplied role; held means assigned directly to the supplied user.

    • --limit

      integer

      Maximum rows to return per resource. Default 50.

    • --json

      boolean

      Emit structured JSON on stdout instead of the rendered view.

show: read one instance in full

show prints the stages of one instance, the activities in each with their status, and any pending effects. History is left out unless you pass --include history, because it grows without bound. --json always carries the complete stored document regardless of --include.

show locates the instance by fanning out across every resource the config mentions, so it takes no deployment selector. An id no resource holds exits 1.

  • sanity-workflows show INSTANCEID(INSTANCEID, --tag, --include, --json): The complete instance document with `--json`

    Show the state, activities, and pending effects of one workflow instance.

    Parameters

    • INSTANCEID

      string

      The workflow instance document id.

    • --tag

      string

      Workflow environment tag, for example prod or test. A query filter that also narrows which resources are searched. Omit it to span every resource the config mentions.

    • --include

      string[]

      Extra sections for the rendered output. Repeatable. The only accepted value is history.

    • --json

      boolean

      Emit structured JSON on stdout instead of the rendered view.

tail: stream new history entries

tail subscribes to one instance and prints each new history entry as it lands in the dataset. It runs until you stop it: Ctrl+C or SIGTERM unsubscribes and exits 0. A dropped subscription exits 1 rather than hanging.

tail prints the timestamp and type of each entry, not its payload. Read the payload with show --include history or show --json. There is no --json mode on tail.

  • sanity-workflows tail INSTANCEID(INSTANCEID, --tag): Rendered output only

    Stream new history entries on a workflow instance as they land in the dataset.

    Parameters

    • INSTANCEID

      string

      The workflow instance id to tail.

    • --tag

      string

      Workflow environment tag, for example prod or test. A query filter that also narrows which resources are searched. Omit it to span every resource the config mentions.

diagnose: explain why an instance is not progressing

diagnose classifies an instance as progressing, waiting, blocked, stuck, completed, or aborted, explains why, and lists the remediations the engine considers available. A waiting result distinguishes an action available to this caller, a manual action unavailable to this caller, and automation. Unassigned work has no selected holder; it is not automatically actionable. The command reads state without writing it.

A stuck verdict names one of five causes: an effect that failed against an external system, an effect that was claimed but never reported back, an activity in a terminal failed state, every exit transition evaluating to a definite false, or an exit transition that could not be evaluated because an operand is missing or unreadable. The last one is recoverable on its own: the cascade re-fires once the operand resolves. The rendered output also prints every exit transition with its condition and whether that condition currently holds, which is usually enough on its own.

abort: hard-stop an in-flight instance

abort stops an in-flight instance where it stands. Pending effects are cancelled, the stage guards it holds are removed, and the instance is marked terminal in its current stage. It deletes nothing and moves the instance to no other stage.

Aborting an instance that is already terminal changes nothing and reports when it terminated. Abort before deleting: nuke --instance refuses an in-flight instance precisely so its effects and children are cleaned up first.

  • sanity-workflows abort INSTANCEID(INSTANCEID, --reason, --deployment, --tag): Rendered output only

    Abort an in-flight workflow instance: cancel pending effects, remove stage guards, and mark it terminal where it stands.

    Parameters

    • INSTANCEID

      string

      The workflow instance id.

    • --reason

      string

      Free-text reason, recorded on the history entry for audit.

    • --deployment

      string

      Narrows the instance search to the resource that deployment targets. Never required: an instance id is globally unique. The tag partition still comes from the loaded instance, not from this flag. Mutually exclusive with --tag.

    • --tag

      string

      Narrows the instance search to the resources deployed under that tag. Never required. Mutually exclusive with --deployment.

set-stage: force an instance into a stage

set-stage moves an instance to any stage its pinned definition declares, ignoring the declared transitions and their conditions. This is the administrative override the engine provides.

It is not a full bypass. The enter lifecycle of the target stage still runs, so auto-activities start and stage guards reconcile, and the cascade that follows the move can advance the instance onward immediately. Omit --to on an interactive terminal to pick from the stages the pinned definition declares; the picker marks the current stage and offers every declared stage. A non-interactive shell fails asking for --to. Moving an instance to the stage it is already in changes nothing, and a terminal instance never moves.

  • sanity-workflows set-stage INSTANCEID(INSTANCEID, --to, --reason, --deployment, --tag): Rendered output only

    Force a workflow instance into a stage regardless of its declared transitions and filters.

    Parameters

    • INSTANCEID

      string

      The workflow instance id to move.

    • --to

      string

      Target stage name. Any stage the pinned definition of the instance declares is accepted. Omit it on an interactive terminal to pick from a list.

    • --reason

      string

      Free-text reason, recorded on the history entry for audit.

    • --deployment

      string

      Narrows the instance search to the resource that deployment targets. Never required: an instance id is globally unique. The tag partition still comes from the loaded instance, not from this flag. Mutually exclusive with --tag.

    • --tag

      string

      Narrows the instance search to the resources deployed under that tag. Never required. Mutually exclusive with --deployment.

reset-activity: re-run or skip a failed activity

reset-activity returns a failed activity to active so it can run again. Pass --skip to mark it skipped instead, which is what lets an exit transition gated on that activity fire without the work being done. Both forms continue the workflow cascade.

The activity must be in the current stage of the instance, named exactly as the definition declares it. An activity already at the target status changes nothing, and a terminal instance never resets.

  • sanity-workflows reset-activity INSTANCEID ACTIVITY(INSTANCEID, ACTIVITY, --skip, --deployment, --tag): Rendered output only

    Reset a failed activity on an in-flight instance, back to active to re-run it or skipped to bypass it.

    Parameters

    • INSTANCEID

      string

      The workflow instance id.

    • ACTIVITY

      string

      The activity name, within the current stage of the instance.

    • --skip

      boolean

      Mark the activity skipped instead of returning it to active. Default false.

    • --deployment

      string

      Narrows the instance search to the resource that deployment targets. Never required: an instance id is globally unique. The tag partition still comes from the loaded instance, not from this flag. Mutually exclusive with --tag.

    • --tag

      string

      Narrows the instance search to the resources deployed under that tag. Never required. Mutually exclusive with --deployment.

definition list: list deployed definitions

definition list lists the definitions deployed in every resource the config mentions, ordered by name with the newest version first, and counts the instances each has and how many are still in flight.

--tag filters rows and narrows which resources are searched; omit it to span them all. When the read spans several resources, one that fails is noted in place, the rest still render, and the run exits 1.

  • sanity-workflows definition list(--tag, --limit, --name, --json): `{definitions, truncated}` with `--json`

    List the workflow definitions deployed in the resources the config mentions.

    Parameters

    • --tag

      string

      Workflow environment tag, for example prod or test. A query filter that also narrows which resources are searched. Omit it to span every resource the config mentions.

    • --limit

      integer

      Maximum definitions to return per resource. Default 100.

    • --name

      string

      Filter to a single workflow definition name, for example article-review.

    • --json

      boolean

      Emit structured JSON on stdout instead of the rendered view.

definition show: read one deployed definition

definition show prints one deployed definition, its latest version unless --version names one. It reads what is stored in the Content Lake, not what your sanity.workflow.ts currently declares.

It refuses every ambiguity rather than choosing. A name deployed under several tags inside one dataset fails and lists the tags; a name held by several datasets fails and lists the resources. Pass --tag to resolve either.

definition diff: compare in-code against deployed

definition diff diffs one definition as authored in your sanity.workflow.ts against the version deployed to the selected deployment, the latest unless --version names one. Nothing deployed under that name is a legitimate result and renders as a create.

It takes exactly one definition name, where deploy --dry-run diffs every definition in the deployment. Use definition diff when you want one answer and deploy --dry-run when you want the whole batch. There is no --json mode.

  • sanity-workflows definition diff NAME(NAME, --deployment, --tag, --version): Rendered output only

    Diff an in-code workflow definition against the version deployed to the selected deployment.

    Parameters

    • NAME

      string

      The workflow definition name. It must be declared by the selected deployment; a name it does not declare fails and lists the ones it does.

    • --deployment

      string

      Deployment name, the unique identity of one deployment in the config. Mutually exclusive with --tag.

    • --tag

      string

      Workflow environment tag, for example prod or test. Selects the deployment to act on while the tag names exactly one; a tag spanning several fails and asks for --deployment. Mutually exclusive with --deployment.

    • --version

      integer

      The deployed version to diff against. Defaults to the latest.

definition delete: remove a deployed definition

definition delete deletes every deployed version of a definition, or one version with --version. Orphaned guard documents are removed only when the delete takes the last remaining version. Deleting one version while others survive leaves them in place.

It refuses while any non-terminal instance is pinned to a targeted version. --cascade aborts those instances first and then deletes; the instances are aborted in place and are never deleted, so their history survives. To remove instance documents as well, abort them and then use nuke.

  • sanity-workflows definition delete NAME(NAME, --deployment, --tag, --version, --cascade, --reason): Rendered output only

    Delete a deployed workflow definition, optionally aborting the instances still pinned to it.

    Parameters

    • NAME

      string

      The workflow definition name.

    • --deployment

      string

      Deployment name, the unique identity of one deployment in the config. Mutually exclusive with --tag.

    • --tag

      string

      Workflow environment tag, for example prod or test. Selects the deployment to act on while the tag names exactly one; a tag spanning several fails and asks for --deployment. Mutually exclusive with --deployment.

    • --version

      integer

      Delete only this deployed version. Defaults to every version.

    • --cascade

      boolean

      Abort every non-terminal instance pinned to the targeted versions, then delete. Default false, which refuses the delete while any such instance exists.

    • --reason

      string

      Free-text reason, recorded on each cascade-abort history entry.

nuke: delete engine-owned documents

nuke deletes engine-owned documents. With --deployment or --tag it deletes every instance, definition, and guard under the tag of that deployment, across the workflow resource and every resource its aliases bind. With --instance <id> it deletes one terminal instance plus its guards. Content documents are never touched, and a single-instance delete refuses any id whose _type is not a workflow instance.

This is a development reset for a dataset holding engine documents the versioned upgrade framework cannot yet migrate. Because it deletes raw documents rather than reading them through the engine, it can clear data an older engine wrote that the current one cannot interpret, which definition delete cannot do. It is not an operational tool, and there is no undo.

nuke always prints a dry-run plan of exactly what it will delete, including under --force. Without --force, tag mode then asks you to type back every project.dataset target space-separated, and instance mode asks a single yes-or-no. A shell that cannot prompt fails rather than blocking. --instance refuses an in-flight instance with Instance is in-flight — abort it first, then delete. Tag mode also refuses when another deployment shares the tag and a swept resource, because guard ids embed only the tag and the sweep could not tell the two apart.

  • sanity-workflows nuke(--deployment, --tag, --instance, --force): Rendered output only

    Delete engine-owned documents for a whole deployment tag, or one terminal instance and its guards.

    Parameters

    • --deployment

      string

      The deployment name to reset. With --instance, narrows which deployment the instance is looked up in when its tag spans several.

    • --tag

      string

      The deployment tag to reset, while it names exactly one deployment. Not valid with --instance, which reads its tag from the instance id.

    • --instance

      string

      Delete one terminal instance by id, plus its guard documents, instead of a whole tag. The instance must already be completed or aborted.

    • --force

      boolean

      Skip the confirmation prompt, for scripts and CI. Default false. The plan still prints.

Related reading

Was this page helpful?