| name | vibe-parallel |
| description | Parallel task execution using Claude Code subagents. Reads task files, builds dependency waves, detects file conflicts AND read-write conflicts, and spawns tasks as parallel subagents. Size-aware wave splitting unlocks downstream tasks early when large tasks are in the same wave as small ones. If vibe-graph is installed, each subagent gets a targeted context slice instead of full CODEBASE.md — 60-70% cheaper per subagent on large projects. Structured subagent reporting with [x]/[~]/[!] states. Diagnostic retry on failure. Live wave progress log at vibe/parallel/. Post-wave graph update. Wave cost annotation for vibe-cost. Triggers on "parallel:" prefix, "run tasks in parallel", "spawn subagents", "parallelise the build", "which tasks can run in parallel", "run independent tasks simultaneously". Called automatically by vibe-add-feature, vibe-fix-bug, vibe-new-app when VIBE_MODE=autonomous or parallel tasks exist and user approves.
|
Vibe Parallel Skill v2
Identifies independent tasks, builds dependency waves, and dispatches
each wave as parallel subagents via Claude Code.
What's new in v2:
- Read-write conflict detection (not just Touches field)
- Size-aware wave splitting (L tasks don't hold back S task dependents)
- Graph-aware context slicing per subagent (if vibe-graph installed)
- Structured subagent reporting with [x] / [~] / [!] states
- Diagnostic retry on failure (targeted, not blind)
- Live wave progress log written to vibe/parallel/
- Post-wave vibe-graph update
- Wave cost annotation for vibe-cost
The principle
Independent tasks have no reason to run one after another.
If task B does not depend on task A — they run at the same time.
Subagents execute in parallel within the same Claude Code session.
The main session orchestrates: spawns waves, waits for completion,
unlocks the next wave, runs automatically until done.
How it integrates with VIBE_MODE
grep "VIBE_MODE" CLAUDE.md 2>/dev/null | cut -d= -f2 | tr -d ' '
VIBE_MODE=autonomous:
Parallel detection runs automatically after every planning skill.
No prompt — if independent tasks exist, subagents spawn immediately.
VIBE_MODE=manual (default):
Shows the parallel plan. Asks once: "Run in parallel? (y/n)"
If n — sequential execution, user drives with next.
If y — subagents spawn.
On-demand (parallel: command):
Always shows the plan and asks — regardless of VIBE_MODE.
The user explicitly invoked it, so confirm before launching.
Entry points
Entry point A — On demand
Triggered by: parallel: prefix
Read vibe/TASKS.md for all pending tasks.
Always show plan + ask (y/n), regardless of VIBE_MODE.
Entry point B — Called by vibe-add-feature
Source: vibe/features/[date-slug]/FEATURE_TASKS.md
VIBE_MODE=autonomous → skip prompt, launch directly.
VIBE_MODE=manual → show plan, ask (y/n).
Entry point C — Called by vibe-fix-bug
Source: vibe/bugs/[date-slug]/BUG_TASKS.md
Same mode logic as Entry B.
Entry point D — Called by vibe-new-app
Source: vibe/TASKS.md Phase 1 tasks only.
Same mode logic as Entry B.
Step 0 — Read project context
grep "VIBE_MODE" CLAUDE.md 2>/dev/null | cut -d= -f2 | tr -d ' '
mkdir -p vibe/parallel
Read references/WAVE_BUILDER.md — dependency graph and conflict detection logic.
Read references/SUBAGENT_CONTEXT.md — context slicing and prompt construction.
Read references/REPORTING.md — structured completion report format.
Read vibe/ARCHITECTURE.md — conventions every subagent must follow.
Check for vibe-graph:
ls vibe/graph/DEPENDENCY_GRAPH.json 2>/dev/null && echo "GRAPH_AVAILABLE" || echo "NO_GRAPH"
ls vibe/graph/.graph-meta.json 2>/dev/null && echo "META_AVAILABLE" || echo "NO_META"
Store result — used in Step 3 for context slicing.
Step 1 — Parse tasks
Read the source task file in full.
Extract for each pending [ ] task:
tasks = []
for each task block:
task = {
"id": "[TASK-ID]",
"title": "[Task title]",
"size": "S" | "M" | "L",
"dependencies": [],
"touches": [],
"reads": [],
"description": "[What to do]",
"criteria": [],
"spec_ref": "[section]",
"codebase_update": bool,
"arch_ref": "[which patterns apply]"
}
tasks.append(task)
Inferring reads when not explicitly listed:
A task Reads a file when any of these are true:
- The task description says "use", "call", "import", "extend", "read" a specific file
- The task type is "test" — it reads the file it's testing
- The task is a route handler — it reads the service/agent it calls
- The task is a component — it reads the model/API it consumes
If reads cannot be inferred confidently — leave empty and treat conservatively.
Step 2 — Build dependency waves
Read references/WAVE_BUILDER.md for the full algorithm.
Summary:
Pass 1 — Standard dependency resolution:
Wave 1: tasks where dependencies = [] (or all deps already [x])
Wave 2: tasks whose deps are all in Wave 1
Wave N: tasks whose deps are all in Wave N-1
Pass 2 — File conflict check (write-write):
If two tasks in the same wave both WRITE the same file:
→ Move the alphabetically-later task ID to the next wave.
Exception: vibe/CODEBASE.md and vibe/DECISIONS.md — append-only, safe.
Pass 3 — Read-write conflict check:
If Task A WRITES a file and Task B READS that same file, and both are in the same wave:
→ Task B must move to the next wave — it needs Task A's output.
This catches inheritance, base class, and schema dependencies missed by Touches alone.
Pass 4 — Size-aware wave splitting:
Read references/WAVE_BUILDER.md for the full algorithm.
Short version: if Wave N contains an L task alongside S/M tasks, and some
Wave N+1 tasks depend only on the S/M tasks (not the L task) — those
Wave N+1 tasks can be promoted to run alongside the L task in Wave N as
a "fast lane." The L task and the promoted tasks run in parallel; the
remaining Wave N+1 tasks unlock after both the L task and fast lane complete.
Minimum threshold:
If Wave 1 has only 1 task → no parallelism available.
Autonomous mode: proceed sequentially, no mention of parallel.
Manual mode: proceed sequentially, no prompt shown.
Step 3 — Build subagent context slices
Read references/SUBAGENT_CONTEXT.md for the full algorithm.
Summary:
For each task, build a context slice — the minimum context a subagent
needs to execute that task correctly.
If vibe-graph is available:
def build_context_slice(task, graph, meta):
slice = {
"task_files": task["touches"],
"imports": [],
"concept": None,
"rationale": [],
"god_nodes": [],
"architecture": [],
}
for file in task["touches"]:
node = graph.get(file, {})
for edge in node.get("imports", []):
if isinstance(edge, dict) and edge.get("source") == "EXTRACTED":
slice["imports"].append(edge["file"])
elif isinstance(edge, str):
slice["imports"].append(edge)
slice["rationale"].extend(node.get("rationale", []))
if not slice["concept"]:
slice["concept"] = node.get("concept")
god_node_files = {gn["file"] for gn in meta.get("god_nodes", [])}
for f in slice["imports"] + slice["task_files"]:
if f in god_node_files:
gn = next(gn for gn in meta["god_nodes"] if gn["file"] == f)
slice["god_nodes"].append(gn)
return slice
Context slice replaces CODEBASE.md in the subagent prompt.
CODEBASE.md is NOT loaded by subagents when vibe-graph is available.
If no vibe-graph:
Fall back to providing: CODEBASE.md + ARCHITECTURE.md (standard).
Context size estimate:
Step 4 — Present plan (manual mode only)
In autonomous mode — skip this step entirely.
⚡ PARALLEL EXECUTION PLAN
Wave 1 — [N] tasks run simultaneously:
· [TASK-ID] (S) — [description]
· [TASK-ID] (M) — [description]
· [TASK-ID] (L) — [description] ← long task
Fast lane (runs with Wave 1 L task, unblocked early):
· [TASK-ID] (S) — [description] ← depends only on Wave 1 S/M tasks
Wave 2 — [N] tasks unlock when Wave 1 completes:
· [TASK-ID] (M) — [description]
[Wave N...]
Conflict resolution:
[TASK-ID] moved to Wave 2 — write conflict on src/models/brand_dna.py
[TASK-ID] moved to Wave 2 — read-write conflict (reads base_agent.py written by [TASK-ID])
Context mode: [graph-aware slicing (vibe-graph) | full CODEBASE.md]
Est. time: sequential ~[N]h → parallel ~[N]h (saving ~[N]h)
Est. cost: [graph: ~$X per wave | no graph: ~$Y per wave]
Run in parallel? (y/n)
Wait for response. If n → exit, return to sequential flow.
Step 5 — Initialise wave progress log
Before dispatching any subagent, write the initial status file:
mkdir -p vibe/parallel
cat > vibe/parallel/wave-[N]-status.md << 'EOF'
Started: [ISO timestamp]
| ID | Size | Status | Started | Completed | Duration |
|----|------|--------|---------|-----------|----------|
| [TASK-ID] | S | 🔄 running | [time] | — | — |
| [TASK-ID] | M | 🔄 running | [time] | — | — |
| [TASK-ID] | L | 🔄 running | [time] | — | — |
Total tasks: [N]
Complete: 0
Failed: 0
Partial: 0
Wave [N+1] — waiting (unlocks when all Wave [N] tasks complete)
EOF
Update this file as each subagent reports completion.
Step 6 — Execute wave as parallel subagents
Read references/SUBAGENT_CONTEXT.md for the full subagent prompt format.
Build the subagent prompt for each task:
You are executing [TASK-ID] as part of a parallel build.
═══ PROJECT CONTEXT ═══
[IF graph available:]
Architecture patterns: [relevant sections from ARCHITECTURE.md]
Your concept: [concept name] — [concept description from CONCEPT_GRAPH]
Your files:
[for each file in task touches:]
[file_path] ([type])
Imports: [EXTRACTED imports]
[if rationale exists:]
Rationale:
[WHY/DECISION/HACK entries]
[if god nodes in slice:]
⚠️ GOD NODE WARNING:
[file] — [N] connections. Changes here affect [N] other files.
Be especially careful with any modifications to this file.
[IF no graph:]
Read vibe/CODEBASE.md and vibe/ARCHITECTURE.md for project context.
═══ YOUR TASK ═══
[Full task block verbatim from FEATURE_TASKS.md / BUG_TASKS.md / TASKS.md]
═══ SCOPE BOUNDARIES ═══
Files you MAY write:
[Touches field contents]
Files you must NOT write (assigned to other parallel tasks):
[all Touches fields from other Wave N tasks]
Files you MAY read (your imports):
[slice imports list]
═══ COMPLETION REPORT ═══
When your task is complete, output this report EXACTLY:
TASK_COMPLETE: [TASK-ID]
STATUS: [DONE|PARTIAL|FAILED]
FILES_MODIFIED: [comma-separated list]
FILES_CREATED: [comma-separated list]
TESTS_PASSED: [N]/[total]
CRITERIA:
[x] [criterion 1]
[x] [criterion 2]
[ ] [criterion 3 — NOT MET: reason]
CODEBASE_UPDATE: [YES: what changed | NO]
BLOCKERS: [none | description of anything downstream tasks should know]
RATIONALE_ADDED: [YES: what WHY/DECISION comments were added | NO]
Dispatch all tasks in the wave simultaneously as subagents.
Parse completion reports:
Read references/REPORTING.md for the full parsing logic.
For each subagent completion report:
def parse_completion(report):
status = extract("STATUS", report)
criteria = parse_criteria(report)
unmet = [c for c in criteria if not c["met"]]
if status == "DONE" and not unmet:
return "COMPLETE"
elif status == "PARTIAL" or unmet:
return "PARTIAL"
elif status == "FAILED":
return "FAILED"
Task states:
[x] — fully complete, all criteria met, tests passed
[~] — partially complete, some criteria unmet — downstream tasks are WARNED
[!] — failed — trigger diagnostic retry
Step 7 — Handle failures and partial completions
Partial completion [~]
A task is partial when:
- All code is written but one or more acceptance criteria not met
- Tests pass but not all criteria are verifiable automatically
- Task completed but CODEBASE.md update was skipped
Action:
Log the unmet criteria in the wave progress file.
Warn downstream tasks in their subagent prompts:
⚠️ UPSTREAM WARNING from [TASK-ID]:
[criterion] was not fully met: [reason]
Your task may need to account for this — verify before marking done.
Do NOT block downstream tasks. Propagate the warning.
Hard failure [!]
A task fails when: STATUS=FAILED, or tests fail, or the subagent errors out.
Diagnostic retry (not blind retry):
Read references/REPORTING.md for the diagnostic extraction logic.
def build_diagnostic_retry(task, failure_report):
error = extract_error(failure_report)
cause = diagnose(error, task)
return f"""
RETRY — [TASK-ID]
Your previous attempt failed:
Error: {error}
Most likely cause: {cause}
Targeted approach for this retry:
{targeted_fix(cause, task)}
[Original task prompt]
[Same scope boundaries]
[Same completion report format]
"""
On retry → if COMPLETE: mark [x], continue.
On retry → if still FAILED: mark [!], stop wave, surface to human.
Stop condition:
Any task that fails twice stops the entire wave.
Do not proceed to the next wave.
Report clearly:
🔴 WAVE [N] PAUSED
[TASK-ID] failed after retry.
Error: [specific error from second attempt]
Completed tasks this wave: [list — marked [x] in task file]
Partial tasks: [list — marked [~]]
Failed task: [TASK-ID]
Fix the failure, then say "resume" to continue with Wave [N+1].
The completed tasks do not need to be re-run.
Step 8 — Update task file and progress log
After all subagents in the wave complete (or fail):
Update FEATURE_TASKS.md / BUG_TASKS.md / TASKS.md:
[x] TASK-001 · [description] ← complete
[~] TASK-002 · [description] ← partial — [unmet criterion]
[!] TASK-003 · [description] ← failed — [error summary]
Update CODEBASE.md (batched — main session only):
Collect all FILES_MODIFIED and FILES_CREATED from completion reports.
The main session updates vibe/CODEBASE.md once — not during parallel execution.
Each subagent reports what it changed; the main session writes the update.
Update wave progress log:
# Wave [N] — complete
Started: [time] · Completed: [time] · Duration: [Xm Ys]
## Tasks
| ID | Size | Status | Started | Completed | Duration |
|----|------|--------|---------|-----------|----------|
| TASK-001 | S | ✅ complete | 14:23:00 | 14:23:42 | 42s |
| TASK-002 | M | 🟡 partial | 14:23:00 | 14:24:15 | 75s |
| TASK-003 | L | ❌ failed | 14:23:00 | 14:26:00 | 3m |
## Summary
Total tasks: 3 · Complete: 1 · Partial: 1 · Failed: 1
## Unmet criteria
TASK-002: [criterion] — [reason]
## Files modified this wave
[complete list from all completion reports]
## Cost
Subagent tokens: ~[N] (estimated)
Context mode: graph-aware slicing
Approx cost: ~$[X]
vs sequential: ~$[Y] (parallel [cheaper/more expensive] by $[delta])
Time saved vs sequential: ~[N] minutes
Update vibe/TASKS.md "What just happened":
✅ Wave [N] complete — [N] tasks done · [N] partial · [N] failed
[task IDs]
Cost: ~$[X] · Time saved: ~[N]min
Step 9 — vibe-graph update (post-wave)
After each wave completes, run one graph update:
vibe-graph: update
The git diff captures all subagent writes in a single pass.
More reliable than each subagent updating the graph independently —
subagents can't safely write the same JSON file concurrently.
If vibe-graph not installed — skip this step silently.
Step 10 — Execute remaining waves
For each subsequent wave:
Check if wave is unlocked:
All tasks in this wave have their dependencies marked [x].
Tasks depending on a [~] partial task — include the upstream warning in their prompt.
If any dependency is [!] — that wave cannot proceed. Stop.
Apply size-aware splitting to subsequent waves too.
Repeat Steps 5–9 for each wave.
Wave with 1 task → run as single subagent (no parallelism, but still automatic).
Wave with 2+ tasks → parallel subagents.
Step 11 — All waves complete
Emit cost summary:
⚡ Parallel execution complete
Waves:
Wave 1: [N] tasks ✅ · [N]m [N]s · ~$[X]
Wave 2: [N] tasks ✅ · [N]m [N]s · ~$[X]
Totals:
Tasks complete: [N]/[N]
Tasks partial: [N] (see vibe/parallel/ for unmet criteria)
Time taken: [Xm]
Est. sequential: ~[N]h
Time saved: ~[N]h ([N]% faster)
Total cost: ~$[X]
Context mode: [graph-aware | full CODEBASE.md]
Progress log: vibe/parallel/
In autonomous mode:
Signal completion to the calling skill.
Do not stop — let vibe-add-feature / vibe-fix-bug / vibe-new-app
invoke the review gate automatically.
In manual mode:
Run review: to gate this phase.
Absolute rules
Never give two subagents the same file to write.
Write-write conflicts caught in Step 2 Pass 2 before any subagent launches.
Read-write conflicts are real conflicts.
Task B reading a file Task A writes — Task B must wait.
Caught in Step 2 Pass 3. Never skipped.
Each subagent is completely isolated.
No subagent reads another subagent's in-progress work.
They read the codebase as it existed before Wave 1 started.
Results merged by main session after wave completes.
[~] partial tasks never block — they warn.
A partial task passes its unmet criteria as warnings to downstream tasks.
Downstream tasks decide how to handle. They are not blocked.
[!] failed tasks always stop the wave.
On second failure — stop, report clearly, wait for human.
Never mark a task [x] if tests did not pass.
CODEBASE.md updates are batched by the main session.
Each subagent reports changes. Main session writes CODEBASE.md once.
This prevents concurrent JSON write conflicts.
Graph updates happen once per wave — not per subagent.
vibe-graph: update runs after wave completion.
Git diff captures all subagent writes accurately.
Autonomous mode never skips the review gate.
When all waves complete, signal for review.
It runs automatically, but it always runs.
Cost annotation is always included.
Every wave completion includes token estimate and cost.
Even if vibe-cost is not installed — the annotation is written
to the progress log so vibe-cost can read it later.