# Scheduled automations

> Create and run cron/RRULE automations via CLI: triggers, provider agents, workspace modes, session reuse, run history, and SSH execution targets.

- Repository: stablyai/orca
- GitHub: https://github.com/stablyai/orca
- Human docs: https://grok-wiki.com/public/docs/stablyai-orca-2036d532bf1c
- Complete Markdown: https://grok-wiki.com/public/docs/stablyai-orca-2036d532bf1c/llms-full.txt

## Source Files

- `src/cli/specs/automations.ts`
- `src/cli/handlers/automations.ts`
- `src/shared/automations-types.ts`
- `src/main/automations/service.ts`
- `docs/automations-navigation-stack.md`
- `skills/orca-cli/SKILL.md`

---

---
title: "Scheduled automations"
description: "Create and run cron/RRULE automations via CLI: triggers, provider agents, workspace modes, session reuse, run history, and SSH execution targets."
---

Orca persists scheduled automations in the main-process store and exposes them through the `orca automations` command group, which calls runtime RPC methods (`automation.list`, `automation.create`, `automation.runNow`, and related). A background `AutomationService` evaluates due schedules every 60 seconds and asks the renderer to dispatch agent terminal sessions; runs are recorded with statuses, optional output snapshots, and provider usage when available.

```mermaid
sequenceDiagram
  participant CLI as orca automations
  participant RPC as Orca runtime RPC
  participant Store as persistence Store
  participant Svc as AutomationService
  participant UI as Renderer dispatch

  CLI->>RPC: automation.create / edit / run
  RPC->>Store: createAutomation / updateAutomation
  Svc->>Store: listAutomations / createAutomationRun
  Svc->>UI: automations:dispatchRequested
  UI->>UI: SSH connect / worktree / agent terminal
  UI->>RPC: automations:markDispatchResult
  RPC->>Store: updateAutomationRun
```

## Prerequisites

<Note>
On Linux, the public CLI is `orca-ide` (not `orca`) to avoid conflicting with GNOME Orca. Substitute `orca-ide` everywhere this page says `orca`.
</Note>

- A running Orca editor or headless runtime reachable by the CLI (`orca status --json`).
- For scheduled firing (not just CRUD): an Orca window with a ready renderer. Without it, due runs are recorded as `skipped_unavailable`.
- Automations are persisted in Orca state; do not edit automation storage files directly.

## Command surface

| Command | Purpose |
| --- | --- |
| `orca automations list [--json]` | List all automations |
| `orca automations show <id> [--json]` | Show one automation |
| `orca automations create ...` | Create a scheduled automation |
| `orca automations edit <id> ...` | Patch fields on an automation |
| `orca automations remove <id> [--json]` | Delete automation and its run history |
| `orca automations run <id> [--json]` | Trigger a manual run now |
| `orca automations runs [--id <automation-id>] [--json]` | List run history |

All commands accept global CLI flags such as `--json`, `--environment`, and `--pairing-code` when targeting a remote runtime. See [Selectors and JSON output](/selectors-json-output).

### Create and edit flags

<ParamField body="--name" type="string" required>
Display name for the automation.
</ParamField>

<ParamField body="--prompt" type="string" required>
Text submitted to the agent on each run (create only).
</ParamField>

<ParamField body="--provider" type="string" required>
Agent id (`TuiAgent`) to launch — for example `codex`, `claude`, `gemini`. Must be a known provider or the CLI returns `Unknown provider`.
</ParamField>

<ParamField body="--trigger" type="string" required>
Schedule preset, 5-field cron, or RRULE string. Alias: `--schedule` (mutually exclusive with `--trigger`).
</ParamField>

<ParamField body="--repo" type="selector">
Repo selector (`id:`, `path:`, etc.). Mutually exclusive with `--workspace`.
</ParamField>

<ParamField body="--workspace" type="selector">
Worktree selector (`id:`, `path:`, `branch:`, `active`, `current`). Mutually exclusive with `--repo`.
</ParamField>

<ParamField body="--workspace-mode" type="string">
`existing` or `new-per-run` / `new_per_run`. Default: `existing` when `--workspace` resolves; otherwise `new_per_run`.
</ParamField>

<ParamField body="--base-branch" type="string">
Base branch for `new_per_run` automations only.
</ParamField>

<ParamField body="--time" type="string">
`HH:MM` (24-hour). Default `09:00`. Only with preset triggers `daily`, `weekdays`, or `weekly` — not `hourly` or custom cron/RRULE.
</ParamField>

<ParamField body="--day" type="integer">
Day of week `0`–`6` (Sunday = `0`). Only with preset `weekly`.
</ParamField>

<ParamField body="--timezone" type="string">
IANA timezone string stored on the record. Defaults to the runtime host timezone when omitted at create.
</ParamField>

<ParamField body="--enabled / --disabled" type="boolean">
Toggle whether the scheduler fires the automation. Flags take no value.
</ParamField>

<ParamField body="--missed-run-grace-minutes" type="positive integer">
Minutes after a scheduled time Orca may still run a missed occurrence. Default **720** (12 hours).
</ParamField>

<ParamField body="--reuse-session / --fresh-session" type="boolean">
Control session reuse for `existing` workspace automations. Mutually exclusive. Flags take no value.
</ParamField>

## Schedule triggers

The CLI normalizes presets into RRULE strings stored on the automation. Custom schedules pass through as either a **5-field cron** expression or an **RRULE** string (detected by presence of `=`).

| `--trigger` value | Stored / behavior |
| --- | --- |
| `hourly` | `FREQ=HOURLY;BYMINUTE=<minute>` (default minute `0`) |
| `daily` | `FREQ=DAILY;BYHOUR=<h>;BYMINUTE=<m>` |
| `weekdays` | `FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;BYHOUR=...;BYMINUTE=...` |
| `weekly` | `FREQ=WEEKLY;BYDAY=<day>;BYHOUR=...;BYMINUTE=...` (default day Monday / `1`) |
| `"0 9 * * 1-5"` | Five-field cron (minute hour day-of-month month day-of-week) |
| `FREQ=...;BYHOUR=...` | RRULE |

<Warning>
`manual` triggers are rejected. For on-demand runs only, create with `--disabled` and use `orca automations run <id>`.
</Warning>

Occurrence math (`nextRunAt`, missed-run detection) lives in `automation-schedules.ts` and uses the **host local calendar** (`Date` setHours / day scans). The stored `timezone` field is metadata today; do not assume IANA timezone conversion drives firing unless product behavior changes.

**Hourly minute:** use a cron trigger such as `"30 * * * *"` instead of `--time` on the hourly preset.

## Workspace modes

| Mode | CLI | Per-run behavior |
| --- | --- | --- |
| `existing` | `--workspace <selector>` or default enclosing worktree from `cwd` | Runs in the bound worktree (`workspaceId`). |
| `new_per_run` | `--repo <selector>` (or repo implied from workspace) | Renderer creates a new worktree per run (`auto-<slug>-<timestamp>` naming). |

**Default target resolution (create):**

1. If `--repo` or `--workspace` is set, use that (not both).
2. Else on a **local** CLI client, resolve the enclosing Orca worktree from `cwd` as `existing`.
3. Else (remote CLI with no explicit target), omit target and the runtime may require `--repo` or `--workspace`.

**Edit constraints:**

- Switching an `existing` automation to a different repo requires `--workspace-mode new-per-run`.
- `reuseSession` is cleared when retargeting to `new_per_run`.

## Provider agents

`--provider` maps to `agentId` and must be a valid `TuiAgent` (Claude Code, Codex, Gemini CLI, Pi, Grok CLI, and the rest of Orca's agent catalog). Automations launch agents through the same background terminal path as other Orca agent sessions.

<Info>
Token/cost usage is collected after **completed** runs for **local** `claude` and `codex` automations from local usage logs. SSH automations report `remote_usage_unavailable`; other agents may report `provider_unsupported`.
</Info>

## Session reuse

For `workspaceMode: existing` only:

- `--reuse-session`: later runs try to submit the prompt into the previous run's live terminal when the agent pane is still `done` and the tab still exists.
- `--fresh-session`: disables reuse on edit.
- If reuse cannot find a live session, dispatch falls back to a fresh background agent session.

Runtime enforces: `reuseSession: true` on create/update is rejected unless `workspaceMode` is `existing`.

## Run lifecycle and history

Each firing creates an `AutomationRun` with `trigger` `scheduled` or `manual` (`orca automations run`).

| Status | Meaning |
| --- | --- |
| `pending` | Run record created |
| `dispatching` | Dispatch requested; waiting on renderer |
| `dispatched` | Agent terminal launched; work in progress |
| `completed` | Finished successfully |
| `dispatch_failed` | Launch or agent exit with error |
| `skipped_missed` | Scheduled time passed beyond grace window while Orca was unavailable |
| `skipped_unavailable` | No Orca window, missing repo/workspace, or SSH connect failure |
| `skipped_needs_interactive_auth` | SSH target needs interactive passphrase |

`orca automations remove` deletes the automation **and all run history**. `orca automations runs` returns runs newest-first; filter with `--id`.

Run records retain `workspaceDisplayName` after workspace deletion, store optional `outputSnapshot` (plain text), and attach `usage` when collection succeeds.

## Scheduler and missed runs

- `AutomationService` ticks every **60 seconds** (`DEFAULT_TICK_MS`).
- Policy: `missedRunPolicy: run_once_within_grace` with configurable `missedRunGraceMinutes` (default **720**).
- When `now - scheduledFor > grace`, the run is marked `skipped_missed` and `nextRunAt` advances.
- Duplicate runs for the same `(automationId, scheduledFor)` are deduplicated in the store.

<Check>
Use `--disabled` when creating automations during setup or tests so nothing fires before review. Enable later with `orca automations edit <id> --enabled`.
</Check>

## SSH execution targets

When the automation's repo is registered with an SSH `connectionId`, persistence sets:

- `executionTargetType: ssh`
- `executionTargetId: <connectionId>`
- `schedulerOwner: ssh_bridge`

Before dispatch, the renderer checks SSH state: interactive passphrase prompts yield `skipped_needs_interactive_auth`; connection failures yield `skipped_unavailable`. SSH automations only run while Orca can reach the host.

<Warning>
Do not assume local usage/cost metrics for SSH automations; usage collection is skipped with `remote_usage_unavailable`.
</Warning>

## Examples

<Steps>
<Step title="Daily review in the current worktree">
From inside an Orca-managed worktree:

```bash
orca automations create \
  --name "Daily review" \
  --trigger daily \
  --time 09:00 \
  --prompt "Review open changes and summarize risk" \
  --provider codex \
  --json
```

Verify:

```bash
orca automations list --json
orca automations show <automationId> --json
```
</Step>

<Step title="Weekday cron on a repo (new worktree per run)">
```bash
orca automations create \
  --name "Weekday triage" \
  --trigger "0 9 * * 1-5" \
  --prompt "Triage open issues" \
  --provider claude \
  --repo path:/abs/path/to/repo \
  --workspace-mode new-per-run \
  --base-branch main \
  --json
```
</Step>

<Step title="Reuse agent session in an existing workspace">
```bash
orca automations create \
  --name "Inbox digest" \
  --trigger hourly \
  --prompt "Summarize unread notifications" \
  --provider codex \
  --workspace active \
  --reuse-session \
  --json
```
</Step>

<Step title="Manual run and inspect history">
```bash
orca automations run <automationId> --json
orca automations runs --id <automationId> --json
```
</Step>
</Steps>

### JSON shape (automation)

<ResponseField name="automation" type="object">
Core fields returned by create/show/edit/list: `id`, `name`, `prompt`, `agentId`, `projectId`, `workspaceMode`, `workspaceId`, `baseBranch`, `reuseSession`, `rrule`, `dtstart`, `enabled`, `nextRunAt`, `lastRunAt`, `missedRunGraceMinutes`, `executionTargetType`, `executionTargetId`, `schedulerOwner`, `timezone`.
</ResponseField>

## RPC methods (runtime)

| Method | Role |
| --- | --- |
| `automation.list` | List automations |
| `automation.show` | Fetch one by id |
| `automation.create` | Resolve repo/workspace, validate schedule, persist |
| `automation.update` | Partial update (`updates` object) |
| `automation.delete` | Remove automation and runs |
| `automation.runNow` | Manual run via `AutomationService` |
| `automation.runs` | List runs (optional `automationId`) |

The CLI never bypasses these methods for native Orca automations.

## Troubleshooting

| Symptom | Likely cause |
| --- | --- |
| `Missing required --trigger` | Create without `--trigger` / `--schedule` |
| `Use either --trigger or --schedule, not both` | Both flags set |
| `Manual-only automations are not supported yet` | `--trigger manual` |
| `Unknown provider` | Invalid `--provider` |
| `Use either --repo or --workspace, not both` | Conflicting targets |
| `Automation requires --repo or --workspace` | Remote CLI or cwd outside any Orca worktree without explicit target |
| `Session reuse requires an existing workspace target` | `--reuse-session` with `new_per_run` |
| Runs stay `skipped_unavailable` | Orca closed, renderer not ready, or missing project/workspace |
| Runs `skipped_needs_interactive_auth` | SSH host needs interactive credentials |
| Runs `skipped_missed` | Machine offline longer than grace window |
| No token/cost on run | SSH target, non-claude/codex agent, or incomplete run |

## Related pages

<CardGroup>
<Card title="CLI scripting workflow" href="/cli-scripting-workflow">
Terminal read/send/wait and worktree comments alongside automations.
</Card>
<Card title="Terminals and agents" href="/terminals-and-agents">
Provider catalog, agent terminals, and `TuiAgent` detection.
</Card>
<Card title="Worktrees and repos" href="/worktrees-and-repos">
Repo registration, worktree selectors, and `new_per_run` workspace creation.
</Card>
<Card title="SSH remote worktrees" href="/ssh-remote-worktrees">
SSH targets, connection state, and remote repo constraints.
</Card>
<Card title="Runtime environments" href="/runtime-environments">
Target a remote Orca runtime with `--environment` or `--pairing-code`.
</Card>
<Card title="CLI core reference" href="/cli-core-reference">
Full flag inventory for `orca` command groups.
</Card>
</CardGroup>
