| name | parallel |
| description | Parallel execution patterns for montaj — load when workflow has multiple clips or foreach steps |
| step | false |
Parallel Execution
Important: Claude Code's Bash tool executes sequentially — multiple Bash calls in the same turn queue one after another. They do NOT run in parallel. Use the patterns below for true parallelism.
Step-level — same step, multiple clips
For foreach steps on independent clips, use a single Bash call with background jobs:
out0=$(curl -s -X POST http://localhost:3000/api/steps/transcribe \
-H "Content-Type: application/json" \
-d '{"input": "/path/clip0.MOV", "model": "base.en"}') &
out1=$(curl -s -X POST http://localhost:3000/api/steps/transcribe \
-H "Content-Type: application/json" \
-d '{"input": "/path/clip1.MOV", "model": "base.en"}') &
wait
echo "$out0"; echo "$out1"
Use for any independent foreach step: waveform_trim, transcribe, rm_fillers, probe, snapshot.
Do NOT use background jobs for encoding steps. See Encoding steps below.
Encoding steps — materialize_cut, remove_bg
Encoding steps are memory-intensive per instance (full libx264 encode + frame buffers). Fanning them out unbounded across N clips will exhaust memory on 4K footage. Use batch mode with the built-in concurrency cap instead of background jobs:
montaj materialize-cut --inputs clip0_spec.json clip1_spec.json clip2_spec.json
montaj materialize-cut --inputs clip0.MOV clip1.MOV --workers 3
montaj remove-bg --inputs clip0_cut.mp4 clip1_cut.mp4 clip2_cut.mp4
remove_bg is long-running (minutes per clip on MPS/GPU). Always run it in the background when using the Agent tool or HTTP API so the agent remains responsive.
waveform_trim native batch
Preferred over background jobs — pass all clips in a single call:
curl -s -X POST http://localhost:3000/api/steps/waveform_trim \
-H "Content-Type: application/json" \
-d '{"inputs": ["/path/clip0.mp4", "/path/clip1.mp4", "/path/clip2.mp4"]}'
montaj waveform-trim clip0.mp4 clip1.mp4 clip2.mp4
Clip-level — multiple steps per clip (swarm)
When each clip needs 3+ sequential steps before concat, background jobs get unwieldy. Use one subagent per clip:
- Identify fan-out point: all per-clip steps (before concat)
- Identify fan-in point:
concat and everything after
- Spawn one subagent per clip — each receives: clip path, steps to run, project id, editing prompt
- Cap at 4 concurrent clip agents to avoid resource contention
- Wait for all subagents to complete, collect output paths
- Fan in: run
concat with all paths, then continue
Use when a clip needs 3+ sequential steps — subagent coordination overhead is worth it beyond that threshold.
Dependency waves
Workflow steps declare needs: [step_ids]. Identify waves of ready steps (all needs met) and execute each wave with the appropriate parallel pattern before moving to the next.
Example — default workflow:
| Wave | Steps | Pattern |
|---|
| 1 | probe, snapshot, waveform_trim (per clip) | Bash & or waveform_trim batch |
| 2 | transcribe (per clip) | Bash & |
| 3 | rm_fillers (per clip) | Bash & |
| 4 | select-takes | Sequential |
| 5 | caption, overlays | Sequential |
| 6 | concat | Sequential (encode boundary) |