Skip to content

Command-Level Options

Command-Level Options

All command types (claude:, shell:, foreach:) support additional fields for advanced control and orchestration. These options enable timeout management, output capture, error handling, conditional execution, and more.

Core Options

timeout

Sets a maximum execution time for the command (in seconds). If the command exceeds this duration, it will be terminated.

Type: Option<u64> (optional, no default timeout)

Source: src/config/command.rs:383

commands:
  # 5 minute timeout for test suite
  - shell: "npm test"
    timeout: 300

  # 10 minute timeout for Claude implementation
  - claude: "/implement feature"
    timeout: 600

  # No timeout (runs until completion)
  - shell: "cargo build --release"

Real-world examples: - workflows/debtmap-reduce.yml:6 - 15 minute timeout for coverage generation - workflows/complex-build-pipeline.yml:23 - 10 minute timeout for benchmarks - workflows/documentation-drift.yml:48 - 5 minute timeout for doc tests

id

Assigns an identifier to the command for referencing its outputs in subsequent commands via workflow variables.

Type: Option<String> (optional)

Source: src/config/command.rs:351-352

commands:
  - shell: "git rev-parse --short HEAD"
    id: "get_commit"
    capture_output: "commit_hash"

  # Use the captured output
  - shell: "echo 'Building commit ${commit_hash}'"

commit_required

Specifies whether the command is expected to create git commits. Prodigy tracks commits for workflow provenance and rollback.

Type: bool (default: false)

Source: src/config/command.rs:354-356

commands:
  # Claude commands that modify code should commit
  - claude: "/prodigy-coverage"
    commit_required: true

  # Test commands typically don't commit
  - shell: "cargo test"
    commit_required: false

  # Linting fixes may commit changes
  - claude: "/prodigy-lint"
    commit_required: true

Real-world examples: - workflows/coverage.yml:5,11 - Coverage and implementation commands - workflows/documentation-drift.yml:19,23,27 - Documentation update commands - workflows/implement-with-tests.yml:27,31 - Test vs implementation distinction

MapReduce-Specific Behavior (Spec 163)

In MapReduce workflows, commit_required: true is strictly enforced with validation to prevent silent data loss. When a command in agent_template is marked with commit_required: true, Prodigy validates that at least one commit was created in the agent's isolated worktree.

Validation Behavior: - Before each commit_required command executes, the current git HEAD is captured - After the command completes, the git HEAD is checked again - If no new commits are detected (HEAD unchanged), the agent fails with CommitValidationFailed error - Failed agents are added to the Dead Letter Queue (DLQ) with manual_review_required: true

MapReduce Example:

name: process-items
mode: mapreduce

map:
  input: "items.json"
  json_path: "$.items[*]"

  agent_template:
    # This command MUST create a commit
    - shell: |
        echo "${item.data}" > "${item.file}"
        git add "${item.file}"
        git commit -m "Process item ${item.id}"
      commit_required: true

Error Message Format:

Agent execution failed: Commit required but no commit was created

Worktree: /Users/user/.prodigy/worktrees/repo/agent-1
Expected behavior: Command should create at least one git commit
Command: shell: process-item.sh

Merge Behavior: - Agents with commits: Merged to parent worktree via queue - Agents without commits: Worktree cleaned up, merge skipped (logged at INFO level) - Agents with validation errors: Worktree cleaned up, added to DLQ

Event Tracking: - AgentCompleted events include commits: Vec<String> field with commit SHAs - AgentFailed events include failure_reason: CommitValidationFailed for validation errors - Both events include json_log_location for debugging

Troubleshooting: See MapReduce Troubleshooting Guide for common issues and solutions.

Output Capture Options

capture_output

Captures command output and stores it in a workflow variable. Supports both boolean mode (captures to default variable) and variable name mode (captures to named variable).

Type: Option<CaptureOutputConfig> where CaptureOutputConfig is:

enum CaptureOutputConfig {
    Boolean(bool),      // Simple capture (true/false)
    Variable(String),   // Capture to named variable
}

Source: src/config/command.rs:367-368, 403-411

commands:
  # Capture to default variable name (shell.output)
  - shell: "echo 'Starting analysis...'"
    capture_output: true

  # Capture to custom variable name
  - shell: "ls -la | wc -l"
    capture_output: "file_count"

  # Use the captured variable
  - shell: "echo 'Found ${file_count} files'"

  # Disable capture explicitly
  - shell: "cargo build"
    capture_output: false

Real-world examples: - examples/capture-output-custom-vars.yml:10-48 - Custom variable names - workflows/implement-with-tests.yml:26,55 - Test output capture - workflows/complex-build-pipeline.yml:17,24 - Build diagnostics

capture_format

Specifies how to parse captured output. Determines the data type and structure of the captured variable.

Type: Option<String> with values: string (default), json, lines, number, boolean

Source: src/config/command.rs:391-392, src/cook/workflow/variables.rs:250-265

Supported formats: - string - Raw string output (default) - json - Parse as JSON object/array - lines - Split into array of lines - number - Parse as numeric value - boolean - Parse as boolean (true/false)

commands:
  # Capture as JSON object
  - shell: "cat package.json"
    capture_output: "package_info"
    capture_format: "json"

  # Access JSON fields
  - shell: "echo 'Package: ${package_info.name} v${package_info.version}'"

  # Capture as boolean
  - shell: "cargo test --quiet && echo true || echo false"
    capture_output: "tests_passed"
    capture_format: "boolean"

  # Capture as number
  - shell: "find src -name '*.rs' | wc -l"
    capture_output: "file_count"
    capture_format: "number"

  # Capture as array of lines
  - shell: "git diff --name-only"
    capture_output: "changed_files"
    capture_format: "lines"

Real-world examples: - examples/capture-json-processing.yml:9-54 - JSON metadata extraction - examples/capture-conditional-flow.yml:9-37 - Boolean and number formats - examples/capture-parallel-analysis.yml:9-101 - Multi-format capture pipeline

capture_streams

Controls which output streams to capture from command execution. By default, only stdout is captured.

Type: Option<String> or structured configuration

Source: src/config/command.rs:394-396, src/cook/workflow/variables.rs:267-292

Captured fields: - stdout - Standard output (default: true) - stderr - Standard error (default: false) - exit_code - Process exit code (default: true) - success - Whether command succeeded (default: true) - duration - Execution duration (default: true)

commands:
  # Capture all streams and metadata
  - shell: "cargo build --release"
    capture_output: "build_result"
    capture_streams:
      stdout: true
      stderr: true
      exit_code: true
      success: true
      duration: true

  # Access captured fields
  - shell: |
      echo "Build Success: ${build_result.success}"
      echo "Exit Code: ${build_result.exit_code}"
      echo "Duration: ${build_result.duration}s"

Real-world examples: - examples/capture-conditional-flow.yml:44-51 - Multi-stream capture with conditionals

output_file

Redirects command output to a file. This option is defined in the type definition but not yet widely used in the codebase.

Type: Option<String> (file path)

Source: src/config/command.rs:398-400

commands:
  - shell: "cargo test --verbose"
    output_file: "test-results.txt"

  - shell: "cargo doc --no-deps"
    output_file: "docs/api-output.log"

Note: This feature is defined but no production examples currently exist. Consider contributing examples if you use this option.

Error Handling

on_failure

Specifies commands to execute when the main command fails. Supports automatic retry with configurable attempts and workflow failure control.

Type: Option<TestDebugConfig> with fields: - claude: String - Claude command to run on failure - max_attempts: u32 - Maximum retry attempts (default: 3) - fail_workflow: bool - Whether to fail workflow after max attempts (default: false) - commit_required: bool - Whether debug command should commit (default: true)

Source: src/config/command.rs:370-372, 166-183

commands:
  # Retry tests with automated fixing
  - shell: "cargo test"
    on_failure:
      claude: "/prodigy-debug-test-failure --output ${shell.output}"
      max_attempts: 3
      fail_workflow: false

  # Critical check that must pass
  - shell: "just fmt-check && just lint"
    on_failure:
      claude: "/prodigy-lint ${shell.output}"
      max_attempts: 5
      fail_workflow: true

  # Doc test failures with commit requirement
  - shell: "cargo test --doc"
    on_failure:
      claude: "/prodigy-fix-doc-tests --output ${shell.output}"
      max_attempts: 2
      fail_workflow: false
      commit_required: true

Real-world examples: - workflows/coverage-with-test-debug.yml:13-23 - Test debugging with retries - workflows/debtmap-reduce.yml:58-70 - Critical quality gates - workflows/documentation-drift.yml:47-53 - Doc test recovery

on_success

Executes another command when the main command succeeds. Enables chaining of dependent operations.

Type: Option<Box<WorkflowStepCommand>> (nested command)

Source: src/config/command.rs:374-376

commands:
  # Chain successful operations
  - shell: "cargo check"
    on_success:
      shell: "cargo build --release"
      on_success:
        shell: "cargo test --release"

  # Nested success/failure handlers
  - shell: "cargo test"
    capture_output: "test_output"
    on_failure:
      claude: "/prodigy-debug-test-failures '${test_output}'"
      commit_required: true
      on_success:
        # After fixing, verify tests pass
        shell: "cargo test"
        on_failure:
          claude: "/prodigy-fix-test-failures '${shell.output}' --deep-analysis"

  # Success notification
  - shell: "cargo test --release"
    capture_output: "final_results"
    on_success:
      shell: "echo '✅ All tests passing!'"

Real-world examples: - workflows/implement-with-tests.yml:28-40,61-63 - Nested test-fix-verify loops - workflows/complex-build-pipeline.yml:7-13 - Build pipeline chaining

Conditional Execution

when

Evaluates a boolean expression to determine whether to execute the command. Supports variable interpolation and boolean logic.

Type: Option<String> (boolean expression)

Source: src/config/command.rs:387-388

commands:
  # Capture test status
  - shell: "cargo test --quiet && echo true || echo false"
    capture_output: "tests_passed"
    capture_format: "boolean"

  # Conditional execution based on test results
  - shell: "echo 'Running coverage analysis...'"
    when: "${tests_passed}"

  # Multiple conditions
  - shell: "cargo build --release"
    when: "${tests_passed} && ${lint_passed}"
    capture_output: "build_output"

  # Conditional deployment
  - shell: |
      if [ "${tests_passed}" = "true" ] && [ "${build_output.success}" = "true" ]; then
        echo "✅ Deployment ready!"
      fi
    when: "${tests_passed}"

Real-world examples: - examples/capture-conditional-flow.yml:20-51 - Multi-stage conditional pipeline

Advanced Options

validate

Configures implementation completeness validation with automatic gap detection and filling.

Type: Option<ValidationConfig> (validation configuration)

Source: src/config/command.rs:378-380

commands:
  - claude: "/implement-feature"
    validate:
      force_refresh: false
      max_cache_age: 300

Note: See validation documentation for comprehensive coverage of this feature.

analysis

Specifies per-step analysis requirements for code quality and coverage tracking.

Type: Option<AnalysisConfig> with fields: - force_refresh: bool - Force fresh analysis even if cached (default: false) - max_cache_age: u64 - Maximum cache age in seconds (default: 300)

Source: src/config/command.rs:116-126

commands:
  - claude: "/implement-feature"
    analysis:
      force_refresh: true
      max_cache_age: 600

env

Sets command-specific environment variables that override workflow-level and system environment variables.

Type: HashMap<String, String> (key-value pairs)

Source: src/config/command.rs:143-145

commands:
  - shell: "cargo build"
    env:
      RUST_BACKTRACE: "1"
      CARGO_INCREMENTAL: "0"

  - claude: "/analyze-code"
    env:
      DEBUG_MODE: "true"
      LOG_LEVEL: "trace"

Option Combinations

Test-Fix-Verify Pattern

Combines output capture, error handling, and conditionals for robust test workflows:

commands:
  # Initial test run
  - shell: "cargo test"
    capture_output: "test_output"
    commit_required: false
    on_failure:
      # Automated fix on failure
      claude: "/prodigy-debug-test-failures '${test_output}'"
      commit_required: true
      max_attempts: 3
      on_success:
        # Verify fix worked
        shell: "cargo test"
        commit_required: false

Conditional Pipeline Pattern

Uses capture formats and conditionals for decision-making workflows:

commands:
  # Capture test status as boolean
  - shell: "cargo test --quiet && echo true || echo false"
    capture_output: "tests_passed"
    capture_format: "boolean"

  # Capture coverage as number
  - shell: "cargo tarpaulin --output-dir coverage | grep -oP '\\d+\\.\\d+(?=%)' | head -1"
    capture_output: "coverage_percent"
    capture_format: "number"
    when: "${tests_passed}"

  # Deploy only if quality gates pass
  - shell: "echo 'Deploying to production...'"
    when: "${tests_passed} && ${coverage_percent} >= 80"

Parallel Capture Pattern

Captures multiple metrics in parallel for aggregation:

commands:
  # Capture metadata
  - shell: "find src -name '*.rs' | wc -l"
    capture_output: "total_files"
    capture_format: "number"

  # Build summary JSON
  - shell: |
      echo '{
        "repository": "'$(basename $(pwd))'",
        "total_files": ${total_files},
        "timestamp": "'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"
      }'
    capture_output: "metadata"
    capture_format: "json"

Troubleshooting

Command Times Out

Problem: Command exceeds timeout and is terminated

Solutions: - Increase timeout value - Optimize command performance - Split into multiple smaller commands - Remove timeout for commands with unpredictable duration

Capture Format Mismatch

Problem: Error parsing captured output with specified format

Solutions: - Verify command output matches expected format (use echo to inspect) - Add format validation to command output - Use capture_format: "string" as fallback - Check for extra whitespace or unexpected characters

on_failure Not Triggering

Problem: Failure handler doesn't execute when command fails

Solutions: - Verify command actually returns non-zero exit code - Check max_attempts hasn't been exceeded - Ensure on_failure syntax is correct (nested under command) - Review workflow logs for execution details

Variable Not Available

Problem: ${variable} not found or empty in subsequent command

Solutions: - Verify capture_output is set with correct variable name - Check command actually produces output (not empty) - Ensure capture_format matches output type - Use default values: ${var|default:fallback}