# Loop

> General-purpose unattended work drain across every project and kind — code, browser, outreach, design, portal tasks. Spreads load with agents teams + balanced account rotation so one logout or rate-limit does not kill the night. Drives each item to landed — engineering merges on green behind a non-author review, never waiting on the user to click merge. Its `triage` mode forces every open item to keep-and-schedule-this-cycle or cancel instead of draining. Triggers on: 'work loop', '/work:loop', 'overnight drain', 'drain the board', 'finish everything unattended', 'keep moving on all projects', 'triage the board', 'clean up the backlog', 'decide keep/cancel on every ticket'.

- Skill: `phnx-labs/loop-2` (Agent Skill)
- Install (CLI): `npx skillmds@latest add phnx-labs/loop-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/phnx-labs/loop-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: phnx-labs (https://skillmd.com/u/phnx-labs)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/phnx-labs/loop-2

---



# work:loop — get the work done, unattended

You are the **orchestrator of a general-purpose drain**. The board is every open, clear,
unblocked item across the user's projects — not one repo, not engineering only. Your job
is to **drive every agent-doable item to landed without involving the user**, park only
what genuinely needs their judgment, and **never pin the night on a single account or
host**.

This is the kind-agnostic sibling of `code:loop`. For pure engineering mechanics
(worktrees, claim/dedup, PR shape, **merge-on-green**) you **compose** `code:loop` — this
skill owns the overnight / multi-project / multi-kind contract, and it inherits
`code:loop`'s completion bar rather than lowering it.

## Mindset (load-bearing)

1. **Done without the user.** While draining, never call `AskUserQuestion` and never wait
   for approval. If a decision is genuinely product/taste-only, park the item with a comment
   and continue. The sole exception is **Triage mode's no-goal-signal case** below, where you
   may ask **once, briefly** for the missing goal — that one carve-out is why this skill holds
   the `AskUserQuestion` grant; do not use it anywhere else in the drain.
2. **Maximize finished work.** Prefer landing a solid PR, sending the outreach, filling
   the form, publishing the asset — over perfecting a plan or waiting for review.
3. **Unattended means you own the merge, not that you skip it.** The user is asleep or
   running fifty other agents; a PR left for them to review is work parked on the one
   person who cannot get to it. For engineering: implement → test → open PR → get a
   **non-author** review → **merge on green** → clean up → close the ticket. The review
   is the repo's automated reviewer where one is configured and posting, otherwise a
   subagent that did not author the PR. For non-coding: complete the real outcome
   (message sent, form submitted, report filed) when the agent can do it alone.
4. **Spread load always.** One Claude logout or rate-limit must not collapse the night
   (real failure mode: m-box logouts and bwrap failures re-homing everything onto s0/s1).
   Default to `agents teams` / multiple `agents run` with **`--strategy balanced`**, mixed
   harnesses, and worker hosts — never one long single-account session for a whole queue.
5. **Re-home on death.** Auth 401, rate-limit, bwrap, host unreachable → re-probe, then
   move that track to another account / harness / host. Do not hammer the same dead path.

## Tools you already have — use them

| Surface | Use when |
|---|---|
| **`browser` skill / `agents browser`** | Web apps, portals, forms, dashboards, ordering, web outreach. Prefer signed-in fleet profiles; use `agents secrets` for bundles. |
| **`computer` skill / `agents computer`** | Native desktop apps (Finder, Electron hosts, anything not a browser). Element mode; do not steal the user's interactive machine when workers can run headless. |
| **`agents secrets` / `agents secrets exec`** | Credentials. Never invent logins; inject the named bundle. If a harness shows "not logged in", try minting/rotating via fleet paths before parking. |
| **`agents sessions`** | Prior conversations, decisions, mid-task context. Search by topic/ticket/id; load summaries; continue from real history. |
| **Tracker comments + PRs** | Prior human decisions, "do this not that", scope cuts. Prefer written history over guessing. |
| **Read the code** | When a ticket or product note is ambiguous — the repo is ground truth. Read entry points, AGENTS.md, recent CHANGELOG; do not invent APIs. |
| **WebSearch** | External/current facts (API shapes, pricing, how a third-party portal works this year). |

If you are confused: **sessions → ticket/PR comments → code → web**, in that order for
*this user's* intent, then external truth. Do not stop and ask the user for context you
can recover yourself.

## What is in the queue

`$ARGUMENTS` empty or `overnight` / `all` → pull **clear, unblocked, keep-worthy** items
across projects (Linear Todo/In Progress delegated or labeled for drain; open GitHub issues
with pilot labels if any; skip items that need cancel/priority taste — those are for `triage` mode below).

A project name, label, or query scopes the queue. Human-only holds (`hold`, explicit "wait
for me") stay parked.

Normalize each item: id · title · kind (engineering | browser/web | design/content |
research | other) · project/repo · acceptance · host preference if any.

## Triage mode — force every open item to a decision

`triage` (`/work:loop triage`, or `triage <project|label>`) flips the loop from *draining
the clear items* to *deciding the whole board*. The regular drain deliberately **skips**
items that need a cancel/priority/taste call; triage mode is where those get made. **The
point is fewer open items, not reshuffled ones** — success is the total open count and the
per-cycle count trending **down** across runs. A pass that ends with the same count it
started with triaged nothing.

**Step 0 — ground in the real product goals first.** You cannot tell "genuinely urgent"
from "just labeled urgent" without knowing what the product is trying to do right now.
Before judging a single ticket:

- **Linear** — read the goal spine: Initiative → Project (one-liner/metric/goal-now) →
  Milestones (target date + done-condition). `linear milestones` / `linear projects` for
  live state. The **current goal is the incomplete milestone with the soonest target
  date** — a query, not a guess. Check for a milestone/goal-spine memory first.
- **GitHub** — `ROADMAP.md`, pinned issues, the repo's milestone list
  (`gh api repos/{owner}/{repo}/milestones`), any product doc (`PRODUCT.md`,
  `MASTER_PLAN.md`) for a stated near-term goal.
- **Neither exists?** Ask once, briefly, then proceed — don't triage against an invented goal.

**Force exactly one of two outcomes per item — no third hedge state:**

- **KEEP & SCHEDULE** — real work worth doing → into the **current cycle** (active cycle /
  this week's milestone), status Todo or further, never `--cycle none` and never Backlog.
  If it's small and fully scoped, don't just schedule it — build it now in the same pass.
- **CANCEL** — not worth doing (dead code path, speculative nit, superseded, someday-idea)
  → cancel outright with a one-line reason. Do **not** downgrade to Low or Backlog instead
  of canceling — that's a slower cancel that clutters the count exactly the same.

**Banned as a landing state for anything you touch this pass:** `Backlog` status,
`--cycle none`, and "Low priority, revisit someday." (On a tracker with no cycle concept,
e.g. bare GitHub Issues, the rule maps to open+milestoned-now vs closed.) **One narrow
exception:** an item genuinely blocked on a human decision or external dependency stays in
its current state, but must carry a comment naming exactly what it's waiting on and who.

**Decide, don't ask.** Re-leveling a priority, canceling a stale ticket, moving something
into the active cycle are yours to decide and state in one line, not `AskUserQuestion`
material (F1) — consistent with this skill's unattended contract. Only ask for a genuine
strategy/scope call the user hasn't already made (e.g. "is this initiative still
company-priority"), not "should I re-level this." Never let indecision default to
Backlog/Low. **Always link, never bare IDs** — every ticket you name carries its full URL
(`linear tasks <id> | grep URL:`, or the tracker's issue link).

**Report the delta, compactly:** counts before → after (total open, per-cycle/current,
Backlog trending to 0, canceled this pass); each keep/cancel decision with its link and
one-line reason; anything left for the user (the narrow exception only), with what it's
waiting on.

## Dedup and claim (same spine as code:loop)

Before building:

1. Open PR already for this id? → attach to that PR (land it further) or skip if clearly
   someone else's live work.
2. Live `agents sessions --active` already on it? → skip this round.
3. Claim: Todo → In Progress + comment (`Picked up by work:loop · <session> on <host>`).
4. Re-check status right before first real mutation.

Every engineering PR title/body carries the item id so other loops can find it.

## Spread strategy (mandatory)

When ≥2 independent items (or one item with ≥2 independent tracks):

```bash
# Discover capacity
agents teams doctor
agents view --json
agents devices list   # workers only for spawn; never flood the interactive laptop

# Fan out — balanced accounts, mixed harnesses
agents teams create <slug> --enable-worktrees   # edit-mode isolation when coding
agents teams add <slug> claude "..." --name <role> --mode auto   # hard / ambiguous
agents teams add <slug> codex  "..." --name <role> --mode auto   # grunt implement
# kimi / other cheap harnesses when signed in — use them for bulk mechanical work
agents teams start <slug> --watch
```

- **`--strategy balanced`** / bare `claude` (no pin) so accounts rotate by headroom.
- **Never** three of the same exhausted account "verifying" each other.
- **Hosts:** pin workers (`yosemite-s0`, `yosemite-s1`, …) or `--device auto`. The
  interactive machine stays light — orchestrator only. Address it as
  `--device interactive` rather than by name: it resolves to whatever
  `interactive.host` pins, so the guidance stays correct on any fleet and after
  the pin changes.
- **Cap concurrency** by judgment and live capacity; prefer more smaller tracks over one
  fat track that dies with one logout.
- On track failure that is **auth/limit/infra**: re-home; do not rewrite the product code
  to paper over a dead host.

Single trivial item → one `agents run … --mode auto --strategy balanced` (or inline if
tiny). Still unattended.

## Routing by kind

| Kind | How you finish (unattended) |
|---|---|
| **Engineering** | Worktree off `origin/$BASE`; implement; run real tests; **open PR**; comment on ticket with PR link; then **land it** — watch CI, get a non-author review, **rebase-merge on green**, remove the worktree, delete the branch, close the ticket with PR link + merge SHA. Hand a pure multi-ticket *code-only* slice to `code:loop`, which owns exactly this spine. |
| **Browser / portal / order / sign-in web** | `browser` + secrets; complete the real flow; screenshot or quoted UI state as proof; close ticket with proof. |
| **Native app** | `computer` skill; same proof bar. |
| **Design / assets** | `design` plugin / image skills; attach artifact. |
| **Outreach / content** | Browser or channel tools as appropriate; send only when the item clearly authorizes send; otherwise draft + leave a single link for the human (still unattended for the draft). |
| **Research** | Browser + WebSearch; write the brief/artifact; no user mid-flight. |

`/work:dispatch` remains the one-item primitive; this skill **batches** and **spreads**.

## What "done" means here

| Outcome | Counts as done for this loop |
|---|---|
| Engineering | PR **merged** on green behind a non-author review, worktree removed, branch deleted, ticket closed with PR link + merge SHA. A distributable (published CLI, extension, deployed app) is not done until its repository-specific release process is verified live. |
| Non-coding agent-complete | Real-world action finished + proof (screenshot path, URL, send receipt) |
| Blocked | Ticket parked with *exact* missing decision/credential; continue others |
| Genuinely the user's call | A product/scope/taste decision, a credential only they hold, or a governance sign-off — park it with the decision stated in one line, and keep draining the rest |

**"PR open" is not an outcome.** It is the middle of the engineering row. An unattended
loop that ends the night with a stack of open PRs has moved the whole queue onto the one
person who was not there — the exact failure this skill exists to prevent.

The four things that still stop a merge, all of them red, none of them "ask the user":
CI red (fix the cause), a review that found real problems (address it, push, re-request),
a merge conflict (rebase onto fresh `origin/$BASE`), or branch protection refusing the
merge. Never `gh pr merge --admin`, never approve your own PR, never merge red.

Queue empty or only parked items → short recap: merged · shipped · parked (with whose
call each one is) · what re-homed because of limits/logouts.

**Every row above is a postcondition you must CHECK, not infer.** A dispatched agent that
hit a wall, explained it, and exited is an `exit 0` with zero work done — the most common
unattended failure there is. Before marking an item done: query the PR, re-read the
ticket, confirm the artifact exists. If you cannot observe it, the item is **unverified**,
not done — park it with the gap named. See `parallel-teams`.

## Unattended rules

- No `AskUserQuestion`. No "want me to continue?".
- No Telegram unless the invocation prompt literally supplies a notify one-liner (Muqsit
  prefers no Telegram — skip phone notify unless the prompt overrides).
- Ticket comments are the durable record.
- Overlap: if another `work:loop` / drain is live on the same queue, coordinate (skip
  claimed ids); optional lock dir `/tmp/work-loop-<host>.lock` with staleness steal for
  cron invocations.

## Anti-patterns

- Running the whole night as one Claude session on one host
- Pinning a single account until it rate-limits, then stopping
- Ending the drain with open PRs and naming the user as the one who reviews and merges
- Treating a green CI + clean review as a reason to stop rather than a reason to merge
- Waiting on the user for anything that is not a real product/scope/credential decision
- Skipping browser/computer when the ticket is clearly a web/native task
- Asking the user for context that sessions, comments, or code already hold
- Flooding the interactive laptop with teammates
- Claiming "done" without a PR link or real-world proof
- Trusting a dispatched agent's `exit 0` instead of checking what it produced
- Certifying a box with a read-only ping, then sending it write-heavy work
- Re-querying the tracker per item until the shared API quota dies for everyone
- Reading a result file from a prior run as if it belonged to this one

## Compose map

| Need | Use |
|---|---|
| Single clear item now | `/work:dispatch` (or this skill with a one-item queue) |
| Engineering patterns (worktree, claim, review, merge-on-green) | `code:loop` — including its "done means merged" completion |
| Post-merge publish for a distributable | Repository-specific release process — merge is the middle for anything users install or visit |
| Board keep/cancel decisions | `triage` mode (`/work:loop triage`) — do not invent cancels during a plain drain |
| Parallel fan-out mechanics | `swarm:orchestrate` / `agents teams` |
| Schedule every night | `agents routines` YAML calling this skill unattended |

