Search

Sign in to launch Copilot/Codex from the palette.

TERRALOOP

Two tools that run long tasks on Cloudflare, so you don't have to sit and watch them.

Pattern 2026.07.11, updated 2026.10.09

A "terraloop" sounds like a framework. It isn't. It's a name for a shape three things fall into: a heartbeat that keeps re-prompting the agent, the agent that holds the state and spawns work into terrarium, and terrarium handing back a receipt so the agent knows what actually happened.

Diagram of a terraloop: a heartbeat box reloads the agent box; the agent spawns work into a terrarium box; terrarium returns a callback receipt to the agent; the heartbeat loops on itself.
heartbeat reloads the agent · agent spawns work · terrarium returns the receipt

The part people skip is the state. The heartbeat only re-runs the prompt; what makes the loop actually move is that the agent carries its progress from one tick to the next, and the receipts from terrarium are what it trusts to update that state. Lose the state and you just have a cron job re-reading the same instruction forever.

A command like /loop every 30s check MR !38955; stop this loop once it merges kicks one off. The heartbeat keeps checking; the moment the thing is true, the loop deletes itself. You close the laptop.

Update: The Protocol Is Now a Gate

The first version of this post was a skill: prose the agent could follow or skip. It skipped it. It did the work inline, never locked a contract, and reported the work was done.

terraloop-mode moves the protocol into Pi's tool_call hook. A skipped step is now a blocked tool call with a reason the model cannot argue with.

  • Arm. /terraloop or the agent's action=arm. Only the user can leave, with /terraloop-off.
  • Lock. Goal, gate, scope, and proof, after the user says go. No child spawns before this.
  • Drive. A loops_task driver must exist. Writes outside the locked scope are blocked, including /tmp.
  • Gate. action=gate runs the proof command itself. A non-zero exit refuses the gate, so the agent cannot certify its own work.

Two things changed the heartbeat. A settle tick re-delivers the driver prompt as soon as a working turn ends, so the loop no longer waits out the interval. And an advisory evidence screen asks Clef whether the proof output, with its own PASS labels stripped, shows the gate holds.

The repo also ships loop skills with runnable gates: one for GitLab review queues that rediscovers the queue on every run, one for GitHub issue-to-PR work, and one that reviews the last loop.

Install: pi install git:github.com/acoyfellow/terraloop-mode@main. 76 tests pass. It is not a security boundary: an agent with a shell can edit its own state file.

Tool One: The Heartbeat

A thin warm orbital arc sweeping across a deep navy background
loops-yaml.coey.dev — run it now, run it again later

loops-yaml is the heartbeat. A loop is a schedule plus a command, nothing fancier. As a Pi/OpenCode extension it re-injects a prompt on an interval while the session is open and idle, so nobody has to sit there re-typing it. The agent runs these through a loops_task tool and deletes the task when it's done.

The heartbeat waits on completion callbacks instead of sleeping or polling. Each tick the agent reaps whatever finished, folds it into its state, moves one step, and kicks off the next.

Tool Two: The Runner

A cozy glass terrarium on a desk. Inside, one small robot tends a garden of even smaller robots.
terrarium.coey.dev — one robot, tending a garden of smaller robots

terrarium runs each bounded task as one isolated job and hands back a receipt. This is the part I care about most, because exit 0 lies. A callback lies. Model prose that says "done!" lies.

A real success is a TERRARIUM_RESULT whose server-minted runId, taskFingerprint, and nonce all line up with the task that was handed out. So the agent re-reads the receipt, re-runs the test, or curls the endpoint before it trusts the result into its state. A callback means the run finished, not that it worked.

The Four Habits That Keep It Safe

GOAL IS BINARY

Decide what "done" means before you start. It has to be checkable, not a feeling.

PARALLEL FIRST

Ask what can run at the same time before running one thing. Independent work goes out concurrently.

RIDE CALLBACKS

Advance when a child reports back. Don't sit in a sleep loop burning the session.

DELETE ON STOP

When the goal is true, kill the loop. A loop spinning against a satisfied gate is just noise.

The Whole Thing Is One File

Here's the part you actually copy. One loop is one markdown file. Fill the angle brackets and point your heartbeat at it.

# Terraloop: <one-line goal>

Follow the terraloop protocol. This file is the contract for one loop.

## Goal (binary)
<the end state, checkable — not a vibe>. DONE = <the exact condition>.

## Method (parallel-first)
- Name the smallest steps; run independent ones concurrently.
- The heartbeat (loops-yaml) re-injects this prompt each tick while idle.
- Each tick: reap finished children, verify, advance ONE step, spawn the next.

## Children (terrarium)
- Spawn one bounded child per deep task with: one objective, its PASS criteria,
  the safety rules. Read-only digs stay read-only; only the gate step deploys.
- A child's "done" is a claim. Re-check every receipt: runId + taskFingerprint
  + nonce must correlate. A callback means finished, not succeeded.

## Stop gate
<the binary condition>. Delete the heartbeat loop the moment it is met.

The loop ends the same way every time: the agent verifies a receipt from terrarium, confirms the final state clears the stop gate, and deletes its own loops-yaml task. No dashboard, no daemon left running. Just a file that did its job and a receipt you can still read tomorrow.