Parallel Execution¶
Run multiple AI tasks concurrently to save time and increase productivity. This guide covers the parallel execution architecture, task file format, error handling strategies, and real-world patterns.
Overview¶
The parallel command executes multiple tasks simultaneously across one or more backends. Unlike sequential execution, parallel tasks run concurrently, with the total execution time equal to the slowest task rather than the sum of all tasks.
Key Benefits:
- Time Savings: Run independent tasks simultaneously
- Multi-Perspective Analysis: Get insights from different AI models at once
- Batch Processing: Process multiple files or components efficiently
- Resource Optimization: Maximize throughput within rate limits
Parallel Execution Architecture¶
How It Works¶
flowchart TB
subgraph SUBMIT["Task Submission"]
T1["Task 1 (Claude)"]
T2["Task 2 (Codex)"]
T3["Task 3 (Gemini)"]
T4["Task 4 (Claude)"]
end
POOL["Worker Pool (max_workers=3)"]
subgraph WORKERS["Workers"]
W1["Worker 1"]
W2["Worker 2"]
W3["Worker 3"]
end
RESULT["Result Collector"]
T1 --> POOL
T2 --> POOL
T3 --> POOL
T4 --> POOL
POOL --> W1
POOL --> W2
POOL --> W3
W1 --> RESULT
W2 --> RESULT
W3 --> RESULT
style SUBMIT fill:#e3f2fd,stroke:#1976d2
style POOL fill:#fff3e0,stroke:#f57c00
style WORKERS fill:#e8f5e9,stroke:#388e3c
style RESULT fill:#ffecb3,stroke:#ffa000
Execution Flow:
- Task Parsing: JSON task file is parsed and validated
- Worker Pool: Tasks are distributed to workers (up to
max_workers) - Concurrent Execution: Each worker runs its assigned task
- Result Collection: Results are gathered as tasks complete
- Aggregation: Final output is formatted and displayed
Concurrency Model¶
clinvk uses a worker pool pattern for parallel execution:
- Worker Pool Size: Controlled by
--max-parallelormax_workersconfig - Task Queue: Tasks wait in a queue until a worker is available
- Independent Execution: Each task runs in isolation with its own backend process
- Result Ordering: Results maintain task index order in output
JSON Task File Format¶
Basic Structure¶
{
"tasks": [
{
"backend": "claude",
"prompt": "review the auth module"
},
{
"backend": "codex",
"prompt": "add logging to the API"
},
{
"backend": "gemini",
"prompt": "generate tests for utils"
}
]
}
Complete Task Specification¶
{
"tasks": [
{
"backend": "claude",
"prompt": "review the code",
"model": "claude-opus-4-5-20251101",
"workdir": "/path/to/project",
"approval_mode": "auto",
"sandbox_mode": "workspace",
"output_format": "json",
"max_tokens": 4096,
"max_turns": 10,
"system_prompt": "You are a code reviewer."
}
]
}
Task Fields Reference¶
| Field | Type | Required | Description |
|---|---|---|---|
backend |
string | Yes | Backend to use (claude, codex, gemini) |
prompt |
string | Yes | The prompt to execute |
model |
string | No | Model override |
workdir |
string | No | Working directory for the task |
approval_mode |
string | No | default, auto, none, always |
sandbox_mode |
string | No | default, read-only, workspace, full |
output_format |
string | No | Accepted but ignored in CLI parallel (reserved) |
max_tokens |
int | No | Maximum response tokens |
max_turns |
int | No | Maximum agentic turns |
system_prompt |
string | No | Custom system prompt |
Top-Level Options¶
Specify options that apply to all tasks:
| Field | Type | Default | Description |
|---|---|---|---|
max_parallel |
int | 3 | Maximum concurrent tasks |
fail_fast |
bool | false | Stop on first failure |
Priority: CLI flags override file-level settings, which override config defaults.
Running Tasks¶
From File¶
From Stdin¶
Pipe task definitions for dynamic generation:
Execution Options¶
Limit Parallel Workers¶
Control concurrency to manage resource usage:
When to Limit Workers:
- Rate Limits: Stay within backend API limits
- Resource Constraints: Limited CPU/memory
- Network Bandwidth: Avoid overwhelming connections
- Cost Control: Limit concurrent API calls
Fail-Fast Mode¶
Stop all tasks on the first failure:
Use Cases for Fail-Fast:
- Tasks have dependencies (later tasks need earlier ones to succeed)
- Validation tasks where any failure invalidates the batch
- CI/CD pipelines where partial success is not acceptable
Trade-offs:
- Pros: Faster failure detection, resource savings
- Cons: May miss multiple issues, less complete feedback
Continue-on-Error (Default)¶
Run all tasks regardless of individual failures:
clinvk parallel --file tasks.json
# or explicitly
clinvk parallel --file tasks.json --max-parallel 3
Use Cases for Continue-on-Error:
- Independent tasks (no dependencies)
- Getting complete feedback on all items
- Batch processing where partial success is acceptable
Output Formats¶
Text Output (Default)¶
Shows progress and results as tasks complete:
Running 3 tasks (max 3 parallel)...
[1] The auth module looks good...
[2] Added logging statements...
[3] Generated 5 test cases...
Results
============================================================
BACKEND STATUS DURATION TASK
------------------------------------------------------------
1 claude OK 2.50s review the auth module
2 codex OK 3.20s add logging to the API
3 gemini OK 2.80s generate tests for utils
------------------------------------------------------------
Total: 3 tasks, 3 completed, 0 failed (3.20s)
JSON Output¶
Structured output for programmatic processing:
{
"total_tasks": 3,
"completed": 3,
"failed": 0,
"total_duration_seconds": 3.2,
"results": [
{
"index": 0,
"backend": "claude",
"output": "The auth module looks good...",
"duration_seconds": 2.5,
"exit_code": 0
},
{
"index": 1,
"backend": "codex",
"output": "Added logging statements...",
"duration_seconds": 3.2,
"exit_code": 0
},
{
"index": 2,
"backend": "gemini",
"output": "Generated 5 test cases...",
"duration_seconds": 2.8,
"exit_code": 0
}
]
}
Quiet Mode¶
Suppress task output, show only summary:
Output:
Best for: CI/CD pipelines, cron jobs, when only status matters
Result Aggregation Patterns¶
Pattern 1: Collect All Results¶
Process all outputs together:
Pattern 2: Filter by Status¶
Process only successful results:
Pattern 3: Error Handling¶
Check for failures and react:
#!/bin/bash
result=$(clinvk parallel --file tasks.json --json)
failed=$(echo "$result" | jq '.failed')
if [ "$failed" -gt 0 ]; then
echo "Warning: $failed tasks failed"
echo "$result" | jq '.results[] | select(.exit_code != 0)'
exit 1
fi
Real-World Examples¶
Security Audit Pipeline¶
Run comprehensive security checks across multiple backends:
{
"tasks": [
{
"backend": "claude",
"prompt": "Review this codebase for security vulnerabilities, focusing on injection attacks and authentication issues",
"approval_mode": "auto",
"sandbox_mode": "read-only"
},
{
"backend": "gemini",
"prompt": "Analyze this code for common security anti-patterns and OWASP Top 10 issues",
"approval_mode": "auto",
"sandbox_mode": "read-only"
},
{
"backend": "codex",
"prompt": "Check for hardcoded secrets, API keys, and credentials in the codebase",
"approval_mode": "auto",
"sandbox_mode": "read-only"
}
],
"max_parallel": 3
}
Multi-Perspective Code Review¶
Get diverse insights on code changes:
{
"tasks": [
{
"backend": "claude",
"prompt": "Review this PR for architectural issues and design patterns"
},
{
"backend": "gemini",
"prompt": "Review this PR for security vulnerabilities"
},
{
"backend": "codex",
"prompt": "Review this PR for performance issues"
}
]
}
Batch Test Generation¶
Generate tests for multiple modules:
{
"tasks": [
{"backend": "codex", "prompt": "generate unit tests for auth.go"},
{"backend": "codex", "prompt": "generate unit tests for user.go"},
{"backend": "codex", "prompt": "generate unit tests for api.go"}
],
"max_parallel": 3
}
Multi-Project Tasks¶
Update dependencies across multiple projects:
{
"tasks": [
{
"backend": "claude",
"prompt": "update dependencies and check for breaking changes",
"workdir": "/projects/frontend"
},
{
"backend": "claude",
"prompt": "update dependencies and check for breaking changes",
"workdir": "/projects/backend"
},
{
"backend": "claude",
"prompt": "update dependencies and check for breaking changes",
"workdir": "/projects/worker"
}
]
}
Combining with Chain Execution¶
Use parallel within chain steps for complex workflows:
{
"steps": [
{
"name": "analyze",
"backend": "claude",
"prompt": "Analyze the codebase structure"
},
{
"name": "generate-tests",
"backend": "claude",
"prompt": "Create a tasks.json file with test generation tasks for all modules based on: {{previous}}"
}
]
}
Then run the generated tasks:
clinvk chain --file analyze.json --json | \
jq -r '.results[-1].output' > generated-tasks.json
clinvk parallel --file generated-tasks.json
Resource Limits and Tuning¶
Worker Pool Sizing¶
| Scenario | Recommended max_workers |
Reason |
|---|---|---|
| Local development | 2-3 | Balance speed and resource use |
| CI/CD pipeline | 3-5 | Faster feedback, controlled resources |
| High-volume batch | 5-10 | Maximize throughput |
| Rate-limited APIs | 1-2 | Stay within limits |
Memory Considerations¶
Each parallel task spawns a separate backend process:
Memory Usage ≈ Base + (Tasks × Backend Memory)
Example:
- Base clinvk: 50MB
- Claude process: 200MB
- 3 parallel tasks: 50 + (3 × 200) = 650MB
Rate Limiting¶
Backends may have rate limits. Strategies:
- Reduce Workers: Lower
max_parallelto stay within limits - Sequential Mode: Use
--max-parallel 1for strict limits - Backoff: Implement retry logic in scripts
- Mixed Backends: Distribute load across different backends
Configuration¶
Default parallel execution settings in ~/.clinvk/config.yaml:
parallel:
# Maximum concurrent tasks
max_workers: 3
# Stop on first failure
fail_fast: false
# Combine output from all tasks
aggregate_output: true
Error Scenarios and Solutions¶
Scenario 1: Partial Failures¶
Problem: Some tasks fail while others succeed
Solution:
# Continue despite failures (default)
clinvk parallel --file tasks.json
# Then process results
clinvk parallel --file tasks.json --json | \
jq '.results[] | select(.exit_code != 0) | {index, backend, error}'
Scenario 2: Rate Limiting¶
Problem: Hitting API rate limits
Solution:
# Reduce concurrency
clinvk parallel --file tasks.json --max-parallel 1
# Or use sequential mode
clinvk parallel --file tasks.json --max-parallel 1
Scenario 3: Resource Exhaustion¶
Problem: System runs out of memory/CPU
Solution:
# Limit workers based on available resources
clinvk parallel --file tasks.json --max-parallel 2
# Process in batches
head -n 10 tasks.json > batch1.json
clinvk parallel --file batch1.json
Scenario 4: Dependency Failures¶
Problem: Task B depends on Task A succeeding
Solution:
# Use fail-fast mode
clinvk parallel --file tasks.json --fail-fast
# Or use chain execution for dependencies
clinvk chain --file dependent-tasks.json
Best Practices¶
Start with 2-3 Workers
Begin with conservative concurrency and increase based on your system's capacity and backend rate limits.
Use JSON for Automation
When integrating into scripts or CI/CD, always use --json output for reliable parsing.
Group Similar Tasks
Organize tasks by backend to optimize context switching and resource usage.
Handle Failures Gracefully
Design your workflows to handle partial failures, especially for long-running batch jobs.
Monitor Resource Usage
Watch memory and CPU usage when running many parallel tasks, especially with large models.
Comparison with Other Commands¶
| Feature | Parallel | Chain | Compare |
|---|---|---|---|
| Execution | Concurrent | Sequential | Concurrent |
| Data Flow | Independent | Pass-through | Independent |
| Use Case | Batch processing | Multi-stage workflows | Multi-perspective analysis |
| Failure Handling | Configurable | Stop on failure | Continue with remaining |
Next Steps¶
- Chain Execution - Sequential pipelines with data flow
- Backend Comparison - Compare responses side-by-side
- Session Management - Manage conversation context