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
- The review loop is where it earns its keep
- The part I didn't plan: the board sprawled
- The twist: a teammate who can't use GitHub
- What I'd tell someone starting
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:
-
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.)
-
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.
-
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:
-
The obvious way doesn't work. Claude's "add a connector" UI only does OAuth login — which would authenticate as the PM's own GitHub identity, which they don't have. Dead end. The working path is a small local proxy (
mcp-remote) that injects a scoped access token instead, so the connection acts as the bot — no seat consumed, the PM never added to the org. -
A misleading error cost me an hour. Reading the board kept failing with "resource not accessible by token" — which screams "permissions problem." It wasn't. The token was fine (I proved it with a raw API call). The real cause: GitHub's integration doesn't load the Projects tools by default — you have to opt in. The error blamed the token; the token was innocent. A good reminder to verify the thing the error accuses before believing it.
-
The PM thinks in problems, not repos. They'd say "the wallet app won't show balances" — they have no idea that maps to a specific repository. So Claude has to do the routing: figure out which product a problem belongs to, confirm before filing, and when it genuinely can't tell, tag it for an engineer to sort rather than guess wrong.
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
- Automate the bookkeeping, not the thinking. The win isn't AI writing your code — it's AI removing the seven steps of friction around it so the board stays honest with zero willpower.
- Make it config-driven from day one. The skill knows nothing about any specific repo; the repo's config tells it everything. That's why it scales.
- One org board, not one per project. Learn from my migration tax.
- When you hit a wall, check what the error is actually accusing. "Token not accessible" wasn't the token. Verify the accusation before you act on it.
- The interface can outlive the tool. Once the workflow is something Claude drives, the people using it don't need to know the tool underneath — which is how a non-technical PM ended up running a GitHub board without GitHub.
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.