# Commands

The workflow CLI gives you one-shot commands for starting, inspecting, recovering, and cancelling workflow runs.

## Command Overview

```bash
$ aroom workflow run <workflow> [options]
$ aroom workflow status <run_id>
$ aroom workflow list [--status ...] [--workflow ...]
$ aroom workflow history <run_id> [--transcript]
$ aroom workflow transcript <run_id> [step_id]
$ aroom workflow replay <run_id>
$ aroom workflow resume <run_id> [--from-step ...] [--definition ...]
$ aroom workflow repair <run_id> --field <path> --value <value>
$ aroom workflow cancel <run_id>
$ aroom workflow watch <run_id>
$ aroom workflow diagnose <run_id>
$ aroom workflow why <run_id>
$ aroom workflow schedule <path>
$ aroom workflow triggers {list|fire|enable|disable}
$ aroom workflow validate <path>
$ aroom workflow simulate <path> [--stubs <stubs.yaml>]
$ aroom workflow tail <run_id> [--step <id>] [--last N] [--stderr]
$ aroom workflow worktree <run_id>
$ aroom workflow delta <run_id> [--since-event <id>]
```

## `aroom workflow run`

Start a new workflow run from a workflow id or a YAML path.

```bash
$ aroom workflow run examples/workflows/issue_delivery.yaml --issue 123
```

For the highest-quality local Claude/Codex delivery flow, prefer `examples/workflows/local_work_item_router.yaml`. The `issue_delivery` example remains the generic reference workflow for the engine.

### Arguments

| Argument | Required | Description |
|---|---|---|
| `workflow_name` | Yes | Workflow id or path to a YAML definition |
| `--issue` | No | Issue number for issue-oriented workflows |
| `--param` | No | Override a workflow param (repeatable): `--param lint_command="eslint src/"` |
| `--dry-run` | No | Show the resolved plan without executing |
| `--detach` | No | Create the run, print its ID, and continue execution in the background |
| `--no-transcript` | No | Suppress live transcript output during execution (timeline-only) |

### Dry Run

Use `--dry-run` to inspect the definition, target, and steps without creating a run:

```bash
$ aroom workflow run examples/workflows/issue_delivery.yaml --issue 123 --dry-run
```

### Early Run ID

The run ID is printed immediately after the workflow run is created, before execution begins. This lets you start monitoring or share the run ID while the workflow is still running.

### Detached Execution

Use `--detach` to start a workflow in the background and return immediately:

```bash
$ aroom workflow run examples/workflows/issue_delivery.yaml --issue 123 --detach
Run ID: 9f8c7b2a-...
Detached: workflow will continue in the background.
Watch: aroom workflow watch 9f8c7b2a-...
Log: ~/.anteroom/logs/workflow-runs/9f8c7b2a-....log
```

The detached process runs independently. Use `workflow watch`, `workflow status`, or `workflow list` to monitor it.

### Interrupting a Run

Press `Ctrl-C` during a foreground run to interrupt cleanly. The run transitions to `paused` status and can be resumed:

```bash
^C
Workflow interrupted.
Run paused: 9f8c7b2a-...
Resume: aroom workflow resume 9f8c7b2a-...
```

No Python traceback is shown. The run's lock is released and all completed steps are preserved.

### Live Progress

During execution, the CLI prints timeline-style progress using status icons and friendly durations:

- `● step_id` when a step starts (running)
- `✅ step_id  5m 12s` when a step succeeds
- `🚫 step_id  < 1s` when a step is blocked
- `❌ step_id  error message` when a step fails
- `❌ step_id  (continued)` when a step with `continue_on: [failed]` fails but the workflow proceeds
- `⏭ step_id  (skipped)` when a step is skipped by a `when` guard
- `📢 message` when an `emit` step fires — color-coded by level (cyan for `info`, yellow for `warning`, green for `success`, red for `error`)

### Live Transcript

By default, transcript events stream inline below the active step during foreground execution:

```
  ● start_work
    [assistant] I'll start by reading the issue requirements...
    [tool_call] bash: gh issue view 123
    [tool_result] bash: Issue #123: Add widget parser... (+2 lines)
  ✅ start_work  45s
  ● fast_checks
    Running ruff check src/...
    [stderr] src/foo.py:12: E501 line too long
  ❌ fast_checks  3s
```

- **Color-coded**: green for assistant, content-aware colors for stdout (errors in red, paths in blue, etc.), cyan for tool calls, blue for tool results, red for stderr
- **No label for stdout**: stdout lines render without a prefix; stderr retains `[stderr]`
- **Compact by default**: tool calls and tool results are summarized to keep file reads, glob results, and bash payloads readable
- **Terminal-width wrapping**: stdout and stderr lines are not truncated — Rich handles wrapping to the terminal width naturally
- **Cleared on step transition**: each new step starts with a clean transcript view

Pass `--no-transcript` to suppress inline transcript output and show timeline progress only.

After execution finishes, the CLI prints:

- a timeline overview of all steps with icons, durations, and runner types
- the workflow-level **result summary** if the definition includes a `summary:` block (e.g., `"PR #123 opened for issue #456"`)
- a diagnosis hint for non-success runs (with a `workflow diagnose` suggestion)
- **recovery actions** for non-success runs including waiting states (`waiting_for_approval`, `waiting_for_input`), showing concrete next commands (approve/deny/respond/resume/cancel)
- the run id for follow-up commands

Streaming subprocess output is emitted per-line during execution (not buffered until completion), so `workflow watch` and the web UI transcript panel update in real-time.

!!! info
    This is still a foreground command. The process owns the run until it exits, fails, or is interrupted.

## `aroom workflow status`

Show current state and step progress for one run with a timeline-style display.

```bash
$ aroom workflow status 9f8c7b2a-...
```

The output includes:

- workflow id and version
- target kind and target ref
- current run status
- stop reason, if any
- current step id
- checkpoint count (total number of checkpoints recorded for the run)
- budget usage vs. limits (steps, tokens, duration)
- estimated cost (when `cli.usage.model_costs` is configured)
- step timeline with status icons, friendly durations (`5m 12s`), and runner types
- loop-nested steps are indented under their parent loop
- annotations for cached, fallback, skipped, and compensation steps
- loop end reason annotations: `(until met)`, `(until not met)`, `(break condition)`, `(no progress)`, `(exhausted)` based on the `loop_end_reason` artifact (#1125, #1130, #1152)
- failure branch steps (`_fail/` prefix) indented under their parent step (#1127)
- `retry_reason` in retry events: `exception`, `failed_status`, or `result_condition` (#1129)

## `aroom workflow list`

List workflow runs from the current database.

```bash
$ aroom workflow list
$ aroom workflow list --status paused
$ aroom workflow list --workflow issue_delivery
```

### Filters

| Flag | Description |
|---|---|
| `--status` | Filter by run status |
| `--workflow` | Filter by workflow id |
| `--limit` | Limit row count |

`list` is read-only — it does not perform inline recovery. The output table includes a **Stop Reason** column so you can see why non-terminal runs stopped. Stale lock reclamation happens automatically in the background executor poll loop and during `workflow resume`.

## `aroom workflow history`

Show durable step and event history for one run.

```bash
$ aroom workflow history 9f8c7b2a-...
```

This is the best command when you want a full operational trail:

- step ids
- step types
- runner types
- result statuses
- durations
- tokens consumed per step (from `result_artifacts`); cached steps show `(cached)` badge
- idempotency key (for publish steps, when present)
- structured outputs (resolved `key=value` pairs from `outputs` declarations, #1131)
- checkpoint list with labels (e.g., `after:step_one`, `failure:step_two`, `completed`)
- event log sequence

### `--transcript` Flag

Pass `--transcript` to append transcript events (assistant messages, tool calls, stdout/stderr) after the step and event tables:

```bash
$ aroom workflow history 9f8c7b2a-... --transcript
```

## `aroom workflow transcript`

Show transcript events for a workflow run, optionally scoped to a single step. Transcript events include assistant responses, tool calls, tool results, stdout, stderr, and usage summaries.

```bash
$ aroom workflow transcript 9f8c7b2a-...
$ aroom workflow transcript 9f8c7b2a-... build_step
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier |
| `step_id` | No | Scope output to a single step |

## `aroom workflow replay`

Full conversation replay of a workflow run, stitching step-level transcript entries into a run-level view.

```bash
$ aroom workflow replay 9f8c7b2a-...
```

Unlike `history` (which shows tabular step metadata), `replay` renders the actual conversation content: assistant messages, tool calls and results, stdout/stderr, and usage stats. Step boundary headers separate each step with type and runner info. A summary footer shows total steps and tokens.

Events are merged from both `transcript_*` events and lifecycle events (`step_started`, `step_finished`, `step_failed`), ordered by insertion id.

## `aroom workflow resume`

Resume a paused, waiting, blocked, or failed run from the last completed step. For failed runs, the failed step is re-executed automatically — all previously completed steps are skipped. For blocked runs, the blocking gate step is re-evaluated to check whether the external condition has been satisfied.

```bash
$ aroom workflow resume 9f8c7b2a-...
```

### Options

| Flag | Description |
|---|---|
| `--from-step` | Override the resume point |
| `--definition` | Path to the YAML definition for custom workflows |
| `--force` | Override drift detection and resume with the current definition even if it has changed since the run started |
| `--no-transcript` | Suppress live transcript output during execution (timeline-only) |

### Definition Drift

When a run starts, Anteroom records a SHA-256 hash of the workflow definition. On resume, if the definition on disk no longer matches that hash, the resume is blocked with an error listing which steps changed. This prevents partially-executed runs from continuing against an incompatible definition.

Use `--force` to override the block and resume with the current definition. Only use this when you have reviewed the changes and confirmed the run can safely continue.

### Definition Resolution

Resume resolves definitions in this order:

1. explicit `--definition`
2. built-in or example workflow by ID

For custom workflows, you should pass `--definition`.

Resume output follows the same format as `workflow run`: timeline progress, emitted messages, and the workflow-level result summary (if configured) are all displayed during and after execution.

### What Resume Does

When a run is resumed, the engine:

- re-acquires the workflow lock
- rebuilds prior step results from persisted records
- skips completed steps
- restarts execution with fresh runner sessions

## `aroom workflow repair`

Repair a field on a paused, waiting, or failed workflow run before resuming. Allows operators to fix inputs or step outputs without restarting the entire workflow — preserving all completed step progress.

```bash
# Fix run inputs (e.g., wrong issue number)
$ aroom workflow repair 9f8c7b2a-... --field inputs --value '{"issue_number": 99}'

# Fix a step's result artifacts (e.g., wrong PR number)
$ aroom workflow repair 9f8c7b2a-... --field step.create_pr.result_artifacts --value '{"pr_number": 456}'

# Fix a step's result summary
$ aroom workflow repair 9f8c7b2a-... --field step.review.result_summary --value "Approved with minor comments"
```

### Recovering from Failures

When a workflow fails (e.g., an agent step hits max iterations), you can repair the run and resume without re-running completed steps:

```bash
# 1. Diagnose the failure
$ aroom workflow diagnose 9f8c7b2a-...

# 2. Fix the inputs that caused the failure
$ aroom workflow repair 9f8c7b2a-... --field inputs --value '{"issue_number": 100}'

# 3. Resume — completed steps are skipped, the failed step re-executes
$ aroom workflow resume 9f8c7b2a-...
```

A failed step cannot be repaired directly (its status is `"failed"`, not `"completed"`). Instead, repair the run's inputs or a prior completed step's artifacts, then resume. The failed step will re-execute with the corrected context.

### Repairable Fields

**Run fields:** `inputs`

**Step fields:** `result_artifacts`, `result_summary`

All other fields (status, budget, definition, etc.) are immutable — repair attempts on them are rejected.

### Requirements

- Run must be in `paused`, `waiting_for_approval`, `waiting_for_input`, or `failed` status
- Step repairs require the step to be `completed`
- The `--value` argument is parsed as JSON; falls back to plain string if JSON parsing fails

### Audit Trail

Every repair is recorded as a `repair_applied` workflow event with before/after values and actor identity. Use `aroom workflow history` to review repairs.

### Web API

```
PATCH /workflow-runs/{run_id}/repair
Content-Type: application/json

{"field_path": "inputs", "value": {"issue_number": 99}}
```

## `aroom workflow cancel`

Cancel a paused, waiting-for-approval, or blocked workflow run.

```bash
$ aroom workflow cancel 9f8c7b2a-...
```

### Important Limitation

`cancel` works on `paused`, `waiting_for_approval`, or `blocked` runs.

If a run is actively executing in another terminal, stop it with `Ctrl-C` in that terminal. The engine does not yet support cross-process active cancellation.

## `aroom workflow approve`

Approve a pending tool approval request on a `waiting_for_approval` run.

```bash
$ aroom workflow approve 9f8c7b2a-...
```

When an agent step requests a tool that requires operator sign-off, the run pauses with `waiting_for_approval` status. This command approves the tool call and prints a reminder to use `resume` to continue execution.

```bash
$ aroom workflow approve 9f8c7b2a-...
Approved. Use 'aroom workflow resume 9f8c7b2a-...' to continue.
```

## `aroom workflow deny`

Deny a pending tool approval request on a `waiting_for_approval` run.

```bash
$ aroom workflow deny 9f8c7b2a-...
```

Denying a tool request moves the run to `paused` status with a `approval_denied` stop reason. Use `aroom workflow resume` to continue — the agent will see the denial and can adapt its approach.

## `aroom workflow respond`

Respond to a `human_gate` step decision on a `waiting_for_input` run.

```bash
$ aroom workflow respond 9f8c7b2a-... --option approve
```

A `human_gate` step presents named decision options (defined in the workflow YAML). The operator selects one:

```bash
$ aroom workflow respond 9f8c7b2a-...
  Pending decision for run 9f8c7b2a-...:
    Options: approve, reject, escalate

  Pass --option <option_id> to respond.
  Example: aroom workflow respond 9f8c7b2a-... --option approve
```

After responding, use `aroom workflow resume` to continue execution.

## Exit and Recovery Behavior

### Process Interrupted

If the workflow process dies:

- runs with expired heartbeats are automatically reclaimed (see [Stale Lock Recovery](monitoring.md#stale-lock-recovery))
- normal runs transition to `failed` with `stop_reason: stale_heartbeat_reclaimed`
- compensating runs transition to `paused` to preserve rollback safety
- in-flight steps are marked `interrupted`
- locks are released so other runs can proceed
- `resume` continues from the durable state

### Hook Delivery

If the workflow has notification hooks, Anteroom drains pending hook deliveries with a bounded timeout before the command exits.

## Example Session

```bash
$ aroom workflow run examples/workflows/issue_delivery.yaml --issue 123

Starting workflow: issue_delivery v0.1.0
Target: issue:123

  ● gate_issue_current
  ✅ gate_issue_current  < 1s
  ● start_work
    Cloning repository...
    Checking out branch issue-123-add-widget
  ✅ start_work  15s
  ● fast_checks
    Running ruff check src/...
    [stderr] src/foo.py:12: E501 line too long
  ❌ fast_checks  Exit code 1

issue_delivery  ❌ failed  18s
Run: 9f8c7b2a  Steps: 3/5

  ✅ gate_issue_current    < 1s  gate
  ✅ start_work              15s  shell
  ❌ fast_checks            3s  shell
  ○ open_pr
  ○ final_review

  ❌ Step fast_checks failed
  Exit code 1
  Run: aroom workflow diagnose 9f8c7b2a

Run ID: 9f8c7b2a-...

$ aroom workflow diagnose 9f8c7b2a-...
$ aroom workflow status 9f8c7b2a-...
```

## Current Scope

What the workflow CLI does today:

- run workflows
- inspect runs
- recover paused runs
- cancel paused runs

What it does not do today:

- browser-driven execution
- cross-process cancel for active runs
- workflow authoring from the CLI

## `aroom workflow watch`

Watch a workflow run in real-time with a Rich Live timeline display. Polls the database every 2 seconds and refreshes the timeline view showing run status, step progress, and friendly elapsed times.

```bash
$ aroom workflow watch abc123-def456
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier to watch |

The watch display includes:

- run header with workflow name, status icon, and live elapsed time
- step timeline with status icons (`✅●○❌⏭`), durations, and runner types
- running steps show live elapsed time that updates each refresh
- loop-nested steps indented under their parent
- **transcript section** showing live stdout/stderr from the active step (color-coded: green for stdout, red for stderr)
- **emitted messages** from `emit` steps, rendered inline with level-based colors
- transcript clears on step transitions and caps at `workflow.watch_buffer_lines` (default 50)
- terminal status, stop reason, and **result summary** displayed on completion

Press Ctrl+C to stop watching. If the run is already in a terminal state, watch prints the final state and exits immediately. Blocked runs are not terminal — watch keeps polling until the run is resumed or cancelled.

Useful for observing runs enqueued via `POST /workflow-runs` (server-mode background executor).

## `aroom workflow diagnose`

Explain why a blocked or failed workflow run stopped. Shows a structured diagnosis with What/Why/Evidence/Next Actions.

```bash
$ aroom workflow diagnose abc123-def456
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier to diagnose |

The diagnosis covers 13 stop reason categories:

- **runner failure** — step exited non-zero, with command output and stderr
- **gate block** — gate condition not met, with the blocking step and reason
- **budget exceeded** — token/step/duration limit reached
- **cancel** — operator-requested cancellation
- **approval denied/expired** — approval gate resolved negatively or timed out
- **engine error** — unhandled exception or process interruption
- **stale recovery** — run terminated because its heartbeat expired (worker died or was interrupted)
- **concurrency** — target locked by another run
- **human gate** — operator decision expired or chose stop
- **compensation failure** — rollback steps failed after primary failure
- **loop until not met** — loop exhausted all rounds without satisfying the `until` condition (#1125)

The output includes a Rich Panel with the diagnosis and a confidence indicator (`● high`, `◐ medium`, `○ low`).

For runs in success states (completed, running, pending), diagnose reports that no diagnosis is needed.

## `aroom workflow why`

Concise one-shot blocker summary for a workflow run. Unlike `diagnose` (which shows a full panel with evidence and timeline), `why` prints three lines at most: Blocked/Waiting, Because, and Next.

```bash
$ aroom workflow why abc123
Blocked: Step lint failed
Because: Exit code 1
Next: Inspect step output: aroom workflow history abc123
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier |

For waiting states (`waiting_for_approval`, `waiting_for_input`), prints the pending gate. For terminal states (`completed`, `cancelled`), prints "No active blocker." For all other non-success states, delegates to the diagnosis engine and prints the top-level result.

## `aroom workflow schedule`

Register cron triggers from a workflow definition. Parses the `triggers:` section, validates cron expressions and path confinement, and creates schedule records.

```bash
$ aroom workflow schedule path/to/workflow.yaml
```

See [Workflow Scheduling](scheduling.md) for trigger YAML syntax and `missed_policy` details.

## `aroom workflow triggers`

Manage registered workflow schedules.

```bash
$ aroom workflow triggers list              # List all schedules
$ aroom workflow triggers fire <id>         # Enqueue a run manually
$ aroom workflow triggers enable <id>       # Enable a disabled schedule
$ aroom workflow triggers disable <id>      # Disable a schedule
```

## `aroom workflow validate`

Validate a workflow definition without executing it. Catches structural errors (missing fields, invalid step references, unknown runner types) before you commit to a run.

```bash
$ aroom workflow validate path/to/workflow.yaml
Valid: path/to/workflow.yaml (3 steps)
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `workflow_path` | Yes | Path to a YAML workflow definition |

## `aroom workflow simulate`

Run a workflow with stub runners for testing. The real engine executes the definition but all runner steps return canned results instead of performing real side effects.

```bash
$ aroom workflow simulate path/to/workflow.yaml --stubs stubs.yaml
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `workflow_path` | Yes | Path to a YAML workflow definition |
| `--stubs` | No | Path to a YAML file mapping step IDs to canned results |

### Stubs File Format

```yaml
build:
  status: success
  summary: "Build completed"
test:
  status: failed
  summary: "3 tests failed"
```

## `aroom workflow tail`

Show the most recent transcript events for a run. Useful for quickly checking what the agent is doing without scrolling through a full transcript.

```bash
$ aroom workflow tail <run_id>
$ aroom workflow tail <run_id> --step build --last 50
$ aroom workflow tail <run_id> --stderr
$ aroom workflow tail <run_id> --stdout
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier (full UUID or unique prefix) |
| `--step` | No | Filter events to a specific step ID |
| `--last` | No | Number of events to show (default 20) |
| `--stderr` | No | Show only stderr events |
| `--stdout` | No | Show only stdout events |

## `aroom workflow worktree`

Show worktree health for an issue-oriented workflow run. Reads the shared issue state to report worktree path, branch, git status, ahead/behind main, and venv presence.

```bash
$ aroom workflow worktree <run_id>
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier (full UUID or unique prefix) |

### Output

- Worktree path and branch name
- Working tree status (clean, dirty with file count, or conflicted)
- Commits ahead/behind origin/main
- Virtual environment path (found or not found)
- Additional state fields from the issue state file

## `aroom workflow delta`

Show all workflow events since a given event ID. Useful for incremental monitoring or building automation that polls for new events.

```bash
$ aroom workflow delta <run_id>
$ aroom workflow delta <run_id> --since-event 42
```

### Arguments

| Argument | Required | Description |
|---|---|---|
| `run_id` | Yes | Run identifier (full UUID or unique prefix) |
| `--since-event` | No | Event ID to start from (default 0, shows all events) |

## See Also

- [Workflow Definitions](definitions.md)
- [Workflow Scheduling](scheduling.md)
- [Workflow Monitoring](monitoring.md)
- [Workflow API Reference](api-reference.md)
