Automating My GitHub Workflow with Claude — and Letting a Non-Technical PM In

Automating My GitHub Workflow with Claude — and Letting a Non-Technical PM In

The actual coding was never the slow part. The slow part was everything around it.

File an issue. Label it. Put it on the board. Branch. Do the work. Push a PR that closes the issue. Wait for CI. Move the ticket to Code Review. Get it merged. Move the ticket to Done. Repeat — for every single change. None of it is hard. All of it is friction, and friction is where consistency goes to die. I'd do the work and forget to move the ticket. The board would lie about what was actually happening.

So I taught Claude to do the boring half. This is what that turned into — and the part I genuinely didn't see coming, where a teammate who has never opened GitHub started using the same system.

In this post:

The loop I wanted to disappear

Here's the workflow every ticket goes through, in my head:

file issue → start work → open PR → CI passes → code review → merge → board updated

Seven steps, six of which are bookkeeping. I built a Claude skill — I call it gh-workflow — that owns the bookkeeping so I can stay on the one step that matters (the work). I just say things like "let's work on #142" or "this is done," and it drives the rest.

A quick aside on that one step — the work — because it's not me hand-typing every line either. Depending on the ticket, the actual coding is done by a small cast of specialized agents: a "principal engineer" agent that drafts the change, an adversarial reviewer agent whose only job is to try to tear it apart before a human ever sees it, and for big or risky work, a whole orchestrated team that splits the job and checks each other. That's a genuinely deep rabbit hole — how you get a team of AI agents to write code that survives review — and it deserves its own post. For this one, just hold the thought that "do the work" is itself automated; the part I'm describing here is everything wrapped around it.

A few decisions made it actually usable rather than a clever demo:

It's config-driven, not hardcoded. Each repo has a tiny config file (gh-workflow.yaml) describing its board, labels, and CI commands. The skill reads that, so the same skill drives every repo without knowing anything about them in advance. New repo? Point its config at the board and the skill just works.

It files the issue first, always. No PR without an issue behind it. The issue is the unit of work that lives on the board; the PR is an implementation detail that links back to it. This one rule keeps the board honest — every trackable thing is an issue, nothing important hides inside a PR.

It refuses to lie about CI. A ticket can't move to "Code Review" while tests are red or still running. The status on the board reflects reality because the automation won't advance it otherwise. That's the whole point — the board is only useful if it's true.

It does the work as a bot, not as me. Commits and PRs are authored by a dedicated bot identity, not my personal account. Small thing, big payoff: I can actually review the bot's PRs (you can't meaningfully review your own), and the audit trail is clean.

The result is that the board stopped being a chore I maintained and became a thing that maintained itself as a side effect of working. That alone was worth it.

The review loop is where it earns its keep

Opening a PR isn't the end — it's the start of the part that used to eat my attention in little fragments all day: is CI done yet? did anyone comment? did the bot reviewer flag something? is it ready to merge? Refreshing the PR tab is its own kind of tax.

So the automation doesn't fire-and-forget the PR. After it opens one, it arms a live watch and then drives the whole review loop:

  1. Watch CI first. It polls the PR's checks. Red → stop, report, leave the ticket where it is. Green → move on. (It also knows the one weird case where a PR that edits a workflow file makes the AI-review check fail by design — that one's safe to ignore, and only the real test job counts.)

  2. Once CI is green, move the ticket to Code Review — and keep watching. This is the part I'm proud of. It doesn't just wait for an approval; it reacts to every kind of review event, live:

    • The AI code reviewer (we run one on every PR) posts an inline comment → the bot reads it, and if it's a real issue, pushes a fix.
    • A human leaves a comment or a "changes requested" → it addresses every point, pushes, and replies on the thread.
    • A human asks a question (a review that's just "commented", not approved) → it answers, because a question is a soft block: the PR shouldn't merge until it's resolved.
    • CI goes red on a new push → back to fixing.

    It loops through that — fix, push, re-check, respond — until the only thing left is a human's green light.

  3. On human approval, it auto-merges — but only behind seven guardrails. This was the scariest thing to get right, because "auto-merge" sounds like "merge things it shouldn't." So it refuses unless all seven hold: auto-merge is opted-in for that repo, the PR was authored by the bot (never auto-merges a human's PR), no conflicts, no outstanding "changes requested", no unresolved reviewer threads, all required checks pass, and GitHub's own merge state is clean (so branch protection still rules). Any one fails → it doesn't merge, and tells me exactly which guardrail stopped it. Then the merge flips the ticket to Done on its own.

Two things I learned building this loop:

Watch the right signal, or you miss the human. My first version polled the PR's (state, review decision, merge status). Problem: when a human leaves a comment or a question — the most common kind of review — none of those three fields change. So the automation sat there thinking nothing happened while a reviewer waited for an answer. You have to watch the actual newest comment/review from a human, not just the headline status. A reviewer's question that goes unanswered for 30 minutes because your poll was too coarse is a great way to annoy your teammates.

The board is the memory. The watch lives in the session — close my laptop and it dies. So on every start, the automation sweeps the board: any ticket sitting in "Code Review" whose PR is still open gets its watch re-armed. The board isn't just a display; it's the source of truth that lets the whole thing survive restarts. The work doesn't get lost because the state lives somewhere durable, not in a running process.

The net effect: I open a PR and basically walk away. CI, the AI reviewer's nits, a teammate's questions, the merge, the board update — it rides the whole thing to Done and only pulls me in when a human needs to actually decide something. The fragments-of-attention tax is gone.

The part I didn't plan: the board sprawled

Once it was easy to put work on a board, I made a board for every project. Which felt tidy right up until I had four of them and no single place that answered "what's everyone working on?"

The fix was something I should have known from the start: GitHub's Projects are org-level and multi-repo by design. One board can hold issues from every repo, tagged by which repo they came from. So I consolidated four boards into one — "THXNET Engineering" — migrated ~140 issues across (their labels travel with them automatically; their status doesn't, that's per-board and has to be re-set), and pointed every repo's config at the single board.

Lesson I'll keep: per-project boards are the thing you grow out of. Start with one org board and a "which repo" column. I did it backwards and paid the migration tax.

The twist: a teammate who can't use GitHub

Here's where it got interesting. Our project manager doesn't have a GitHub account — seats cost money, and it's hard to justify one for someone who'll never touch code. But they're exactly the person who needs to know what the team is working on, and who has new tasks to add.

They do use Claude, though. So the question became: can the PM drive the board through Claude, without ever touching GitHub?

It turned out to be yes — and the path was full of small walls I had to climb:

Now the PM opens Claude and says "what's the team working on?" and gets the live board, grouped and readable. They report a bug in plain language and it lands as a properly-labeled issue in the right repo. The same automation foundation I built for myself just... extended to someone who can't use the underlying tool at all. That's the part that surprised me.

What I'd tell someone starting

The boring half of my workflow now runs itself, the board doesn't lie, and a teammate who can't use GitHub is fully plugged in. For something I built to get a bit of friction out of my own day, that turned out to be a pretty good place to land.


I've been thinking about cleaning up the gh-workflow skill and open-sourcing it — the config-driven, repo-agnostic version, not anything tied to my team's setup. If that's something you'd actually use, leave a comment below and I'll prioritise it.