Skip to main content

Git-Steer Advanced Patterns: Workflows, Multi-Repo Ops, and Extensions

Ryan Dahlberg
Ryan Dahlberg
February 1, 2026 10 min read
Share:
Git-Steer Advanced Patterns: Workflows, Multi-Repo Ops, and Extensions

Overview

This post covers advanced git-steer patterns for power users:

  1. Custom GitHub Actions Workflows - Building your own worker workflows
  2. Multi-Repo Operations - Orchestrating changes across many repositories
  3. Extending git-steer - Adding new MCP tools
  4. The Pattern Applied - Adapting “Bare Tin Foil” to other domains

Git-Steer Series:

  1. Introduction - Architecture and philosophy
  2. Setup Guide - Step-by-step installation
  3. Advanced Patterns (this post) - Custom workflows and extensions

Custom GitHub Actions Workflows

git-steer’s power comes from dispatching GitHub Actions workflows to do heavy lifting. The built-in security-fix.yml workflow is just the beginning.

Anatomy of a git-steer Worker Workflow

name: Custom Worker

on:
  workflow_dispatch:
    inputs:
      target_repo:
        description: 'Target repository (owner/repo)'
        required: true
        type: string
      # Add your custom inputs here
      custom_param:
        description: 'Your custom parameter'
        required: false
        type: string
      job_id:
        description: 'Job ID for tracking'
        required: false
        type: string

jobs:
  worker:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write

    steps:
      - name: Parse target repo
        id: parse
        run: |
          echo "owner=$(echo '${{ inputs.target_repo }}' | cut -d'/' -f1)" >> $GITHUB_OUTPUT
          echo "repo=$(echo '${{ inputs.target_repo }}' | cut -d'/' -f2)" >> $GITHUB_OUTPUT

      - name: Generate token
        id: app-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.GIT_STEER_APP_ID }}
          private-key: ${{ secrets.GIT_STEER_PRIVATE_KEY }}
          owner: ${{ steps.parse.outputs.owner }}
          repositories: ${{ steps.parse.outputs.repo }}

      - name: Checkout target repo
        uses: actions/checkout@v4
        with:
          repository: ${{ inputs.target_repo }}
          token: ${{ steps.app-token.outputs.token }}
          fetch-depth: 0

      # Your custom logic here
      - name: Do the work
        run: |
          echo "Working on ${{ inputs.target_repo }}"
          echo "Custom param: ${{ inputs.custom_param }}"
          # Your code here

      - name: Create PR (if changes)
        env:
          GH_TOKEN: ${{ steps.app-token.outputs.token }}
        run: |
          if ! git diff --quiet; then
            git checkout -b "automated/custom-change-$(date +%s)"
            git add -A
            git commit -m "chore: automated change via git-steer"
            git push -u origin HEAD
            gh pr create --title "Automated Change" --body "Via git-steer"
          fi

Example: Dependency Update Workflow

A workflow that updates all dependencies to their latest versions:

name: Dependency Updater

on:
  workflow_dispatch:
    inputs:
      target_repo:
        required: true
        type: string
      update_type:
        description: 'Type of update'
        type: choice
        options:
          - patch
          - minor
          - major
        default: minor

jobs:
  update-deps:
    runs-on: ubuntu-latest
    steps:
      # ... token generation steps ...

      - name: Update npm dependencies
        run: |
          find . -name "package.json" -not -path "*/node_modules/*" | while read pkg; do
            DIR=$(dirname "$pkg")
            cd "$DIR"

            case "${{ inputs.update_type }}" in
              patch) npx npm-check-updates -u --target patch ;;
              minor) npx npm-check-updates -u --target minor ;;
              major) npx npm-check-updates -u ;;
            esac

            npm install
            cd - > /dev/null
          done

      - name: Update Python dependencies
        run: |
          find . -name "requirements*.txt" -type f | while read req; do
            pip-compile --upgrade "$req" 2>/dev/null || true
          done

      # ... PR creation steps ...

Example: License Compliance Workflow

A workflow that adds or updates LICENSE files:

name: License Compliance

on:
  workflow_dispatch:
    inputs:
      target_repo:
        required: true
        type: string
      license_type:
        type: choice
        options:
          - MIT
          - Apache-2.0
          - GPL-3.0
        default: MIT

jobs:
  add-license:
    runs-on: ubuntu-latest
    steps:
      # ... setup steps ...

      - name: Add LICENSE file
        run: |
          YEAR=$(date +%Y)
          OWNER="${{ steps.parse.outputs.owner }}"

          case "${{ inputs.license_type }}" in
            MIT)
              cat > LICENSE << EOF
          MIT License

          Copyright (c) $YEAR $OWNER

          Permission is hereby granted, free of charge, to any person obtaining a copy
          of this software and associated documentation files (the "Software"), to deal
          in the Software without restriction...
          EOF
              ;;
            # ... other license types ...
          esac

Multi-Repo Operations

One of git-steer’s strengths is orchestrating operations across many repositories.

Pattern: Scan → Filter → Act

// Pseudocode for multi-repo operations
const repos = await github.listRepos();

// Filter to repos matching criteria
const targets = repos.filter(r =>
  r.name.startsWith('mcp-') &&
  !r.archived
);

// Dispatch workflow to each
for (const repo of targets) {
  await github.dispatchWorkflow('security-fix.yml', {
    target_repo: repo.fullName,
    severity: 'high'
  });
}

Example: Organization-Wide Security Sweep

Using git-steer via Claude:

You: "List all repos that start with 'mcp-'"

Claude: [calls repo_list with filter="mcp-*"]
        Found 5 repos:
        - mcp-unifi
        - mcp-proxmox
        - mcp-wazuh
        - mcp-talos
        - mcp-github

You: "Scan all of them for security vulnerabilities"

Claude: [calls security_scan for each]
        mcp-unifi: 2 high, 5 medium
        mcp-proxmox: 0 alerts
        mcp-wazuh: 1 critical, 3 high
        mcp-talos: 0 alerts
        mcp-github: 4 medium

You: "Fix everything critical and high"

Claude: [calls security_fix_pr for mcp-unifi, mcp-wazuh]
        Dispatched 2 workflows
        - mcp-unifi: job-id-123
        - mcp-wazuh: job-id-124

You: "Check status in 5 minutes"

Claude: [calls workflow_status]
        Both completed successfully
        PRs created:
        - mcp-unifi#12
        - mcp-wazuh#8

Pattern: Templated Multi-Repo Changes

When you need to make the same change across many repos:

You: "Add a CODEOWNERS file to all my repos that assigns @ry-ops as owner"

Claude: [for each repo, calls repo_commit]
        repo_commit(owner: "ry-ops", repo: "cortex",
          files: [{path: "CODEOWNERS", content: "* @ry-ops"}],
          message: "Add CODEOWNERS")

        Committed to 30 repos

Pattern: Coordinated Releases

For projects with multiple repos that release together:

You: "Bump version to 2.0.0 in all @cortex/* repos"

Claude: [for each cortex repo]
        1. Read package.json/pyproject.toml
        2. Update version field
        3. Commit with "chore: bump version to 2.0.0"
        4. Create git tag v2.0.0

Extending git-steer

Adding new MCP tools to git-steer is straightforward.

Adding a New Tool

1. Define the tool in src/mcp/server.ts:

const TOOLS: Tool[] = [
  // ... existing tools ...
  {
    name: 'repo_add_codeowners',
    description: 'Add or update CODEOWNERS file',
    inputSchema: {
      type: 'object',
      properties: {
        owner: { type: 'string' },
        repo: { type: 'string' },
        owners: {
          type: 'array',
          items: { type: 'string' },
          description: 'GitHub usernames to add as owners'
        },
        patterns: {
          type: 'object',
          description: 'Path patterns to owner mappings',
          additionalProperties: {
            type: 'array',
            items: { type: 'string' }
          }
        }
      },
      required: ['owner', 'repo', 'owners']
    }
  }
];

2. Implement the handler:

case 'repo_add_codeowners': {
  const defaultOwners = args.owners.map(o => `@${o}`).join(' ');
  let content = `# Default owners\n* ${defaultOwners}\n`;

  if (args.patterns) {
    content += '\n# Path-specific owners\n';
    for (const [pattern, owners] of Object.entries(args.patterns)) {
      const ownerList = (owners as string[]).map(o => `@${o}`).join(' ');
      content += `${pattern} ${ownerList}\n`;
    }
  }

  await this.github.commitFiles(args.owner, args.repo, {
    branch: 'main',
    message: 'Add CODEOWNERS file',
    files: [{ path: 'CODEOWNERS', content }]
  });

  return { success: true, file: 'CODEOWNERS' };
}

Adding a New Workflow

1. Create the workflow file:

# .github/workflows/your-workflow.yml
name: Your Custom Workflow
on:
  workflow_dispatch:
    inputs:
      target_repo:
        required: true
      # your inputs

2. Add a dispatch method to the client:

async dispatchYourWorkflow(
  targetRepo: string,
  options: YourOptions
): Promise<{ dispatched: boolean; jobId: string }> {
  const jobId = `your-workflow-${Date.now()}`;

  await this.triggerWorkflow('ry-ops', 'git-steer', 'your-workflow.yml', 'main', {
    target_repo: targetRepo,
    ...options,
    job_id: jobId
  });

  return { dispatched: true, jobId };
}

3. Add the MCP tool that dispatches it:

case 'your_tool': {
  const result = await this.github.dispatchYourWorkflow(
    `${args.owner}/${args.repo}`,
    { /* options */ }
  );

  return {
    success: true,
    mode: 'workflow_dispatch',
    jobId: result.jobId
  };
}

The Pattern Applied: Beyond GitHub

The “Bare Tin Foil” architecture isn’t GitHub-specific. Here’s how to apply it elsewhere:

Pattern Components

ComponentPurposeImplementation
Local AgentOrchestrationMCP server
Credential StoreSecurityOS Keychain
State StoreConfiguration/AuditGit repo, S3, etc.
Worker ComputeHeavy liftingActions, Lambda, Cloud Run
API LayerIntegrationREST/GraphQL client

Example: Kubernetes Orchestration

┌─────────────────────────────────────────────────────────────────┐
│  YOUR MAC                                                        │
│                                                                  │
│  Keychain: kubeconfig, service account token                     │
│                                                                  │
│  k8s-steer MCP server                                            │
│    ├─► Tools: pod_list, deploy_scale, job_run                    │
│    └─► Dispatches K8s Jobs for heavy work                        │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  KUBERNETES CLUSTER                                              │
│                                                                  │
│  k8s-steer-state ConfigMap (config, audit)                       │
│  k8s-steer-worker Job (ephemeral compute)                        │
└─────────────────────────────────────────────────────────────────┘

Example: Cloud Infrastructure

┌─────────────────────────────────────────────────────────────────┐
│  YOUR MAC                                                        │
│                                                                  │
│  Keychain: AWS credentials, GCP service account                  │
│                                                                  │
│  infra-steer MCP server                                          │
│    ├─► Tools: ec2_list, lambda_invoke, s3_sync                   │
│    └─► Dispatches via Step Functions / Cloud Workflows           │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  AWS / GCP                                                       │
│                                                                  │
│  S3 / GCS bucket (state)                                         │
│  Lambda / Cloud Run (workers)                                    │
│  Step Functions / Workflows (orchestration)                      │
└─────────────────────────────────────────────────────────────────┘

Example: Database Administration

┌─────────────────────────────────────────────────────────────────┐
│  YOUR MAC                                                        │
│                                                                  │
│  Keychain: database credentials                                  │
│                                                                  │
│  db-steer MCP server                                             │
│    ├─► Tools: query, migrate, backup, analyze                    │
│    └─► Dispatches via Cloud Functions                            │
└─────────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│  CLOUD                                                           │
│                                                                  │
│  Cloud SQL / RDS (managed database)                              │
│  Cloud Functions (migration runners, backup jobs)                │
│  GCS / S3 (backup storage, audit logs)                           │
└─────────────────────────────────────────────────────────────────┘

Key Principles

  1. Credentials stay local - Never in code, config files, or remote state
  2. State is versioned - Use Git or a versioned object store
  3. Compute is ephemeral - Spin up, do work, spin down
  4. Operations are audited - Every action logged
  5. Interface is natural language - MCP enables Claude integration

Performance Considerations

Rate Limits

GitHub Apps have rate limits:

  • 5,000 requests per hour per installation
  • 1,000 requests per hour for GraphQL

Mitigation strategies:

  • Batch operations where possible
  • Use ETags for caching
  • Implement backoff on 429 responses

Workflow Concurrency

GitHub Actions has concurrency limits:

  • 20 concurrent jobs (free tier)
  • 180 concurrent jobs (enterprise)

For large operations:

  • Implement queuing in git-steer-state
  • Use workflow concurrency groups
  • Stagger dispatches

Large File Operations

The GitHub Contents API has a 100MB file limit.

For larger files:

  • Use Git LFS
  • Dispatch a workflow that clones and commits directly
  • Use the Git Data API for streaming

Debugging Tips

Enable Verbose Logging

# In Claude Desktop config
{
  "mcpServers": {
    "git-steer": {
      "command": "node",
      "args": ["/path/to/git-steer/bin/cli.js", "start", "--stdio", "--verbose"]
    }
  }
}

Check Workflow Logs

# Get recent workflow runs
gh run list --repo ry-ops/git-steer --workflow security-fix.yml

# View specific run logs
gh run view RUN_ID --repo ry-ops/git-steer --log

Inspect State

# View audit log
gh api repos/ry-ops/git-steer-state/contents/state/audit.jsonl \
  --jq '.content' | base64 -d | jq -s '.[-10:]'

# View job history
gh api repos/ry-ops/git-steer-state/contents/state/jobs.jsonl \
  --jq '.content' | base64 -d | jq -s '.[-5:]'

What’s Next

git-steer is under active development. Planned features:

  • Scheduled operations - Cron-based security scans, branch cleanup
  • Webhooks - React to GitHub events in real-time
  • Multi-account - Manage multiple GitHub accounts/orgs
  • Metrics dashboard - Visualize operations, rate limits, audit logs

Contributions welcome at github.com/ry-ops/git-steer.


Conclusion

git-steer represents a new way of thinking about developer tooling:

  • Your machine is a controller, not a warehouse
  • Cloud is the compute layer, not just deployment target
  • Git is the database, not just version control
  • Natural language is the interface, not just documentation

The pattern scales from a single developer managing a few repos to teams managing hundreds. The architecture stays the same—only the workflows and policies change.

Build your own workflows. Extend the tools. Adapt the pattern. Make your machine a steering wheel, not an engine.


Repository: github.com/ry-ops/git-steer

Previous in series:

#MCP #GitHub #Advanced #Workflows #Automation #Architecture

Explore git-steer on GitHub

Check out the source code, documentation, and contribute to the project.