🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

Build an AI Runbook Generator with Claude API and Git History

Auto-generate incident runbooks from your git history, monitoring alerts, and past incidents using Claude API. Runbooks stay up to date automatically as your code changes — no manual maintenance.

Shubham4 min read
Share:Tweet

Runbooks go stale within weeks of being written. This tool uses Claude API to generate runbooks from your actual git history, Kubernetes configs, and alert definitions — so they reflect what the system actually does.

Setup

bash
pip install anthropic gitpython pyyaml

Generate Runbook from Service Context

python
import anthropic
import subprocess
import yaml
import json
from pathlib import Path
 
client = anthropic.Anthropic()
 
 
def get_git_context(repo_path: str, service_name: str) -> dict:
    """Extract relevant context from git history."""
    context = {}
 
    # Recent commits for this service
    result = subprocess.run(
        ["git", "log", "--oneline", "-20", "--", f"*{service_name}*"],
        capture_output=True, text=True, cwd=repo_path
    )
    context["recent_commits"] = result.stdout
 
    # Check for incident-related commits
    result = subprocess.run(
        ["git", "log", "--oneline", "-50", "--grep=fix", "--grep=hotfix", "--grep=incident", "--all-match"],
        capture_output=True, text=True, cwd=repo_path
    )
    context["incident_commits"] = result.stdout
 
    return context
 
 
def get_kubernetes_context(namespace: str, deployment_name: str) -> dict:
    """Get deployment configuration."""
    context = {}
 
    result = subprocess.run(
        ["kubectl", "get", "deployment", deployment_name, "-n", namespace, "-o", "yaml"],
        capture_output=True, text=True
    )
    if result.returncode == 0:
        dep = yaml.safe_load(result.stdout)
        # Extract key info only
        spec = dep.get("spec", {})
        containers = spec.get("template", {}).get("spec", {}).get("containers", [])
        context["replicas"] = spec.get("replicas", 1)
        context["containers"] = [
            {
                "name": c["name"],
                "image": c["image"],
                "ports": c.get("ports", []),
                "env_count": len(c.get("env", [])),
                "readiness_probe": bool(c.get("readinessProbe")),
                "resources": c.get("resources", {})
            }
            for c in containers
        ]
 
    # Get HPA if exists
    result = subprocess.run(
        ["kubectl", "get", "hpa", "-n", namespace, "-o", "json"],
        capture_output=True, text=True
    )
    if result.returncode == 0:
        hpa_data = json.loads(result.stdout)
        context["hpa"] = [
            {
                "name": item["metadata"]["name"],
                "min": item["spec"].get("minReplicas"),
                "max": item["spec"]["maxReplicas"],
            }
            for item in hpa_data.get("items", [])
            if item["spec"]["scaleTargetRef"]["name"] == deployment_name
        ]
 
    return context
 
 
def generate_runbook(
    service_name: str,
    namespace: str = "production",
    repo_path: str = ".",
    alert_description: str = None
) -> str:
    """Generate a complete runbook for a service."""
 
    git_context = get_git_context(repo_path, service_name)
    k8s_context = get_kubernetes_context(namespace, service_name)
 
    prompt = f"""You are an experienced SRE writing an operational runbook.
 
## Service Information
- Service: {service_name}
- Namespace: {namespace}
- Replicas: {k8s_context.get("replicas", "unknown")}
- Auto-scaling: {json.dumps(k8s_context.get("hpa", []))}
- Containers: {json.dumps(k8s_context.get("containers", []), indent=2)}
 
## Recent Git History
{git_context.get("recent_commits", "No recent commits found")}
 
## Past Incident Commits
{git_context.get("incident_commits", "No incident commits found")}
 
{f"## Alert Being Investigated\n{alert_description}" if alert_description else ""}
 
Generate a complete operational runbook in Markdown for this service. Include:
 
1. **Service Overview** — what it does, dependencies, SLO
2. **Health Checks** — kubectl commands to verify service health
3. **Common Incidents** — based on git history, list likely failure modes
4. **Diagnosis Steps** — step-by-step commands to diagnose issues
5. **Escalation Path** — when to escalate and to whom
6. **Rollback Procedure** — exact commands to roll back
7. **Useful Commands** — kubectl, curl, log commands for this specific service
 
Make it specific and actionable. Use real kubectl commands with the actual namespace and service name."""
 
    response = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=3000,
        messages=[{"role": "user", "content": prompt}]
    )
 
    return response.content[0].text
 
 
def save_runbook(service_name: str, runbook_content: str, output_dir: str = "runbooks/"):
    """Save runbook as markdown file."""
    Path(output_dir).mkdir(exist_ok=True)
    output_path = Path(output_dir) / f"{service_name}-runbook.md"
    output_path.write_text(runbook_content)
    print(f"Runbook saved: {output_path}")
    return str(output_path)
 
 
if __name__ == "__main__":
    import sys
 
    service = sys.argv[1] if len(sys.argv) > 1 else "payment-service"
    namespace = sys.argv[2] if len(sys.argv) > 2 else "production"
    alert = sys.argv[3] if len(sys.argv) > 3 else None
 
    print(f"Generating runbook for {service} in {namespace}...")
    runbook = generate_runbook(service, namespace, alert_description=alert)
    path = save_runbook(service, runbook)
    print(f"\nRunbook generated: {path}")
    print("\nPreview:")
    print(runbook[:500] + "...")

Example Output

markdown
# payment-service Runbook
 
## Service Overview
The payment-service handles all payment processing for the platform.
It calls Stripe API, writes to PostgreSQL, and publishes events to SQS.
SLO: 99.9% availability, p99 latency < 500ms.
 
## Health Checks
kubectl get pods -n production -l app=payment-service
kubectl top pods -n production -l app=payment-service
kubectl logs -n production -l app=payment-service --tail=100 | grep -i error
 
## Common Incidents (from git history)
1. Stripe API timeout (6 past incidents) — payment-service/stripe_client.py
2. Database connection pool exhaustion — increases under load spikes
3. SQS dead letter queue buildup — check when deployments fail mid-publish
 
## Diagnosis Steps
...

Automate Weekly Runbook Updates

yaml
# .github/workflows/update-runbooks.yml
name: Update Service Runbooks
 
on:
  schedule:
    - cron: '0 6 * * 1'  # Monday 6 AM
 
jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Generate updated runbooks
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          pip install anthropic gitpython pyyaml
          for service in payment-service api-gateway user-service; do
            python generate_runbook.py $service production
          done
      - name: Commit updated runbooks
        run: |
          git config user.name "github-actions"
          git config user.email "github-actions@github.com"
          git add runbooks/
          git diff --staged --quiet || git commit -m "Auto-update runbooks [skip ci]"
          git push

Runbooks that update themselves from real system context stay accurate — the fundamental problem with manually maintained runbooks.


More AI SRE tools? Read our Build AI on-call assistant with PagerDuty and Claude and LLM-powered incident response.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Build an AI Load Test Scenario Generator with Claude API

Writing realistic k6 or Locust load test scenarios means understanding actual traffic patterns, not just hammering one endpoint. Build a tool that reads your API spec and real traffic logs, then generates realistic load test scripts with Claude API.

S
3 min readRead

Comments