prun (parallel run)

SkillProductivity

Parallel delegation fan-out. The Claude session coordinates (on whatever Claude model is currently selected, e.g. Opus or Fable) while task units run in parallel on workers (never on the coordinator). Codex (`codex exec`, a separate abundant account) is the prioritized default; Sonnet is reserved fo

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the prun (parallel run) skill

What this skill tells your AI

The instructions your AI receives, as published by yzhao062/anywhere-agents in skills/prun/SKILL.md and read by ahel’s review.

Overview

prun fans a task out into independent units that run in parallel while the current session only coordinates. Workers are Sonnet subagents inside a Claude session and Agy processes running Gemini through the Antigravity CLI. Sonnet is the in-session executor and the only route to session tools. Agy supplies the independent Google model family, a separate subscription pool, and the faster turnaround, so it carries the larger share of ordinary units. Codex is not a prun executor; reserve its higher-cost quota for the default /vet gatekeeper role. The coordinator decomposes the task, dispatches the units, gathers their results, reviews their diffs, and integrates. It never runs a unit itself.

The orchestrator picks the executor per unit: session-internal tools go to Sonnet, and Agy takes the larger share of everything else while its pool is healthy. Sonnet units share the current Claude account. Agy units use the Google AI plan authenticated in agy. Exact plan buckets can change, so inspect current quota before a large batch.

Relationship to the native Workflow tool

The native Workflow tool fans a task out across Claude subagents under a deterministic script, with structured output, judge panels, and resume. A Workflow run counts against the Anthropic plan's usage and rate limits, and its agents use the session model unless the script routes a stage to a different Claude model.

prun supports two account paths. A Sonnet unit shares the current Claude account with the coordinating session. An Agy unit runs Gemini through an authenticated Antigravity CLI and uses the Google AI plan attached to it. Use the Executors rule below to choose each unit's executor. The coordinating session also spends a small Anthropic amount while it decomposes, dispatches, reads results, and integrates.

The two relate in two ways, both with the current session as the orchestrator:

  • Substitute (quota). Read both pools with agent-quota, including snapshot age and reset times. If Claude cannot accommodate the next batch, route suitable units to Agy or defer them. Do not silently shrink a genuinely parallel task to an arbitrary two or three workers. A quota reading does not establish that the other account can finish the batch.
  • Complement (diversity). When a Workflow is affordable and the user's request or an applicable project requirement calls for a cross-vendor perspective, run a Claude panel through the Workflow and a Gemini panel through Agy. Use the same structured contract and the same question on both sides, then cross-check. Agreement across vendors is usually a stronger signal than agreement inside one model family, because shared model lineage and tools can share blind spots. Invoke them together in one natural-language request; no special mode is needed. Reserve this for high-stakes work (a review, an audit, a hard design call), since it spends both pools and the coordinator must merge two result sets.

When to use

Use prun when the task splits into independent units that can run at once (different modules, separate research questions, parallel analyses). Units may be heterogeneous, and there can be many of them: a dozen or twenty in parallel is normal when the task warrants it.

Do not use prun when the task is one sequential unit, or units depend on each other's output, or a unit's result cannot be checked without redoing it.

Executors

ExecutorQuotaNotes
Sonnet subagentCurrent Claude account; check Settings > Usage for the applicable limits or creditsIn-session executor. The only route to session-internal tools (MCP / email / Artifacts), and the fallback when the Agy pool is the constraint.
Agy (agy)Google AI plan authenticated in AntigravityTakes the larger share. Gemini 3.8 Flash High at high effort; fast, separately funded, and dispatched with full unattended tool permission inside a scratch dir or throwaway clone.
Claude session (this session)Current Claude account; check Settings > Usage for the applicable limits or creditsCoordinator and integrator only, on whatever model is selected. Never a unit.

Rule: units never run on the coordinator (the Claude session itself). The orchestrator picks the executor per unit:

  • Session-internal tools stay on Sonnet. An external Agy process cannot use the coordinator's MCP, email connectors, or Artifact tool. That capability boundary is independent of quota. A Sonnet subagent inherits the session's available tools but starts with fresh context, so put all needed state in its unit prompt.
  • Agy takes the larger share of everything else while its pool is healthy: research, verification, extraction, cross-checks, and code-writing units in a throwaway clone. It is fast, its quota is separate from the Claude plan, and the dispatcher gives it the same unattended capability as the /vet Agy reviewer, so a unit can verify numbers, run experiments, and fetch the web. Agy defaults to gemini-3.8-flash-high at the CLI's maximum high effort. Route a unit to Sonnet instead when the Agy pool is the constraint, when the unit needs a Claude-side tool, or when the user or a project-local routing policy says so.
  • Keep the Agy pool busy with follow-up turns. Agy units usually return well before the Sonnet ones. When one returns while others are still running, dispatch a follow-up Agy unit rather than idling, provided the follow-up discharges real work: an acceptance criterion the result left open, a claim it made without evidence, a source it cited but did not fetch, a check it proposed but did not run, or the next independent unit in the queue. A slower sibling is not by itself a reason to invent work. --continue-from <state-dir> resumes the same conversation, so the follow-up keeps the earlier context; a fresh prompt with a fresh result path is the alternative. Record each follow-up in the ledger like any other unit.
  • Codex is excluded from prun. Its quota is intentionally reserved for the /vet reviewer role. Do not route a prun unit to codex exec, even if a legacy dispatcher remains on disk for compatibility with old state directories.
  • When in doubt: session tools to Sonnet, everything else to Agy. An explicit user instruction or a project-local routing policy may change the split for a run.
  • The Claude session stays the coordinator, never a unit. A single small session-tool action may stay inline; independent substantive work belongs in workers.

Why the split is Sonnet plus Agy. They draw on separate subscription pools and provide model- family diversity without spending the higher-cost Codex pool used by /vet. Agy carries the larger share because it is fast and its pool is large; that is a routing and cost decision, not a universal quality ranking, and the coordinator still reviews every result and every diff. Check current quota before a large batch, but do not convert changing meter readings into an arbitrary low worker cap.

Concurrency

The orchestrator decides the unit count autonomously. Partition the task by dependency structure (split only along genuinely independent boundaries) and balanced workload (roughly equal-sized units, each worth a full worker run). High autonomy is the intent: do not target a fixed number, and do not cap artificially. A dozen-plus in parallel is fine when the task genuinely decomposes that way.

Two soft bounds, not hard rules: local CPU/RAM (enough concurrent workers eventually contend and the excess queues) and the headroom of the Claude and Agy pools. agent-quota reads current snapshots for both. The usual real ceiling is integration bandwidth, since the orchestrator must read and reconcile every result, so prefer fewer well-scoped units over many tiny ones. Over-splitting into trivial units wastes worker startup and tends to produce thin results. Dispatch in batches that fit the runtime's concurrent-worker limit and the available quota, and leave the rest queued; a runtime's in-flight limit is separate from how many units a run may have in total.

What a unit may do, and the one rule

A unit may read or write code, run commands, and fetch the web, with full access. The single hard rule: a worker never commits, pushes, or runs destructive git (commit, push, branch/tag mutation, reset --hard, clean). Everything else is allowed. The final gate is the Claude session integrating the results and the user deciding; workers never touch the real repo history.

This is enforced structurally, not by trust:

  • Read-only / research units run from a per-unit scratch cwd, so accidental writes stay out of the repo. dispatch-task does this by default.
  • Code-writing units run inside a throwaway local clone of the repo with its remote removed:
    git clone --local -c core.longpaths=true <repo> <clone-dir>   # longpaths: Windows MAX_PATH safety
    git -C <clone-dir> remote remove origin
    
    The worker edits freely in the clone. An accidental git push has no remote to reach (GitHub / Overleaf stay untouched); an accidental git commit only lands in the throwaway clone. The coordinator reads git -C <clone-dir> diff, integrates the wanted changes into the real tree, and the user approves the actual commit. That is the only gate.

No credential scrubbing or sandbox wall: the user writes the prompts, the clone has no path to the real remotes, and the Claude session plus the user are the integration gate. That is the whole safety model.

Flow

  1. Gate: confirm the task splits into independent, checkable units. Else use a single worker.
  2. Decompose: write one prompt per unit. State the task; for a code-writing unit, that the working dir is a throwaway clone to edit freely but not commit or push; that the unit writes a result summary to its result file (a fresh path, in one write).
  3. Assign: apply the Executors rule (session tools to Sonnet, the larger share of the rest to Agy) and record the routing reason in the ledger. Also pick read-only (scratch) or code-writing (clone) mode. For a web-heavy unit, "Web access" below covers which executor fits.
  4. Dispatch in parallel:
    • Agy unit: run <python> scripts/dispatch-task-agy.py in the background. With no --mode it runs accept-edits with --dangerously-skip-permissions in a scratch directory it creates. A caller-supplied workspace, meaning PRUN_SCRATCH_CWD (a throwaway clone for a code-writing unit) or --add-dir (a clone or snapshot the unit should see), requires an explicit --mode accept-edits or --mode plan, so the write-capable mode is a named choice for any directory the dispatcher did not create. --continue-from <state-dir> resumes an earlier unit's conversation for a follow-up turn.
    • Sonnet unit: spawn a background Agent subagent with model: sonnet. It inherits the session's available tools, including MCP and connector tools; if you set a tools allowlist, include every connector, Artifact, file, shell, and web tool the unit needs. The subagent starts with fresh context, so put any needed state in its prompt. For code-writing it works in a clone too, under Claude's guard.py, which already gates commit/push.
  5. Monitor (do not go idle): the shell monitor covers Agy units only. It reads the dispatch-task-agy state markers (tail, dispatch-pid, result-file) that a Sonnet Agent invocation never writes, and it takes no Agent identifier. For Sonnet units, track the Agent identifiers recorded in the ledger and use the runtime's own task-status and completion tools, checking again on a schedule while any unit is outstanding. Result-file validation and the step-6 reconciliation are common to both. For the Agy units, launch scripts/monitor.{sh,ps1} <state-dir> ... in the background (run_in_background=true) and wait on its completion. It wakes you on the first actionable event: all done, any unit stalled (tail no-growth for PRUN_STALL_THRESHOLD, default 10 min), or any unit failed (FALLBACK result or dead dispatch), printing a per-unit digest. On a stall, surface it to the user with a likely cause (capacity or concurrency pressure; suggest lowering the worker count or re-dispatching) rather than waiting silently; act, then re-launch the monitor on the still-running units until all are done. monitor only observes. The Agy dispatcher relies on the CLI's bounded --print-timeout; it does not scan for or terminate unrelated agent processes. (gather.{sh,ps1} remains for the plain wait-for-all case.)
  6. Reconcile, then integrate: before integrating, reconcile the ledger: every dispatched unit must have a non-empty result. If any is missing or empty, do not integrate the partial set; recover an Agy worker's output from its <state-dir>/tail (dispatch-task-agy also salvages the tail into the result file automatically under a FALLBACK header), or retrieve a Sonnet worker's returned output through its recorded Agent identifier using the runtime's completion/output tools. If no usable result can be recovered, re-dispatch that unit or flag the user. Then the coordinator reads each result plus each clone's git diff, merges the wanted changes into the real tree, runs verification, and asks the user before any commit.

Resolve scripts via this order, first hit wins: skills/prun/scripts/, then .claude/skills/prun/scripts/, then .agent-config/repo/skills/prun/scripts/.

dispatch-task usage (Agy)

<python> scripts/dispatch-task-agy.py --prompt-file <prompt> --result-file <fresh abs result> --unit-id <id>
  • Emits exactly one stdout line STATE-DIR <abs-path>; Agy stream events and stderr land in the state directory, the conversation id from Agy's init event is recorded to <state-dir>/conversation-id, and the final response is published atomically to the result path.
  • Defaults to gemini-3.8-flash-high at high effort. Override with ANTIGRAVITY_DISPATCH_MODEL and ANTIGRAVITY_DISPATCH_EFFORT. Agy takes --effort for its Gemini models only, so the dispatcher omits the flag for the second group below rather than having Agy reject the whole call.
  • Agy Ultra exposes a second quota group for claude-sonnet-4-6, claude-opus-4-6-thinking, and gpt-oss-120b-medium. Keep Gemini as the default because it adds an independent model family to the Sonnet fan-out. The second group is an explicit overflow option through ANTIGRAVITY_DISPATCH_MODEL; it adds quota, not reviewer-family diversity. Naming it is the user's call. A fan-out that reached for it on its own spent 646 generations of that group in a day, on units a Gemini worker would have taken, and the group is the smaller of the two.
  • The dispatcher checks group quota before launching. The two groups are metered separately, and one dispatch names one model, so a batch aimed at an empty group fails once per unit: on 2026-09-11 four units of a seven-unit fan-out died in a row, each carrying Individual quota reached ... Resets in 34m. Before launching, the dispatcher reads the snapshot agent-quota maintains and decides:
    • The Claude and GPT group is empty and Gemini is not: dispatch the Gemini default instead, and record the swap. The line MODEL-FALLBACK from=... to=... reason=claude-and-gpt-quota-exhausted resets=... goes to stderr and to <state-dir>/quota-note. <state-dir>/model always names the model that actually ran, so the ledger's executor column is not the model the caller asked for when the two differ.
    • The Gemini group is empty: exit 75 without launching, and say so. It does not escalate into the metered group on its own; the message names ANTIGRAVITY_DISPATCH_MODEL for the operator who wants that.
    • Both groups are empty: exit 75 with both reset times.
    • A group the snapshot does not report is unknown rather than empty, and an unreadable snapshot skips the check entirely. The gate stops a dispatch only into a group it read as empty. PRUN_AGY_QUOTA_GATE=off disables it. A run that fails at the backend forces a snapshot refresh before exiting, past the readout's own five-minute TTL, because the meter it just hit is newer evidence than the snapshot. Later units then route on what it recorded. This is not a guarantee: a refresh that cannot run, a meter that is unavailable, and units already in flight can still produce repeated quota errors.
  • --mode defaults to accept-edits with --dangerously-skip-permissions, the same unattended capability the implement-review Gemini reviewer already runs with, so a unit can verify numbers, run experiments, and fetch the web without a permission prompt. The default applies only to the scratch directory the dispatcher creates. When the caller supplies a workspace through PRUN_SCRATCH_CWD or --add-dir, the dispatcher refuses to launch until --mode is given, because the write-capable mode could otherwise reach a directory it did not create. Safety stays structural either way: point those at a throwaway clone with no remote or a read-only snapshot, never the real tree. --mode plan is the strictly read-only opt-in; it keeps request-review permissions and never gets the skip flag. In headless use a tool request that needs an approval nobody can give (run_command, read_url, browser tools) is denied, and the process can still exit 0 with a normal-looking result that reports it could not verify. A normal result file therefore does not prove those checks ran; read its Verification and Open items fields. If the worker has not written a non-empty result file, a missing, empty, or shorter-than-20-byte final response produces FALLBACK, and so does a final result event whose status is not SUCCESS. A standing permissions.allow rule in Agy's own settings.json (~/.gemini/antigravity-cli/settings.json, entries such as read_url(*) or command(*)) is the alternative for a plan-mode unit.
  • --add-dir PATH (repeatable) adds a directory outside the unit's working directory to its workspace without copying a repository into the scratch area, in either mode; it requires an explicit --mode. Point it at a clone or a read-only snapshot, never the real tree, since accept-edits can write there. The dispatcher resolves each path to absolute and refuses to launch if it is empty or not an existing directory.
  • --continue-from STATE_DIR resumes the conversation recorded at <STATE_DIR>/conversation-id for a follow-up dispatch that should keep the earlier turn's context instead of re-embedding the prior result in a new prompt. It still needs its own fresh --result-file; an empty STATE_DIR argument, or one whose conversation id file is missing or empty, is a pre-launch error.
  • Requires a fresh result path and refuses to overwrite an existing result. The final response is published to that path, unless the worker already wrote a non-empty result file there itself: then the worker's file is kept and the final response lands beside it as <result>.response.<ext>, so a one-line closing reply never replaces a full result. If no non-empty worker result exists, a failed preflight, launch, worker run, or timeout, or an unusable final response, produces an atomic FALLBACK result with captured tails.
  • Both signals decide the outcome. A non-zero process exit fails the unit, and after an exit of 0 the final result event's status is consulted, because Agy exits 0 when it stops on a quota limit and that ERROR event still carries the opening narration in response. Publishing that response would hand the coordinator work that never happened. Any status other than SUCCESS fails the unit and carries the event's error text into the FALLBACK result. The one exception is a status that is missing or blank, which counts as success so that an older Agy keeps working.
  • A failed run whose worker had already written its own result keeps that file, because the worker may have finished before the backend stopped. The partial response lands beside it as <result>.response.<ext>, and the dispatcher exits non-zero with the backend error on stderr. Both monitors classify a stable worker-written result as done without reading the backend status. Before integrating such a unit, wait for the dispatcher to finish and check its exit code. When that code is unavailable, read the result event's status and error in <state-dir>/tail and the captured dispatch diagnostics. The sibling response is supporting context: a successful run writes one too, and it records no status.
  • ANTIGRAVITY_DISPATCH_TIMEOUT_SECONDS defaults to 2700 and is passed to Agy's bounded --print-timeout. The dispatcher never enumerates or terminates another agent process.
  • The dispatcher omits Agy's --sandbox flag by default. On Windows that sandbox starts an elevated admin broker and raises a UAC prompt for every unit that runs a command; a declined prompt fails the command. PRUN_AGY_SANDBOX controls whether the flag is added; it does not disable a sandbox enabled in Agy's own settings (enableTerminalSandbox). Accepted values are 1/true/yes/on to add the flag and 0/false/no/off, empty, or unset to omit it. Values ignore case and surrounding whitespace; anything else exits 2 before state creation or launch. Scratch directories and throwaway clones reduce accidental changes to the working repository. They do not enforce filesystem or network isolation; the worker must follow the prompt's ban on commit, push, and destructive git.
  • The legacy dispatch-task.{sh,ps1} Codex scripts remain shipped only so older deployments and state directories retain their recovery tooling. Current prun routing never selects them.

Sonnet usage

Sonnet is the executor for a unit needing session-internal tools (see Executors) and the fallback when the Agy pool is the constraint. Spawn an Agent-tool subagent with model: sonnet. It inherits the session's available tools but starts with fresh context (it does not see the conversation), so put any needed state in the unit prompt. Give it the same return contract and result-file path. For a code-writing unit, point it at a clone dir; commit and push are also gated by guard.py on the Claude side.

gather usage

scripts/gather.sh <result-file-1> <result-file-2> ...
  • Prints GATHER-START count=N timeout=Ss, then DONE <abs-path> per file as it lands; exits 0 when all land, exits 2 with TIMEOUT remaining=<k>.
  • A file is "landed" when it exists, is non-empty, and has been quiet for the stable window (default 10s); no startup-snapshot race.
  • Use a fresh result path per unit per run (delete any stale file before dispatch). Have each unit write its result in one operation.

monitor usage

scripts/monitor.sh <state-dir-1> <state-dir-2> ...

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
244
Forks
26
Last commit
Sep 2026

ahel review

  • K6low
    bundled executables the agent is told to run

Automated review, not a security audit. Ruleset v1+k2.

Advanced
Catalog kind
skill
Gateway key
prun
Source
github.com/yzhao062/anywhere-agents