Related Skills: Automate your Git workflows with specialized skills from Skilled. Explore Git automation workflows, branch management skills, and code review automation skills to streamline your development process.

Overview

When you need to apply changes across hundreds of files, sequential execution becomes a bottleneck. Autohand solves this by creating isolated Git worktrees for each task, allowing multiple agents to work simultaneously without stepping on each other.

The problem

Consider migrating a codebase from CommonJS to ESM. With 500 files to update, sequential processing would take hours. Each file needs analysis, transformation, and testing. Traditional approaches fail because:

  • File locks prevent concurrent modifications
  • Partial failures leave the codebase in an inconsistent state
  • No isolation means one bad change affects everything
  • Rollback requires reverting the entire batch

The solution

Git worktrees provide the foundation for true parallelism. Each worktree is a separate working directory with its own branch, sharing the same Git history. Autohand orchestrates agents across these worktrees:

┌─────────────────────────────────────────────────────────────────┐
│                      Autohand Orchestrator                       │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐       ┌──────────┐   │
│  │ Agent 1  │  │ Agent 2  │  │ Agent 3  │  ...  │ Agent N  │   │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘       └────┬─────┘   │
└───────┼─────────────┼─────────────┼─────────────────┼──────────┘
        │             │             │                 │
        ▼             ▼             ▼                 ▼
   ┌─────────┐   ┌─────────┐   ┌─────────┐       ┌─────────┐
   │Worktree │   │Worktree │   │Worktree │       │Worktree │
   │  001    │   │  002    │   │  003    │  ...  │   N     │
   │ branch: │   │ branch: │   │ branch: │       │ branch: │
   │ task-1  │   │ task-2  │   │ task-3  │       │ task-n  │
   └────┬────┘   └────┬────┘   └────┬────┘       └────┬────┘
        │             │             │                 │
        └─────────────┴──────┬──────┴─────────────────┘
                             ▼
                    ┌────────────────┐
                    │  Main Branch   │
                    │   (merge)      │
                    └────────────────┘

Key capabilities

Capability Description
Parallel execution Run 100+ agents concurrently, each in isolated worktrees
Task dependencies Define execution order when tasks depend on each other
Automatic branching Each task gets its own feature branch automatically
Per-task testing Run tests in each worktree before merge
Conflict detection Identify overlapping changes before merge attempt
AI-assisted resolution Automatically resolve conflicts using semantic understanding
Selective rollback Discard individual tasks without affecting others
Resume from failure Continue execution after fixing failed tasks

Architecture

Understanding the orchestration model helps you configure and troubleshoot parallel execution effectively.

Orchestrator components

The parallel execution system consists of four main components:

  • Task Queue: Prioritized queue of pending tasks with dependency resolution
  • Agent Pool: Pool of concurrent agents bounded by max_concurrent
  • Worktree Manager: Creates, tracks, and cleans up Git worktrees
  • Merge Coordinator: Handles conflict detection, resolution, and final merge

Task lifecycle

Each task progresses through defined states:

PENDING ──▶ QUEUED ──▶ RUNNING ──▶ TESTING ──▶ COMPLETED
    │          │          │           │            │
    │          │          ▼           ▼            ▼
    │          │       FAILED     FAILED       MERGED
    │          │          │           │
    │          ▼          ▼           ▼
    └───────── BLOCKED (dependency not met)
               CANCELLED (user cancelled)
               SKIPPED (condition not met)

Resource management

The orchestrator manages system resources to prevent overload:

# .autohand/config.yaml
orchestrator:
  # Maximum concurrent agents
  max_concurrent: 50

  # Resource limits per agent
  agent:
    memory_limit: 2GB
    cpu_limit: 2

  # API rate limiting
  api:
    requests_per_minute: 100
    retry_on_rate_limit: true
    retry_delay: 60s

  # Disk management
  disk:
    min_free_space: 10GB
    cleanup_threshold: 5GB
    worktree_size_limit: 1GB

Disk space planning: Each worktree is a full copy of your working directory (excluding .git). For a 500MB codebase with 100 concurrent tasks, plan for 50GB+ of disk space.

Task definition

Tasks are defined in YAML files with rich configuration options for controlling execution behavior.

Basic structure

# tasks.yaml
version: "1.0"
name: ESM Migration
description: Migrate CommonJS modules to ES Modules

defaults:
  model: claude-sonnet
  timeout: 5m
  retries: 2

tasks:
  - id: migrate-utils
    description: Migrate utility modules
    files:
      - src/utils/**/*.js
    prompt: |
      Convert this CommonJS module to ES Module syntax.
      Replace require() with import statements.
      Replace module.exports with export statements.
      Ensure named exports are used where appropriate.

Task options

Option Type Description
id string Unique identifier for the task
description string Human-readable description for logs and PRs
files array Glob patterns for files to process
prompt string Instructions for the AI agent
depends_on array Task IDs that must complete first
priority number Execution priority (higher runs first)
condition string Shell command that must exit 0 to run task
timeout duration Maximum execution time per task
retries number Retry count on failure
test object Test configuration for validation

Task dependencies

When tasks must execute in a specific order, use depends_on:

tasks:
  - id: update-types
    description: Update TypeScript type definitions
    files: ["src/types/**/*.ts"]
    prompt: Update type definitions for new API schema
    priority: 100  # Run first

  - id: update-api-client
    description: Update API client implementation
    files: ["src/api/**/*.ts"]
    prompt: Update API client to match new types
    depends_on: [update-types]  # Wait for types

  - id: update-components
    description: Update React components
    files: ["src/components/**/*.tsx"]
    prompt: Update components to use new API client
    depends_on: [update-api-client]  # Wait for API client

  - id: update-tests
    description: Update test files
    files: ["src/**/*.test.ts"]
    prompt: Update tests for new implementations
    depends_on: [update-types, update-api-client, update-components]

Conditional execution

Skip tasks based on conditions:

tasks:
  - id: update-legacy-module
    description: Update legacy authentication
    files: ["src/legacy/**/*.js"]
    prompt: Migrate legacy auth to new system
    condition: "test -d src/legacy"  # Only if directory exists

  - id: generate-openapi
    description: Regenerate OpenAPI client
    files: ["src/api/generated/**/*"]
    prompt: Regenerate API client from schema
    condition: "git diff --name-only HEAD~1 | grep -q openapi.yaml"

Per-task testing

Validate changes before marking tasks complete:

tasks:
  - id: refactor-auth
    files: ["src/auth/**/*.ts"]
    prompt: Refactor authentication module
    test:
      # Commands to run in the worktree
      commands:
        - npm run typecheck
        - npm test -- --testPathPattern=auth

      # Test behavior
      required: true          # Fail task if tests fail
      timeout: 5m             # Test timeout
      retry_on_flaky: true    # Retry flaky tests once

      # Coverage requirements
      coverage:
        enabled: true
        min_percent: 80
        fail_on_decrease: true

Parallel execution

Once tasks are defined, execute them with the orchestrator.

Running tasks

# Execute all tasks from file
autohand parallel run --tasks tasks.yaml

# Limit concurrency
autohand parallel run --tasks tasks.yaml --concurrency 20

# Run specific tasks only
autohand parallel run --tasks tasks.yaml --only update-types,update-api

# Exclude specific tasks
autohand parallel run --tasks tasks.yaml --exclude update-tests

# Dry run (preview without executing)
autohand parallel run --tasks tasks.yaml --dry-run

Execution modes

# .autohand/config.yaml
execution:
  # How to handle task failures
  on_failure: continue    # continue, pause, or abort

  # Whether to run tests automatically
  auto_test: true

  # Notification settings
  notify:
    on_complete: true
    on_failure: true
    channels:
      - slack:#dev-automation
      - email:[email protected]

Monitoring progress

# Real-time status dashboard
autohand parallel status --watch

# Output:
# ┌─────────────────────────────────────────────────────────────┐
# │ Parallel Execution: ESM Migration                          │
# ├─────────────────────────────────────────────────────────────┤
# │ Progress: ████████████████░░░░░░░░░░░░░░░░ 47/100 (47%)    │
# │ Running: 20  │  Completed: 45  │  Failed: 2  │  Queued: 53 │
# ├─────────────────────────────────────────────────────────────┤
# │ Active Tasks:                                               │
# │   migrate-utils-023    [████████░░] 80%  src/utils/date.js │
# │   migrate-api-017      [██████░░░░] 60%  src/api/users.ts  │
# │   migrate-components-8 [████░░░░░░] 40%  src/Button.tsx    │
# │   ...                                                       │
# ├─────────────────────────────────────────────────────────────┤
# │ Failed Tasks:                                               │
# │   migrate-legacy-auth  [FAILED] TypeError in transformation│
# │   migrate-db-client    [FAILED] Test assertion failed      │
# ├─────────────────────────────────────────────────────────────┤
# │ Resources: CPU 45%  │  Memory 12GB/32GB  │  Disk 23GB free │
# │ API: 45 req/min (limit: 100)  │  Est. remaining: 12 min    │
# └─────────────────────────────────────────────────────────────┘

# View logs for specific task
autohand parallel logs migrate-utils-023

# Follow logs in real-time
autohand parallel logs migrate-utils-023 --follow

# Export execution report
autohand parallel report --format json --output report.json

Pause and resume

# Pause execution (finish running tasks, don't start new ones)
autohand parallel pause

# Resume execution
autohand parallel resume

# Cancel all running tasks
autohand parallel cancel --all

# Cancel specific task
autohand parallel cancel migrate-legacy-auth

# Retry failed tasks
autohand parallel retry --failed

# Retry specific task
autohand parallel retry migrate-legacy-auth

Conflict resolution

When multiple tasks modify overlapping code, conflicts arise during merge. Autohand provides detection, prevention, and resolution strategies.

Conflict detection

# Analyze potential conflicts before merge
autohand parallel conflicts --analyze

# Output:
# Conflict Analysis Report
# ========================
#
# High Risk (3 conflicts):
# ┌──────────────────────────────────────────────────────────────┐
# │ task-001 vs task-003                                         │
# │ File: src/api/users.ts                                       │
# │ Lines: 45-67 (both tasks modify getUserById function)        │
# │ Recommendation: Manual review required                       │
# ├──────────────────────────────────────────────────────────────┤
# │ task-002 vs task-005                                         │
# │ File: src/utils/helpers.ts                                   │
# │ Lines: 12-15 (overlapping import statements)                 │
# │ Recommendation: Auto-resolvable (merge both imports)         │
# ├──────────────────────────────────────────────────────────────┤
# │ task-007 vs task-012                                         │
# │ File: package.json                                           │
# │ Lines: dependencies section                                  │
# │ Recommendation: Auto-resolvable (merge dependencies)         │
# └──────────────────────────────────────────────────────────────┘
#
# Medium Risk (5 conflicts):
# ...
#
# Total: 8 potential conflicts across 47 completed tasks

Prevention strategies

Reduce conflicts through task design:

# .autohand/config.yaml
conflicts:
  prevention:
    # Automatically split tasks that would conflict
    auto_split: true

    # Lock files during task execution
    file_locking: true

    # Merge order optimization
    optimize_merge_order: true

    # Protected paths (never auto-resolve)
    protected_paths:
      - package.json
      - package-lock.json
      - yarn.lock
      - .env*
      - "*.config.js"

Resolution strategies

# Automatic resolution using AI
autohand parallel resolve --auto

# Interactive resolution (shows diff, prompts for choice)
autohand parallel resolve --interactive

# Apply specific resolution strategy
autohand parallel resolve --strategy ours     # Keep current branch
autohand parallel resolve --strategy theirs   # Keep incoming branch
autohand parallel resolve --strategy union    # Keep both (for additive changes)

AI-assisted resolution

For complex conflicts, the AI analyzes both changes and produces a merged result:

# .autohand/config.yaml
conflicts:
  resolution:
    strategy: ai_assisted    # manual, auto, or ai_assisted

    ai:
      # Context to provide for resolution
      include_file_history: true
      include_task_prompts: true

      # Confidence threshold for auto-apply
      auto_apply_threshold: 0.9

      # Require human review below threshold
      require_review_below: 0.7

    # Rules for specific file patterns
    rules:
      - pattern: "*.test.ts"
        strategy: merge_both

      - pattern: "package.json"
        strategy: merge_dependencies

      - pattern: "*.generated.*"
        strategy: regenerate

      - pattern: "*.lock"
        strategy: regenerate

Merging to main

After tasks complete and conflicts are resolved, merge changes to the target branch.

Merge strategies

Strategy Use case Commit history
sequential When order matters or conflicts are complex One merge commit per task
batch Fast merge of non-conflicting changes Single merge commit for all tasks
squash Clean history with one commit per task Squashed commits, linear history
rebase Linear history without merge commits Rebased commits on target
pr Code review required Creates pull requests

Direct merge

# Merge all completed tasks to main
autohand parallel merge --to main

# Preview merge without applying
autohand parallel merge --to main --dry-run

# Merge with specific strategy
autohand parallel merge --to main --strategy squash

# Merge only specific tasks
autohand parallel merge --to main --tasks task-001,task-002,task-003

# Skip failed tasks and merge successful ones
autohand parallel merge --to main --skip-failed

Pull request mode

# Create individual PRs for each task
autohand parallel merge --strategy pr

# Create draft PRs
autohand parallel merge --strategy pr --draft

# Add labels and reviewers
autohand parallel merge --strategy pr \
  --labels "automated,migration" \
  --reviewers "@team/backend"

# Link to issues
autohand parallel merge --strategy pr --link-issues

# Create single PR for all tasks
autohand parallel merge --strategy pr --combine

Commit message generation

# .autohand/config.yaml
commit:
  message:
    # Template for individual task commits
    task_template: |
      {{type}}: {{description}}

      Task: {{task_id}}
      Files: {{file_count}} modified

      {{#if breaking}}
      BREAKING CHANGE: {{breaking_description}}
      {{/if}}

      Generated by Autohand

    # Template for batch commits
    batch_template: |
      {{type}}: Complete {{task_count}} parallel tasks

      Tasks completed:
      {{#each tasks}}
      - {{id}}: {{description}}
      {{/each}}

      Generated by Autohand

    # Infer commit type from changes
    infer_type: true

    # Types: feat, fix, refactor, docs, test, chore
    default_type: refactor

Push and cleanup

# Merge, push, and cleanup in one command
autohand parallel merge --to main --push --cleanup

# Push to specific remote
autohand parallel merge --to main --push --remote upstream

# Keep worktrees for inspection
autohand parallel merge --to main --push --no-cleanup

# Manual cleanup
autohand parallel cleanup --merged      # Only merged tasks
autohand parallel cleanup --all         # All worktrees
autohand parallel cleanup --older-than 7d  # Stale worktrees

Safety and guardrails

Prevent unintended changes with configurable safety controls.

Protected paths

# .autohand/config.yaml
safety:
  protected_paths:
    # Never modify these files
    readonly:
      - .github/workflows/*
      - .env*
      - secrets/*
      - "*.pem"
      - "*.key"

    # Require explicit approval
    require_approval:
      - package.json
      - tsconfig.json
      - "*.config.js"
      - migrations/*

    # Allow but flag for review
    flag_for_review:
      - src/core/*
      - src/auth/*

Change limits

# .autohand/config.yaml
safety:
  limits:
    # Maximum changes per task
    max_files_per_task: 50
    max_lines_changed: 1000
    max_files_deleted: 5

    # Maximum total changes
    max_total_files: 500
    max_total_lines: 10000

    # Abort if limits exceeded
    on_limit_exceeded: abort  # abort, warn, or ignore

Approval gates

# .autohand/config.yaml
safety:
  approval:
    # Require approval before merge
    require_before_merge: true

    # Approval methods
    methods:
      - slack_reaction    # React with :white_check_mark:
      - github_review     # Approve in PR
      - cli_confirm       # Confirm in terminal

    # Approvers
    approvers:
      - team:platform
      - user:tech-lead

    # Auto-approve low-risk changes
    auto_approve:
      enabled: true
      conditions:
        - "files_changed < 10"
        - "no_protected_paths"
        - "all_tests_pass"
        - "no_conflicts"

Rollback procedures

# Rollback specific task (before merge)
autohand parallel rollback task-001

# Rollback all changes from a session
autohand parallel rollback --session abc123

# Rollback merged changes (creates revert commits)
autohand parallel rollback --merged --session abc123

# Rollback with PR for review
autohand parallel rollback --merged --pr

# View rollback history
autohand parallel rollback --list

Observability

Monitor execution with metrics, logs, and alerts.

Metrics

# View execution metrics
autohand parallel metrics

# Output:
# Session Metrics: abc123
# ──────────────────────────────────────────────────
# Duration:           45 minutes
# Tasks:              100 total, 95 completed, 5 failed
# Success rate:       95%
# Avg task duration:  2.3 minutes
#
# Resource Usage:
#   Peak CPU:         78%
#   Peak Memory:      24GB
#   Disk used:        45GB
#   API calls:        4,521
#   API cost:         $12.34
#
# Merge Stats:
#   Conflicts:        12 detected, 10 auto-resolved
#   Manual reviews:   2
#   Lines changed:    +4,521 / -2,103

Logging

# .autohand/config.yaml
logging:
  level: info    # debug, info, warn, error

  # Log destinations
  destinations:
    - type: file
      path: .autohand/logs/parallel.log
      rotate: daily
      retain: 7d

    - type: stdout
      format: pretty

    - type: json
      path: .autohand/logs/parallel.jsonl

  # What to log
  include:
    - task_start
    - task_complete
    - task_failed
    - conflict_detected
    - merge_complete
    - api_calls

Alerts

# .autohand/config.yaml
alerts:
  channels:
    slack:
      webhook: ${SLACK_WEBHOOK_URL}
      channel: "#dev-automation"

    email:
      to: ["[email protected]"]
      from: "[email protected]"

  triggers:
    - event: task_failed
      severity: warning
      channels: [slack]

    - event: execution_complete
      channels: [slack, email]

    - event: conflict_unresolved
      severity: error
      channels: [slack, email]

    - event: approval_required
      channels: [slack]
      mention: ["@oncall"]

Advanced patterns

Monorepo support

Execute tasks across multiple packages in a monorepo:

# tasks.yaml
version: "1.0"
name: Monorepo Migration

# Define packages
packages:
  - name: web
    path: packages/web
    test: npm test
  - name: api
    path: packages/api
    test: npm test
  - name: shared
    path: packages/shared
    test: npm test

tasks:
  - id: update-shared-types
    package: shared
    files: ["src/**/*.ts"]
    prompt: Update shared type definitions

  - id: update-web-client
    package: web
    files: ["src/**/*.tsx"]
    prompt: Update web client components
    depends_on: [update-shared-types]

  - id: update-api-handlers
    package: api
    files: ["src/**/*.ts"]
    prompt: Update API handlers
    depends_on: [update-shared-types]

Cross-repository execution

# cross-repo-tasks.yaml
version: "1.0"
name: Cross-Repository Migration

repositories:
  - name: frontend
    url: [email protected]:company/frontend.git
    branch: main
  - name: backend
    url: [email protected]:company/backend.git
    branch: main
  - name: shared-libs
    url: [email protected]:company/shared-libs.git
    branch: main

tasks:
  - id: update-api-schema
    repository: backend
    files: ["src/api/schema.ts"]
    prompt: Update API schema with new fields

  - id: regenerate-client
    repository: frontend
    files: ["src/api/generated/*"]
    prompt: Regenerate API client from schema
    depends_on: [update-api-schema]

  - id: update-shared-types
    repository: shared-libs
    files: ["src/types/*"]
    prompt: Update shared type definitions
    depends_on: [update-api-schema]

Distributed execution

For very large task sets, distribute across multiple machines:

# .autohand/config.yaml
distributed:
  enabled: true

  # Coordinator settings
  coordinator:
    host: autohand-coordinator.internal
    port: 8080

  # Worker settings
  workers:
    - host: worker-1.internal
      max_concurrent: 20
    - host: worker-2.internal
      max_concurrent: 20
    - host: worker-3.internal
      max_concurrent: 20

  # Task distribution
  distribution:
    strategy: round_robin    # round_robin, least_loaded, affinity

    # Affinity rules (run related tasks on same worker)
    affinity:
      - pattern: "src/api/*"
        worker: worker-1
      - pattern: "src/web/*"
        worker: worker-2

Incremental execution

Resume from checkpoints after failures:

# Save checkpoint periodically
autohand parallel run --tasks tasks.yaml --checkpoint-interval 5m

# Resume from last checkpoint
autohand parallel resume --from-checkpoint

# Resume from specific checkpoint
autohand parallel resume --checkpoint abc123-checkpoint-5

# List available checkpoints
autohand parallel checkpoints --list

CI/CD integration

GitHub Actions

# .github/workflows/parallel-migration.yml
name: Parallel Migration

on:
  workflow_dispatch:
    inputs:
      tasks_file:
        description: 'Tasks YAML file'
        required: true
        default: 'tasks.yaml'
      concurrency:
        description: 'Concurrent tasks'
        required: false
        default: '20'
      dry_run:
        description: 'Dry run only'
        type: boolean
        default: false

jobs:
  execute:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
          token: ${{ secrets.PAT_TOKEN }}

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Autohand
        run: npm i -g autohand-cli

      - name: Run parallel tasks
        env:
          AUTOHAND_API_KEY: ${{ secrets.AUTOHAND_API_KEY }}
        run: |
          autohand parallel run \
            --tasks ${{ inputs.tasks_file }} \
            --concurrency ${{ inputs.concurrency }} \
            ${{ inputs.dry_run && '--dry-run' || '' }}

      - name: Create pull requests
        if: ${{ !inputs.dry_run }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          autohand parallel merge \
            --strategy pr \
            --draft \
            --labels "automated,migration"

      - name: Upload execution report
        uses: actions/upload-artifact@v4
        with:
          name: execution-report
          path: .autohand/reports/

GitLab CI

# .gitlab-ci.yml
parallel-migration:
  stage: migrate
  image: node:20
  variables:
    AUTOHAND_API_KEY: $AUTOHAND_API_KEY
  before_script:
    - npm i -g autohand-cli
  script:
    - autohand parallel run --tasks tasks.yaml --concurrency 20
    - autohand parallel merge --strategy pr --draft
  artifacts:
    paths:
      - .autohand/reports/
    expire_in: 7 days
  when: manual

Troubleshooting

Common issues

Issue Cause Solution
Worktree creation fails Insufficient disk space Free up disk or reduce concurrency
Tasks timeout frequently Complex files or slow API Increase timeout or reduce file scope
Many conflicts detected Overlapping file patterns Split tasks to reduce overlap
Tests fail in worktree Missing dependencies Add setup step to install deps
Merge fails silently Protected branch rules Use PR strategy or adjust rules
API rate limited Too many concurrent requests Reduce concurrency or add delay

Debug mode

# Enable verbose logging
autohand parallel run --tasks tasks.yaml --debug

# Trace specific task
autohand parallel run --tasks tasks.yaml --trace task-001

# Inspect worktree state
autohand parallel inspect task-001

# Validate task file
autohand parallel validate tasks.yaml

Recovery procedures

# If execution is stuck
autohand parallel status --diagnostics
autohand parallel cancel --force

# If worktrees are corrupted
autohand parallel cleanup --force --all
git worktree prune

# If branches are orphaned
autohand parallel cleanup --branches --orphaned

# Reset to clean state
autohand parallel reset --hard

Command reference

Command Description
autohand parallel run Execute tasks from YAML file
autohand parallel status View execution status and progress
autohand parallel logs Stream logs from task
autohand parallel pause Pause execution
autohand parallel resume Resume paused execution
autohand parallel cancel Cancel running tasks
autohand parallel retry Retry failed tasks
autohand parallel conflicts Analyze potential conflicts
autohand parallel resolve Resolve conflicts
autohand parallel merge Merge completed tasks
autohand parallel cleanup Remove worktrees and branches
autohand parallel rollback Rollback changes
autohand parallel metrics View execution metrics
autohand parallel report Generate execution report
autohand parallel validate Validate task file