> ## Documentation Index
> Fetch the complete documentation index at: https://rapidreview.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Long runs and waking

> How an agent launches a long sandbox command, sleeps, and gets woken when it finishes — per client.

The client-neutral core: launch over SSH with `merv_run <label> -- <command>`, then observe the durable receipt with `sandbox.runs`. What differs per client is how the agent *waits* without burning its context or a tool-call timeout.

## The watcher

`merv-runs-wait` (installed with the plugin as `bin/merv-runs-wait`) blocks until a run settles. **Its exit is the wake signal.** stdout carries exactly one line:

```text theme={"theme":{"light":"github-light","dark":"dark-plus"}}
MERV_RUNS_WAIT <state> <label> [status=... exit_code=...]
```

Two modes:

```bash theme={"theme":{"light":"github-light","dark":"dark-plus"}}
merv-runs-wait --url <wait_url>                                   # URL mode — no credential needed
merv-runs-wait --project-id <p> --sandbox-uid <s> --label <l> [--deadline 3600]   # keyed mode
```

| Exit | State           | Meaning                                                                                                             |
| ---- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
| `0`  | `done`          | Terminal observation. Read `status=` / `exit_code=` on the line — **exit 0 never means the workload succeeded**     |
| `2`  | `still_running` | The server hold cap (60 min) or `--deadline` elapsed; re-arm                                                        |
| `3`  | `poll_error`    | The wait itself failed (transport, auth, rate limit); read truth with one authenticated `sandbox.runs`, then re-arm |
| `4`  | `no_such_run`   | Absence, or an expired/rejected URL — in URL mode the run may still exist behind auth                               |

A watcher killed outright exits with no line at all; treat a missing line exactly like `poll_error`.

### `wait_url`

Each `sandbox.runs` row carries a `wait_url` signed for exactly one sandbox + label. It's served by an auth-exempt route, so an agent can wait without holding a credential; it reveals only that the run ended and how (`status`, `exit_code`) — logs and receipts stay behind authenticated tools. It expires about six hours after the brain last saw a terminal run, or at sandbox lease + one day. Treat it like a status pager, not a secret: fine for a local background process, not for public paste. Direct/library callers with no reachable base URL get rows without a `wait_url` — use keyed mode.

### Long-polling instead

Where no watcher can run (Claude Desktop and similar MCP-only clients), long-poll `sandbox.runs` with `wait_seconds` — recommended ≤ 45 (most MCP clients cut tool calls near 60 s; the server cap is 300 s), never tighter than 60 s apart.

## Per client

| Client       | Recipe                                                                                                                                                                                              |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Claude Code  | `merv-runs-wait --url <wait_url>` as a background Bash task (`run_in_background`); task exit fires the native notification. Works from subagents. Fallback `curl -N <wait_url>` (curl's exit codes) |
| Codex        | Foreground blocking terminal (raise `background_terminal_max_timeout`), or background terminal + empty `write_stdin` poll                                                                           |
| Cursor 3.0+  | Background shell with notify-on-output armed on `^MERV_RUNS_WAIT `; shell exit or a matched line resumes the agent. Re-run the watcher (or use a stop-hook loop) if a long-idle reattach fails      |
| Kilo Code    | `background_process` with `ready.pattern` `^MERV_RUNS_WAIT `                                                                                                                                        |
| Hermes Agent | Background terminal with completion notification; on exit read `sandbox.runs`                                                                                                                       |

Not yet documented per client — the generic pattern applies: **GitHub Copilot CLI, Gemini CLI, Qwen Code, OpenCode** run the watcher in a background shell and treat its exit as the wake signal; **OpenHands, Replit Agent** long-poll `sandbox.runs`.

Concept: [Sandboxes](/docs/merv/concepts/sandboxes).
