Skip to main content

Fix Linter Errors Dynamically

This example demonstrates a more advanced Bosun workflow that dynamically identifies linter errors in your codebase and then spawns individual AI agents to fix each error. This showcases the power of combining run steps for command execution with for_each loops and agent steps for targeted, automated code remediation.

Workflow Definition (bosun.yaml)

name: fix-linter-errors-dynamically
description: Identifies linter errors and uses agents to fix them, then creates a PR.

inputs:
maxErrors:
type: Number
required: false
description: Limit how many erroring files to process.

steps:
- id: lint_errors
name: Run linter and get errors
run: |
# Simulate a linter command that outputs file paths with errors.
# In a real scenario, this would be your actual linter command (e.g., `eslint --format compact src/`).
# For this example, we'll just list some files that *would* have errors.
echo "src/components/BadComponent.tsx"
echo "src/utils/BrokenHelper.ts"
echo "src/pages/UnformattedPage.tsx"
# The output of this step will be a list of file paths, one per line.

- name: Fix each linter error with an agent
for_each:
from: '{{ outputs.lint_errors | split(pat="\n") | filter(value) | slice(end=inputs.maxErrors) | json_encode() }}'
agent:
extends: Coding
instructions: "Apply automatic linting fixes to the file {{ for_each.value }}. Focus on common formatting issues and simple syntax corrections."
role: "You are a meticulous code formatter and linter expert."
constraints:
- "Use the project's standard linting rules (assume ESLint/Prettier are configured)."
- "Only apply fixes that do not change code logic."
- "Ensure the file remains syntactically correct and passes type checks."
- "Focus solely on the specified file: {{ for_each.value }}"
- "Do not make any unrelated changes."

- name: Create a pull request for fixes
agent:
extends: Default
role: "You create pull requests for automated code fixes."
instructions: "Create a draft pull request for all the linter fixes applied by the previous steps."
toolboxes: [repository_read, dangerous]
tools:
- name: create_pull_request
extends: create_or_update_pull_request
with:
draft: true

How it Works

  1. Run Linter: The first run step simulates executing a linter command. In a real-world scenario, you would replace echo "..." with your actual linter command (e.g., eslint --format compact src/). The output of this command is expected to be a list of file paths, one per line, that contain linter errors. Giving the step an ID (lint_errors) makes it easy to reference later.
  2. Iterate and Fix: The for_each step takes the output from the linter (outputs.lint_errors), splits it into individual file paths, filters out any empty strings (from potential trailing newlines), and then iterates over each file. The optional numeric input inputs.maxErrors limits the workload.
    • For each file path, a new Coding agent is spawned.
    • The agent's instructions dynamically include {{ for_each.value }}, telling it exactly which file to focus on.
    • The agent's role and constraints guide it to apply automatic linting fixes without altering code logic.
  3. Create Pull Request: Finally, after all individual agents have attempted to fix their assigned files, a Default agent creates a draft pull request. This PR will contain all the accumulated changes from the linter-fixing agents, ready for review.