warp-delegate
Delegate a coding task to the Warp Agent CLI (`oz`) as a background implementer, then review its diff and land it yourself. Use this whenever the user wants to hand implementation work to Warp - phrasings like "have Warp implement X", "delegate this to the Warp CLI", "run it thro
Install
npx skills add https://github.com/amElnagdy/delegate-skills/tree/master/skills/warp-delegate
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install amelnagdy-delegate-skills@llmmart
git clone https://github.com/amElnagdy/delegate-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole amelnagdy/delegate-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Warp Delegate
You are the orchestrator. Delegate a bounded coding task to a separate implementer - the Warp Agent CLI - then review what it produced and land it yourself. You write the brief and own the judgment; the implementer makes changes in its own conversation; you verify and commit.
The loop needs only a shell command and file access, so any comparable orchestrator can drive it.
The binary is oz, not warp
Warp ships two different programs, and only one of them can be delegated to:
oz- the Warp Agent CLI. Headless and scriptable;oz agent runexecutes an agent against a local directory. This is what the relay drives.warp- the interactive Warp TUI. It requires a terminal device, has no prompt or print flag (its only options are--resume,--auto-approve,--api-key, and the provider-key commands), and exits withDevice not configuredwhen stdin is a pipe. It cannot be relayed.
If oz is missing but warp is installed, you have the TUI, not the CLI.
When NOT to use this
- The task is small enough to do inline; delegation overhead is not worth it.
- The
ozCLI is not installed or authenticated. - You need a sandboxed or read-only implementer.
oz agent runhas no sandbox, no permission mode, and no read-only run - see Autonomy and permissions. - The work must stay off Warp's servers.
oz agent runuploads an end-of-run workspace snapshot unless--no-snapshotis passed, and conversations live server-side.
Prerequisites (check once)
- Install the Warp Agent CLI - see https://docs.warp.dev/cli/.
- Authenticate:
oz login, or setWARP_API_KEYfor CI, a container, or any headless host. - Confirm the account has AI quota. A working login is not enough - unlike the other CLIs in
this package.
oz whoamican succeed while every dispatch fails withIn order to use Warp's AI features, subscribe to a Warp plan, or bring your own inference.Warp records this internally asQuotaLimit/ "lack of AI quota", so it is a credit condition on the account rather than a CLI-specific entitlement:ozruns the same agent harness as the Warp app and draws on the same account, plan, and credits. Check thatoz whoaminames the account holding the plan - if it does not,oz logout && oz loginfixes it. Otherwise confirm the plan's AI credits are not spent, or store your own provider key -warp --set-provider-api-key <openai|anthropic|google|grok>, or/api-keysinside the TUI. Bring-your-own-key needs no paid Warp plan. - Confirm
oz --versionsucceeds andoz whoamiprints your user. - Work in, or point
--cdat, the target git repository.
On macOS the CLI is distributed as a signed Developer ID binary; a first run may be held by Gatekeeper until it is approved.
Choose the model (optional)
Omit --model to use Warp's configured default. To pick another, choose an id from oz model list
and pass it verbatim. The relay accepts letters, digits, and . _ : / - only, so a value cannot be
mistaken for another oz flag.
The loop
Run these five steps per task. Steps 1, 4, and 5 require judgment; 2 and 3 are mechanical.
1. Write the brief
Warp sees only the text you send plus what it can inspect in the workspace - no chat history or
shared context. Include the goal, current state, what to change, what to leave untouched, the
project's actual gates, and a report contract. Tell it not to commit. Keep one task per brief.
The brief is delivered as the --prompt value on argv, so it is visible in the host process list -
keep secrets out of it and reference workspace files instead. See
references/writing-the-brief.md.
2. Dispatch
Use the bundled relay. It runs oz agent run --output-format ndjson, captures the event stream, and
writes result.json. (<skill-dir> is the installed folder containing this SKILL.md.)
node "<skill-dir>/scripts/relay.mjs" --brief brief.txt --cd /path/to/repo
# choose a model: add --model <id from oz model list>
# use an agent profile: add --profile <id>
# label the run: add --name <label>
# continue an existing conversation: add --conversation <id> (delta brief only)
# base the run on a Warp skill: add --skill <name|repo:name|org/repo:name>
# start MCP servers: add --mcp <path-or-inline-json> (repeatable)
# suppress the workspace snapshot upload: add --no-snapshot
# hard time limit (watchdog): add --timeout 2h (the 30m default suits short runs; implementation briefs routinely need 1-2h)
# see all options: node .../relay.mjs --help
The relay pins the workspace with both the child process's cwd and Warp's own --cwd. It writes
artifacts under the system temp dir by default and never commits. See
references/dispatch-and-poll.md.
3. Wait for completion
The relay blocks until oz finishes. Run it with the orchestrator's background-command facility, or
background it in the shell and poll for result.json. A pre-run usage error exits 2 and writes no
result; a missing oz exits 127 and writes status: "warp_unavailable".
Trust process state and the working tree over a progress display. Completion means the process
exited and result.json exists. Warp's report is the finalMessage field in result.json (also
printed on stdout between the report markers); the raw event stream is always in events.jsonl.
4. Review - do not trust the self-report
Treat Warp's final message and gate claims as claims:
- Re-run the project's gates yourself.
- Read the diff against the brief, starting with
touchedFiles. - Run relevant guard skills if installed.
- Round-trip migrations and grep for dangling references after removals or renames.
Because there is no read-only mode to fall back on, the diff is the only record you get - and it records what git can see in the workspace afterward, not everything the run did. Dispatch from a clean tree so the two are as close as they can be. See references/review-and-land.md.
5. Land it
The implementer edits the working tree; the orchestrator commits. Commit only after the gates
pass and the diff holds. If rework is needed, send a delta brief with --conversation <id> using the
conversationId from result.json, then review again.
Autonomy and permissions
oz agent run has no sandbox, no permission mode, and no read-only mode. A headless run reads,
writes, edits, and executes commands with your own user permissions and never prompts. There is
nothing in the CLI to restrict that surface, so this relay ships no --read-only flag - offering one
would imply an enforcement that does not exist. The controls you actually have are:
- Scope by directory.
--cdpins the workspace, and the relay passes it to Warp's own--cwd. Treat this as aim, not a fence: on oz 0.2026.05.27 shell commands did run in the pinned workspace, but the agent's file tool resolved bare relative paths against$HOME. Name absolute paths in the brief - see references/writing-the-brief.md. - Review the diff.
touchedFilesisgit status --porcelaintaken after the run - post-run, git-visible worktree state, not a log of what the agent did. It cannot show an ignored file, an edit the run made and then reverted, or a write outside the repository (see item 1), and it carries anything that was already dirty before dispatch. Dispatch from a clean tree so those are the same set, and treat the diff as the best available record, not a complete one. - Snapshot egress.
--no-snapshotforwards Warp's flag so the end-of-run workspace snapshot is not uploaded. Without it, the upload is Warp's default.
--auto-approve belongs to the interactive warp TUI and has no bearing on oz agent run.
Authorization model
Delegation is something the human opts into. Once they have ("run this queue", "proceed"), committing verified, gate-passing work is the agreed contract. Two limits remain: surface, don't absorb (report Warp's design decisions, defensible-but-unasked turns, and non-blocking nitpicks) and stop for scope changes (if correct completion needs going beyond the brief, ask instead of expanding the mandate). See references/review-and-land.md.
References
- references/writing-the-brief.md - structure, report contract, real gates, argv delivery, and delta briefs.
- references/dispatch-and-poll.md - flags, artifacts,
result.json, polling, and failure recovery. - references/review-and-land.md - review checklist, commit boundary, and rework through Warp conversations.
- references/multi-task-queues.md - sequential queues, constraint carry-forward, progress tracking, and the final coherence pass.
Files (delegate-skills)
-
references
-
dispatch-and-poll.md 8.4 KB
# Dispatch and poll The relay is the only Warp-specific machinery in this skill. It launches `oz agent run`, captures the event stream, and writes one result file the orchestrator can read. ## What the relay runs ```text oz agent run --output-format ndjson --cwd <cd> [--model …] [--profile …] [--name …] [--conversation …] [--skill …] [--mcp … …] [--no-snapshot] --prompt <brief> ``` `--output-format ndjson` makes Warp emit one JSON object per line, so a long run reports progress instead of buffering to the end. The workspace is pinned twice: the child process's cwd and Warp's own `--cwd`. ## Flags | Flag | Effect | | --- | --- | | `--brief <file>` | Path to the brief. Omit to read it from stdin. | | `--cd <dir>` | Working root (default: current directory). Also passed as Warp's `--cwd`. | | `--lane <name>` | Resolve dials from a `delegate-setup` fleet lane. Explicit flags win. | | `--model <id>` | Warp model id from `oz model list`. Letters, digits, and `. _ : / -` only. | | `--profile <id>` | Warp agent profile. | | `--name <label>` | Labels the run in Warp's own run list. | | `--conversation <id>` | Continue an existing Warp conversation. Send a delta brief only. | | `--skill <spec>` | Warp skill as the base prompt: `name`, `repo:name`, or `org/repo:name`. | | `--mcp <spec>` | MCP config path or inline JSON. Repeatable. | | `--no-snapshot` | Forward Warp's `--no-snapshot` so no end-of-run workspace snapshot is uploaded. | | `--timeout <dur>` | Relay watchdog, h/m/s (default `30m`). Warp has no timeout flag of its own. | | `--out-dir <dir>` | Artifact directory (default: a fresh dir under the system temp dir). | Values for `--model`, `--profile`, and `--conversation` are token-validated. `--skill`, `--mcp`, and `--name` accept freer text but must not start with `-`, which `oz` would read as another flag. ## Artifacts Written to `--out-dir`: - `brief.txt` — exactly what was sent. - `events.jsonl` — the raw ndjson stream, byte for byte. The fallback whenever a parsed field looks wrong. - `final.txt` — the assembled report, when one was captured. - `stderr.txt` — everything Warp wrote to stderr. - `result.json` — the structured result, written atomically via a temp file and rename, so a polling reader never sees a half-written file. ## `result.json` Schema id `delegate-relay.result.v1`. Synthetic example: ```json { "schema": "delegate-relay.result.v1", "tool": "oz", "status": "completed", "exitCode": 0, "signal": null, "ozVersion": "Oz v0.0000.00.00.00.00.stable_01", "workdir": "/path/to/repo", "model": null, "profile": null, "snapshotDisabled": false, "resumed": false, "runId": "00000000-0000-0000-0000-000000000000", "runUrl": "https://oz.warp.dev/runs/00000000-0000-0000-0000-000000000000", "conversationId": null, "finalMessage": "Changed src/export/csv.ts …", "touchedFiles": [" M src/export/csv.ts", "?? src/export/csv.test.ts"], "startedAt": "2026-01-01T00:00:00.000Z", "finishedAt": "2026-01-01T00:04:12.000Z" } ``` Field notes: - **`status`** — `completed`, `failed`, `timeout`, `aborted`, or `warp_unavailable`. - **`touchedFiles`** — `git status --porcelain` lines. `null` when git cannot report (not a repository, git missing); `[]` when the tree is genuinely clean. `[]` and `null` mean different things — do not collapse them. - **`runId` / `runUrl`** — from Warp's `run_started` system event. `runUrl` opens the run in Warp. - **`conversationId`** — the handle to pass back as `--conversation` for rework. Present only when Warp emitted it on the stream. - **`finalMessage`** — Warp's own report. Assembled from the text-bearing events in the stream; see the caveat below. - **`stderrTail`** — last 20 stderr lines, included on every non-clean outcome. ### What `finalMessage` actually contains Confirmed against a live edit run on oz 0.2026.05.27. The stream carries: | Event | Meaning | | --- | --- | | `{"type":"system","event_type":"run_started","run_id":…,"run_url":…}` | Run registered. | | `{"type":"system","event_type":"conversation_started","conversation_id":…}` | The `--conversation` handle. Re-emitted on a resumed run carrying the *same* id, so `conversationId` stays stable across a rework chain. | | `{"type":"agent","text":…}` | Agent output. **This is what `finalMessage` is built from.** | | `{"type":"agent_reasoning","text":…}` | Private reasoning. Same shape, deliberately **excluded**. | | `{"type":"tool_call"\|"tool_result"\|"tool_error",…}` | Tool traffic. No `text` field. | Two consequences: - **`finalMessage` is the whole narration, not just the closing report.** Warp emits no distinct final-message event, so every `agent` chunk is concatenated — including running commentary like "Now let me run both gates." This is why the brief must specify a report contract: `FILES:` / `GATES:` / `NOTES:` at the end gives you a stable anchor to read instead of parsing prose. - **`agent_reasoning` must stay excluded.** It carries a `text` field of exactly the same shape, so matching on `text` alone splices the model's reasoning into the report. Past those two rules the extraction stays tolerant — it also accepts `agent_output`, `content`, and a nested `message.content` — so a renamed output event still reports rather than yielding an empty `finalMessage`. If one ever does come back empty on a successful run, `events.jsonl` holds the raw stream and `collectText` is the one place to correct. ## Exit codes | Code | Meaning | | --- | --- | | `0` | Warp exited 0 and reported no stream error. | | `1` | Generic failure, or a stream-reported agent error even when `oz` exited 0. | | `2` | Usage error — bad flag, bad `--timeout`, missing or empty brief. **No result file is written.** | | `124` | The bounded `oz --version` preflight timed out; Warp was never dispatched. | | `127` | `oz` is not on PATH. A result file **is** written, with `status: "warp_unavailable"`. | | `128 + n` | The child died on signal *n*; `signal` records which. | ## Polling The relay blocks until the run ends. Background it and poll for `result.json`: ```bash node "<skill-dir>/scripts/relay.mjs" --brief brief.txt --cd /path/to/repo \ --out-dir /tmp/warp-run-1 & until [ -f /tmp/warp-run-1/result.json ]; do sleep 5; done ``` Completion means the process exited **and** `result.json` exists. Do not infer completion from stdout going quiet — a long tool call looks identical to a finished run. ## Timeouts and aborts `oz` has no timeout flag, so the watchdog is the relay's. When `--timeout` expires the relay kills the whole process group (SIGTERM, then SIGKILL after 10s) and writes `status: "timeout"`. If the relay itself is killed, it still writes `status: "aborted"`, forwards the kill to `oz`, and re-snapshots `touchedFiles` after a 2-second grace window so files flushed during shutdown are recorded. On Windows the process tree is felled with `taskkill /t /f`; Windows delivers no catchable SIGTERM, so the aborted path cannot be driven there. **A timed-out or aborted run leaves a partially edited tree.** Inspect `git status` and `git diff` before re-dispatching. If the state is incoherent, discard it against the recorded baseline rather than stashing — a bare `git stash` leaves behind every file the run created. See [review-and-land.md](review-and-land.md#rework-through-a-conversation). ## Failure recovery | Symptom | What it means | Do | | --- | --- | --- | | `warp_unavailable`, exit 127 | `oz` is not on PATH | Install the Warp Agent CLI; check `oz --version`. | | stderr `subscribe to a Warp plan, or bring your own inference` | Authenticated, but the account has no AI quota. Warp logs it as `QuotaLimit` / "lack of AI quota". `oz` shares the Warp app's account, plan, and credits, so this is a credit condition, not a CLI-only gate | Check `oz whoami` names the account holding the plan - if not, `oz logout && oz login`. Otherwise confirm its AI credits are not spent, or store your own provider key: `warp --set-provider-api-key <openai\|anthropic\|google\|grok>` (or `/api-keys` in the TUI). Bring-your-own-key needs no paid plan. Warp's log is at `~/Library/Logs/oz/warp.log` on macOS. | | `Device not configured` | The `warp` TUI was launched, not `oz` | Use `oz`; the TUI cannot be relayed. | | exit 2, no result file | Usage error | Read the relay's stderr line; fix the flag. | | `status: "timeout"` | The watchdog fired | Raise `--timeout`, or split the brief. | | Empty `finalMessage`, exit 0 | Text extraction missed the event shape | Read `events.jsonl`; see the caveat above. | -
multi-task-queues.md 3.6 KB
# Multi-task queues A queue is a list of briefs run through Warp one at a time, each reviewed before the next is dispatched. It is the shape to reach for when the user hands you a backlog rather than a single task. ## Run them sequentially Dispatch one brief, review it, land it, then dispatch the next. Parallel runs against the same working tree interleave edits into a diff nobody can review — and because `oz agent run` has no sandbox, there is nothing to keep two runs out of each other's files. If tasks are genuinely independent and you want them concurrent, give each its own checkout (a git worktree) and its own `--cd`. Otherwise, keep the queue serial. ## Carry constraints forward Each brief is self-contained, so a constraint discovered in task 2 does not reach task 5 by itself. Keep a short running list and paste the relevant lines into every subsequent brief: - Conventions you had to correct in an earlier review ("use the existing `Result` type, not exceptions"). - Files that are off-limits for the whole queue. - Gates that turned out to be slow, flaky, or need a flag. - Decisions already made, so a later task does not relitigate them. A constraint that had to be corrected twice belongs in the repository's own skill directory (`.agents/skills/`, `.warp/skills/`) instead — then pass it with `--skill` and stop re-pasting it. ## One out-dir per task Give every dispatch its own `--out-dir` so artifacts do not overwrite each other: ```bash node "<skill-dir>/scripts/relay.mjs" --brief briefs/03-stream-export.txt \ --cd /path/to/repo --out-dir /tmp/warp-queue/03 --name "queue-03-stream-export" ``` `--name` labels the run in Warp's own run list, which makes a queue far easier to follow later. Keeping the out-dirs numbered means `result.json`, `events.jsonl`, and `final.txt` for any task stay recoverable after the queue has moved on. ## Track progress where the user can see it Maintain a visible checklist — the orchestrator's task list, or a scratch file — with one line per task and its state: pending, dispatched, under review, landed, or abandoned. Record the commit sha as each task lands, and the reason whenever one is abandoned. ## When a task fails Do not roll straight into the next brief. Decide first: - **Rework** — the diff is close. Continue the conversation with `--conversation <id>` and a delta brief. - **Re-scope** — the task was too big or the brief was wrong. Split it and requeue the parts. - **Abandon** — it depends on something that is not true yet. Record why and move on. A failed task that leaves a dirty tree must be cleaned up before the next dispatch. `git status` should be clean, or clean except for work you have deliberately kept. ## Stop the queue when - Two consecutive tasks fail for the same underlying reason — the shared assumption is wrong, and the remaining briefs probably inherit it. - A task reveals the plan itself is wrong. Re-plan with the user rather than working the list. - The gates start failing for reasons unrelated to the current task; something earlier in the queue broke and the diff is no longer trustworthy. ## Final coherence pass Ten individually correct diffs can still add up to an incoherent whole. When the queue is done, review the aggregate — `git diff <first-commit>~1..HEAD`: - Duplicated helpers that separate tasks each introduced. - Naming that drifted between early and late tasks. - Docs, types, or tests that an earlier task's assumption made stale. - Dead code left by a later task superseding an earlier one. Fix these yourself if small. If the cleanup is substantial, it is one more brief — dispatch it with the aggregate diff as the current state. -
review-and-land.md 7.3 KB
# Review and land Warp edits the working tree. **You commit.** That boundary is the point of the skill: the implementer produces a diff, and a reviewer who did not write it decides whether it ships. ## Why the review is not optional here Every delegate skill asks you to verify the implementer's claims. Warp raises the stakes: `oz agent run` has no sandbox, no permission mode, and no read-only run, so nothing constrained what the run could touch while it worked. The diff is not a courtesy record — it is the only record. ## The checklist Work through these in order. Stop at the first one that fails and decide whether to rework or discard. 1. **Read `result.json` first.** If there is no `result.json`, stop: a usage error exits 2 before Warp is ever dispatched and writes none, so an absent file means the run did not happen — read the relay's stderr, not the tree. Otherwise require `status: "completed"` and `exitCode: 0` before going further. `failed`, `timeout`, `aborted`, and `warp_unavailable` all mean the run did not finish on its own terms, and `timeout` and `aborted` additionally mean the tree may be mid-edit and incoherent. Rework or discard from the baseline rather than reviewing a partial run. 2. **Start from `touchedFiles`.** It is `git status --porcelain` taken after the run: post-run, git-visible worktree state, not a log of what the agent did. It cannot show an ignored file, an edit the run made and then reverted, or a write outside the repository, and it includes anything already dirty before dispatch. Start there, but do not read it as the complete set. `null` means git could not report — inspect the tree by hand. `[]` on a run that claimed edits is a contradiction worth chasing. 3. **Re-run the gates yourself.** Do not accept "tests pass" from `finalMessage`. Run the project's actual lint, typecheck, build, and test commands and read the output. Take "actual" from `CONTRIBUTING.md`, the CI config, or `package.json`: a project's gate set often includes a packaging, manifest, or schema validation step that lint and test do not cover, and that is exactly the gate a run can break without any test going red. 4. **Read the whole diff against the brief.** `git diff` and `git diff --staged` — then open every `??` path in `touchedFiles` directly, including everything inside an untracked directory. Neither diff command shows the contents of an untracked file, so a file Warp created is invisible to both and would otherwise reach your commit unread. Ask of each hunk and each new file: did the brief ask for this? Changes outside the brief's stated scope are the thing to catch. 5. **Check what should NOT have changed.** Lockfiles, CI config, formatter config, unrelated modules, and anything the brief listed under "leave untouched". 6. **Grep for dangling references** after any removal or rename — imports, string keys, docs. 7. **Round-trip migrations.** Apply and roll back before trusting a schema change. 8. **Run guard skills** if the repository has them installed. 9. **Confirm nothing was committed.** `git log -1` should still be your last commit. The relay never commits; if a commit exists, the agent made it despite the brief — treat that as a finding. ## Reading `finalMessage` correctly `finalMessage` is Warp's self-report: a claim, not evidence. Read it for two things only — - **Decisions it made that the brief did not specify.** These are the parts you most need to surface to the user. - **What it says it could not do.** Usually accurate, and it tells you where to look first. Everything else in it — "all tests pass", "no other files changed" — is a hypothesis your gates and your diff read either confirm or refute. If `finalMessage` is empty on a run that exited 0, read `events.jsonl` rather than assuming the run did nothing. ## Rework through a conversation When the diff is close but wrong, continue the same conversation rather than starting cold: ```bash node "<skill-dir>/scripts/relay.mjs" --brief delta-brief.txt --cd /path/to/repo \ --conversation "$(jq -r .conversationId /tmp/warp-run-1/result.json)" ``` Warp still holds the earlier exchange, so send only the delta — what was wrong, what to change, what to leave alone. See [writing-the-brief.md](writing-the-brief.md#delta-briefs). If `conversationId` is `null`, the stream did not carry one; dispatch a fresh run with a brief that restates the corrected requirements. Discard rather than rework when the diff misunderstood the goal, wanders far outside the brief, or would take longer to correct than to redo. Discard against a known baseline, never with a blanket revert. `git checkout -- .` is the wrong reach: it leaves staged and untracked files behind, so the tree stays dirty for the next dispatch, and it destroys any uncommitted work of your own that predates the run. Dispatch from a clean tree — commit your own changes, or `git stash push --include-untracked` them. A bare `git stash` leaves untracked files in place, and those resurface as `??` entries in `touchedFiles`, where the cleanup below would delete work the run never made. Confirm `git status --porcelain` prints nothing before dispatching, so that everything dirty afterward is Warp's, then drop exactly what the run introduced, reading the paths off `touchedFiles`: ```bash git restore --staged --worktree -- <tracked paths> # the ' M' / 'M ' entries git clean -f -- <untracked paths> # the '??' entries ``` A `??` entry can name a whole directory rather than each file under it; passing that path removes the directory and its contents, since `-d` only governs the no-pathspec case. The exception is a nested git repository — if the run scaffolded one, `git clean -f` skips it and `-ff` is required. If dispatching from a clean tree is not an option, give Warp its own `git worktree` instead: then discarding is `git worktree remove --force`, and your work was never in reach. Either way, rewrite the brief before dispatching again. ## Landing Commit once the gates pass and the diff holds. Write the commit message yourself: it should describe the change, not the delegation. Do not credit the tool in the message unless the project's own convention asks for it. ## Surface, don't absorb Delegation is something the human opted into, and committing verified, gate-passing work is the agreed contract. Two limits stay with you: - **Surface, don't absorb.** Report Warp's design decisions, its defensible-but-unasked turns, and the non-blocking nitpicks you chose not to fix. Silently smoothing them over hides the implementer's judgment from the person who owns the code. - **Stop for scope changes.** If finishing correctly requires going beyond the brief — a dependency bump, a schema change, an interface the brief did not mention — ask rather than expanding the mandate yourself. Snapshot egress is a decision you make **before** dispatch, not something you report after it. `oz agent run` uploads an end-of-run workspace snapshot by default, so reading `snapshotDisabled: false` off a finished run tells you only that the upload already happened. If the repository is sensitive, pass `--no-snapshot` on the dispatch and confirm `snapshotDisabled: true` in `result.json` before going further. Keep reporting the field either way — it is the evidence of which way the run went. Also surface the `runUrl` when someone will want to inspect the run in Warp. -
writing-the-brief.md 5 KB
# Writing the brief The brief is the whole contract. Warp sees only the text you send plus whatever it can inspect in the workspace — no chat history, no shared context, none of the reasoning that led you here. ## How the brief reaches Warp `oz agent run` requires one of `--prompt`, `--saved-prompt`, `--task-id`, or `--skill`. Its `-f/--file` config path does **not** satisfy that requirement, so there is no stdin or file channel for the task text: the relay passes the brief as the `--prompt` value on argv. Two consequences that do not apply to the other skills in this package: - **The brief is visible in the host process list** (`ps`, Activity Monitor, Task Manager) for as long as the run is live. Keep credentials, tokens, and customer data out of it. Point Warp at a file in the repo or an environment variable instead of inlining a secret. - **A very large brief can hit the OS argument limit.** Practical briefs are far below it, but a brief that inlines whole files can trip it. Reference paths rather than pasting file contents — Warp can read the workspace itself. Because the brief rides argv, the relay never launches `oz` through a shell on any platform. ## Structure Cover these in order. Skip a heading only when it genuinely does not apply. 1. **Goal** — one sentence on the outcome, not the mechanics. 2. **Current state** — where the code is now, and the paths that matter. **Name the workspace root as an absolute path**, and prefer absolute paths for the files you call out. `--cwd` is not uniformly honoured: on a verified run against oz 0.2026.05.27, shell commands executed in the pinned workspace (`pwd` returned it), but the agent stated its working directory was `/` and its file-reading tool resolved bare relative paths against `$HOME` — so `src/strings.js` was first read as `/Users/<you>/src/strings.js`. The agent recovered by running `pwd` and retrying, but it burned a turn, and in a home directory that happened to hold a matching path it would have read the wrong file. There is no sandbox to catch that. 3. **What to change** — the specific edits, in the order they make sense. 4. **What to leave untouched** — files, patterns, and public interfaces that must not move. Warp has no sandbox, so this is a written boundary, not an enforced one. 5. **Gates** — the project's *actual* commands. Read them out of `package.json`, `Makefile`, or the CI config; do not invent `npm test` because it is conventional. 6. **Report contract** — what the final message must state (below). 7. **Do not commit** — say it explicitly. Committing is the orchestrator's job. ## The report contract Ask for a final message that states, plainly: - What changed, file by file. - Which gate commands were run, and their exact outcome. - Anything the run could not do, and why. - Any decision it made that the brief did not specify. The relay captures that message as `finalMessage` in `result.json` and as `final.txt`. Treat it as a claim to verify, never as verification — see [review-and-land.md](review-and-land.md). ## Repository context files Warp reads skills from `.agents/skills/`, `.warp/skills/`, `.claude/skills/`, and `.codex/skills/`. If the repository carries conventions in one of those, name it with the relay's `--skill` flag (`name`, `repo:name`, or `org/repo:name`) so it becomes the base prompt and your brief stays the task. Anything not in one of those locations — a plain `CONTRIBUTING.md`, for instance — must be referenced by path in the brief; do not assume it is loaded. ## One task per brief A brief that carries two unrelated changes produces a diff you cannot review cleanly and a conversation you cannot resume precisely. Split them and queue the parts — see [multi-task-queues.md](multi-task-queues.md). ## Delta briefs When you continue a conversation with `--conversation <id>`, Warp still holds the earlier exchange. Send only what changed: - What you reviewed and what was wrong — be specific about the file and the symptom. - What to do about it. - What to leave alone from the previous round. - The gates to re-run. Do not re-send the original brief. Restating a satisfied requirement invites Warp to redo work that was already correct. ## Worked example ```text Goal: make the CSV export stream instead of buffering the whole result set. Current state: src/export/csv.ts builds one string in memory (see toCsv) and returns it from the /export route in src/routes/export.ts. Change: - Rewrite toCsv to return a Readable that yields one row at a time. - Update the /export route to pipe that stream to the response. - Keep the column order and the quoting behaviour exactly as they are now. Leave untouched: the public signature of toCsv's caller in src/routes/export.ts beyond the pipe change, and every file under src/import/. Gates: `npm run lint`, `npm run typecheck`, `npm test -- export`. Report: list each file you changed, quote the exact output of each gate command, and state anything you could not finish. Do not commit. Leave the changes in the working tree. ```
-
-
scripts
-
relay.mjs 33.2 KB · in bundle
-
-
SKILL.md 10.1 KB
--- name: warp-delegate description: >- Delegate a coding task to the Warp Agent CLI (`oz`) as a background implementer, then review its diff and land it yourself. Use this whenever the user wants to hand implementation work to Warp - phrasings like "have Warp implement X", "delegate this to the Warp CLI", "run it through Warp", "use oz to implement/fix/refactor" - or wants to run a queue of coding tasks through Warp while staying the reviewer. DO NOT USE for tasks small enough to do inline, when the user wants the code written directly without delegating, or for the interactive `warp` TUI (this skill drives the headless `oz agent run`, not the terminal app). license: MIT compatibility: Requires the `oz` CLI (Warp Agent CLI) installed and authenticated (`oz login`, or `WARP_API_KEY` for a headless host; Warp AI features need an eligible Warp plan or your own provider key), Node 18+, and git. The orchestrating agent must be able to run shell commands and read files. Shell examples assume bash/zsh (macOS/Linux, or Git Bash/WSL on Windows). metadata: version: 0.5.0 --- # Warp Delegate You are the **orchestrator**. Delegate a bounded coding task to a separate **implementer** - the Warp Agent CLI - then review what it produced and land it yourself. You write the brief and own the judgment; the implementer makes changes in its own conversation; you verify and commit. The loop needs only a shell command and file access, so any comparable orchestrator can drive it. ## The binary is `oz`, not `warp` Warp ships two different programs, and only one of them can be delegated to: - **`oz`** - the Warp Agent CLI. Headless and scriptable; `oz agent run` executes an agent against a local directory. **This is what the relay drives.** - **`warp`** - the interactive Warp TUI. It requires a terminal device, has no prompt or print flag (its only options are `--resume`, `--auto-approve`, `--api-key`, and the provider-key commands), and exits with `Device not configured` when stdin is a pipe. It cannot be relayed. If `oz` is missing but `warp` is installed, you have the TUI, not the CLI. ## When NOT to use this - The task is small enough to do inline; delegation overhead is not worth it. - The `oz` CLI is not installed or authenticated. - You need a sandboxed or read-only implementer. `oz agent run` has **no sandbox, no permission mode, and no read-only run** - see [Autonomy and permissions](#autonomy-and-permissions). - The work must stay off Warp's servers. `oz agent run` uploads an end-of-run workspace snapshot unless `--no-snapshot` is passed, and conversations live server-side. ## Prerequisites (check once) 1. Install the Warp Agent CLI - see <https://docs.warp.dev/cli/>. 2. Authenticate: `oz login`, or set `WARP_API_KEY` for CI, a container, or any headless host. 3. Confirm the account has AI quota. **A working login is not enough** - unlike the other CLIs in this package. `oz whoami` can succeed while every dispatch fails with `In order to use Warp's AI features, subscribe to a Warp plan, or bring your own inference.` Warp records this internally as `QuotaLimit` / "lack of AI quota", so it is a credit condition on the account rather than a CLI-specific entitlement: `oz` runs the same agent harness as the Warp app and draws on the same account, plan, and credits. Check that `oz whoami` names the account holding the plan - if it does not, `oz logout && oz login` fixes it. Otherwise confirm the plan's AI credits are not spent, or store your own provider key - `warp --set-provider-api-key <openai|anthropic|google|grok>`, or `/api-keys` inside the TUI. Bring-your-own-key needs no paid Warp plan. 4. Confirm `oz --version` succeeds and `oz whoami` prints your user. 5. Work in, or point `--cd` at, the target git repository. On macOS the CLI is distributed as a signed Developer ID binary; a first run may be held by Gatekeeper until it is approved. ## Choose the model (optional) Omit `--model` to use Warp's configured default. To pick another, choose an id from `oz model list` and pass it verbatim. The relay accepts letters, digits, and `. _ : / -` only, so a value cannot be mistaken for another `oz` flag. ## The loop Run these five steps per task. Steps 1, 4, and 5 require judgment; 2 and 3 are mechanical. ### 1. Write the brief Warp sees only the text you send plus what it can inspect in the workspace - no chat history or shared context. Include the goal, current state, what to change, what to leave untouched, the project's **actual** gates, and a report contract. Tell it not to commit. Keep one task per brief. The brief is delivered as the `--prompt` value on argv, so it is visible in the host process list - keep secrets out of it and reference workspace files instead. See [references/writing-the-brief.md](references/writing-the-brief.md). ### 2. Dispatch Use the bundled relay. It runs `oz agent run --output-format ndjson`, captures the event stream, and writes `result.json`. (`<skill-dir>` is the installed folder containing this `SKILL.md`.) ```bash node "<skill-dir>/scripts/relay.mjs" --brief brief.txt --cd /path/to/repo # choose a model: add --model <id from oz model list> # use an agent profile: add --profile <id> # label the run: add --name <label> # continue an existing conversation: add --conversation <id> (delta brief only) # base the run on a Warp skill: add --skill <name|repo:name|org/repo:name> # start MCP servers: add --mcp <path-or-inline-json> (repeatable) # suppress the workspace snapshot upload: add --no-snapshot # hard time limit (watchdog): add --timeout 2h (the 30m default suits short runs; implementation briefs routinely need 1-2h) # see all options: node .../relay.mjs --help ``` The relay pins the workspace with both the child process's cwd and Warp's own `--cwd`. It writes artifacts under the system temp dir by default and never commits. See [references/dispatch-and-poll.md](references/dispatch-and-poll.md). ### 3. Wait for completion The relay blocks until `oz` finishes. Run it with the orchestrator's background-command facility, or background it in the shell and poll for `result.json`. A pre-run usage error exits 2 and writes no result; a missing `oz` exits 127 and writes `status: "warp_unavailable"`. Trust process state and the working tree over a progress display. Completion means the process exited and `result.json` exists. Warp's report is the `finalMessage` field in `result.json` (also printed on stdout between the report markers); the raw event stream is always in `events.jsonl`. ### 4. Review - do not trust the self-report Treat Warp's final message and gate claims as claims: - Re-run the project's gates yourself. - Read the diff against the brief, starting with `touchedFiles`. - Run relevant guard skills if installed. - Round-trip migrations and grep for dangling references after removals or renames. Because there is no read-only mode to fall back on, the diff is the **only** record you get - and it records what git can see in the workspace afterward, not everything the run did. Dispatch from a clean tree so the two are as close as they can be. See [references/review-and-land.md](references/review-and-land.md). ### 5. Land it The implementer edits the working tree; **the orchestrator commits.** Commit only after the gates pass and the diff holds. If rework is needed, send a delta brief with `--conversation <id>` using the `conversationId` from `result.json`, then review again. ## Autonomy and permissions `oz agent run` has **no sandbox, no permission mode, and no read-only mode**. A headless run reads, writes, edits, and executes commands with your own user permissions and never prompts. There is nothing in the CLI to restrict that surface, so this relay ships no `--read-only` flag - offering one would imply an enforcement that does not exist. The controls you actually have are: 1. **Scope by directory.** `--cd` pins the workspace, and the relay passes it to Warp's own `--cwd`. Treat this as *aim*, not a fence: on oz 0.2026.05.27 shell commands did run in the pinned workspace, but the agent's file tool resolved bare relative paths against `$HOME`. Name absolute paths in the brief - see [references/writing-the-brief.md](references/writing-the-brief.md). 2. **Review the diff.** `touchedFiles` is `git status --porcelain` taken after the run - post-run, git-visible worktree state, not a log of what the agent did. It cannot show an ignored file, an edit the run made and then reverted, or a write outside the repository (see item 1), and it carries anything that was already dirty before dispatch. Dispatch from a clean tree so those are the same set, and treat the diff as the best available record, not a complete one. 3. **Snapshot egress.** `--no-snapshot` forwards Warp's flag so the end-of-run workspace snapshot is not uploaded. Without it, the upload is Warp's default. `--auto-approve` belongs to the interactive `warp` TUI and has no bearing on `oz agent run`. ## Authorization model Delegation is something the human opts into. Once they have ("run this queue", "proceed"), committing verified, gate-passing work is the agreed contract. Two limits remain: **surface, don't absorb** (report Warp's design decisions, defensible-but-unasked turns, and non-blocking nitpicks) and **stop for scope changes** (if correct completion needs going beyond the brief, ask instead of expanding the mandate). See [references/review-and-land.md](references/review-and-land.md). ## References - [references/writing-the-brief.md](references/writing-the-brief.md) - structure, report contract, real gates, argv delivery, and delta briefs. - [references/dispatch-and-poll.md](references/dispatch-and-poll.md) - flags, artifacts, `result.json`, polling, and failure recovery. - [references/review-and-land.md](references/review-and-land.md) - review checklist, commit boundary, and rework through Warp conversations. - [references/multi-task-queues.md](references/multi-task-queues.md) - sequential queues, constraint carry-forward, progress tracking, and the final coherence pass.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.