The assistant runs gh now
For a while I was the courier. Claude would draft a pull request description in the terminal, I'd select it, paste it into the GitHub compose box, open the PR, then copy the review bot's finding back down into the terminal so Claude could read what it was reacting to. Every round trip was me moving text between two windows that couldn't see each other.
Then I let the assistant run gh, GitHub's command-line tool, directly. It's a small change on paper. The effect was bigger than I expected, and most of it had nothing to do with the model getting smarter. The plumbing just stopped leaking.
What it unlocks in the loop
gh turns GitHub into something the assistant can operate without leaving the shell it's already in. Opening a PR, reading a review comment and replying to it in-thread, posting a summary comment, closing a superseded PR, creating a label or filing an issue. All of it happens in the same place the code was written, in the same turn.
The context switch was the expensive part. Not the typing. When the PR description lived in my head as "the thing Claude wrote that I need to go paste," it was one more handoff where detail leaked out. Now the assistant that wrote the change also writes the PR, and it still has the whole change in working memory when it does.
Every PR gets a real description
Here's the part that surprised me most. The win isn't one great PR description. It's that every PR gets the same treatment, and none of them get a lazy one-liner.
The bodies come out structured the same way each time: what changed, why those choices, the trade-offs, and how it was verified. A recent backup PR opened with the mechanism (a daily cron encrypts an export and uploads it), then a "Why these choices" section that actually argued for count-based pruning over a size cap, then the exact environment variables you'd need to set before it runs in production. I didn't ask for that shape. It just shows up, PR after PR.
Commit messages get the same discipline. Instead of "fix bug," the messages explain the why and point at the verification. One read Harden neon snapshot: KEEP validation, non-fatal prune, pagination, and the body walked through each of the three fixes and how each was checked. When I go back through git history now, the messages tell me why a thing changed, not just that it did.
I've always taken care to write good PR descriptions, but that care used to cost me effort. The assistant writes the same way at 11pm as at 9am, and that steady consistency is most of what I'm getting out of this.
Splitting a mega-PR
The clearest example of gh earning its keep was a PR I'd let grow too big.
I'd prototyped an automatic post-series feature, and the branch had quietly accumulated everything: the series collection, a migrations workflow, production database tooling, and Neon preview branching. By the time I looked at it as a pull request it was 4,649 lines added across unrelated concerns. Nobody reviews that. I wouldn't have wanted to review that.
So I asked Claude to split it. It broke the work into three focused, stacked PRs. The first was the migrations workflow plus the production database tooling, the foundation the other two sat on. The second was the series feature itself, based on the first and containing only the feature diff. The third was preview branching and optional auto-migrate on deploy, also based on the first but independent of the second.
Each got its own tailored description. Each stated its merge order at the top ("First of three PRs splitting the old #10. Merge order: this, then Series, then preview branching"). Each cross-linked to the others and to the original. Then the original prototype PR was closed with a pointer to the three replacements.
What made that painless was that gh made the mechanics cheap. Creating the branches, setting the right base for each stacked PR, writing three descriptions, linking them together, closing the old one with a comment. That's a lot of small careful steps, and each one is exactly the kind of thing I'd have half-done if I were doing it by hand at the end of a long session.
Closing the review loop in one turn
The project runs a review bot on pull requests, and watching Claude answer it changed how fast the loop moves.
A finding comes in. The assistant reads it with gh api, looks at the flagged code, and makes an actual judgment about whether it's real or low-risk. When it's real, it fixes it, verifies the fix, pushes, and replies in the same thread, all in one turn.
One finding on the preview-branching PR was the scary kind. A backup-pruning script coerced a KEEP count from an environment variable without validating it. If that variable were 0 or a non-numeric string, Number() would produce 0 or NaN, slice would treat both as zero, and the prune would delete every backup, including the one just created. High severity, correctly. The reply Claude posted after fixing it:
Fixed in aceab7b — good catch, this was the scary one.
NEON_PREMIGRATION_KEEPis now validated to an integer >= 1 (else falls back to 5), soslice(KEEP)can never behave likeslice(0)and delete the just-created backup. Verified: KEEP=0 and KEEP=abc now prune only the genuinely-old backups.
That's the template every reply follows: the fixing commit, what changed, and how it was checked. Another finding on the series PR pointed out that deleting a post left stale references in its series, because the database's cascade delete removed the relationship before the cleanup hook could run. The fix moved the sibling refresh to a beforeDelete hook, while the relationship still existed, and the reply said so and noted it was verified against a local Postgres.
It isn't only bots. When I left a review comment myself, asking why a type assertion was there and calling it a code smell, the answer came back with the reasoning, not just a change: the value was already typed through Payload's generated types, so the assertion was a leftover from an earlier version of the module and could just go. Removed in one commit, explained in the reply. The back-and-forth reads like a conversation with someone who actually reads the comment before answering.
The guardrails I keep
None of this runs unsupervised, and a few rules matter enough that I've written them down.
Anything outward-facing waits for me. Opening a PR, posting a comment, closing something. The assistant drafts it and asks before it publishes. I've been happy to say "go" almost every time, but the confirmation is the point, because publishing is a one-way door and I want a human hand on it.
Merging stays mine. The assistant can do everything up to the merge button. It doesn't press it. That's the one decision I've kept entirely for myself, and I don't expect that to change.
Shell quoting will bite you, and this one is a practical tip. A couple of gh commands broke because the PR body went in as a heredoc containing backticks and apostrophes, and the shell tried to interpret them. The fix was to write the body to a file and pass --body-file instead of inlining it. It's now a standing convention in the project: draft the description in a file, hand gh the file. No quoting surprises, and the body is easier to read over before it goes out.
What actually changed
I keep wanting to describe this as the assistant getting better at GitHub, but that's not it. The model didn't change. What changed is that the work and the record of the work stopped living in two separate places with me shuttling between them.
The artifacts are better because they're written by the thing that just did the work, while it still remembers why. The review turnaround is measured in minutes because reading a finding, fixing it, and replying no longer involves me relaying anything. And I context-switch less, which at the end of a long day is the difference between a clean PR and a one-line description I'll regret in three months.
The assistant runs gh now. I mostly say "go."
Comments
No comments yet. Be the first to comment.