The useful version of an AI coding workflow is not just "ask an agent to write code".
The useful version is a small development system:
- GitHub Issues hold the work.
- A spec defines the shape of the change.
- Branches and pull requests keep the work reviewable.
- Checks prove the code still works.
- Releases turn merged work into something people can use.
The GitHub CLI is the bridge.
Once gh is authenticated, an agent can operate GitHub from the terminal instead of asking you to click around the web UI.
Most AI coding demos stop too early.
They show an agent editing files, but they skip the rest of software development:
- creating the repo
- writing the spec
- breaking work into issues
- keeping the board up to date
- opening pull requests
- responding to review feedback
- merging safely
- cutting a release
That is where real projects get messy.
If the agent can only write code, you still have to manage the workflow around it.
The better question is:
Can the agent move through the same development loop a professional engineer would use?
Use GitHub as the system of record.
Use the agent as the worker.
Use gh as the interface between them.
flowchart LR
Spec["Spec"] --> Issues["GitHub Issues"]
Issues --> Branch["Feature Branch"]
Branch --> PR["Pull Request"]
PR --> Review["Review + Checks"]
Review --> Merge["Squash Merge"]
Merge --> Release["Tag + Release"]
Release --> Issues
The loop is simple:
- Write a small spec.
- Turn the spec into issues.
- Pick one issue.
- Create a branch.
- Implement the change.
- Open a pull request.
- Review and verify.
- Merge.
- Repeat.
- Release when the work is useful.
The point is not to memorize GitHub commands.
The point is to make the workflow visible and repeatable.
For the tutorial, build a small Go CLI called shiplog.
shiplog generates Markdown release notes from merged GitHub pull requests.
It can:
- detect the current GitHub repo from the local git remote
- accept a previous tag and a new tag
- find merged pull requests between those refs
- group pull requests by label
- print clean Markdown release notes
- optionally write the output to a file
This is a good demo because it naturally uses GitHub concepts:
- pull requests
- labels
- tags
- releases
- GitHub Actions
The app is small enough to build in pieces, but real enough to justify the workflow.
You need:
- Git
- Go
- a GitHub account
- GitHub CLI
- Claude Code, Codex, or another coding agent with terminal access
Install GitHub CLI on macOS:
brew install ghAuthenticate:
gh auth login
gh auth status
gh --versionThe important check is gh auth status.
If that works, the agent can use gh commands from the terminal.
Start with a small, explicit repo setup prompt.
Create a new public GitHub repo called shiplog.
Initialize it with a README and a Go module.
Add a standard Go .gitignore.
Set the description to:
"Generate Markdown release notes from merged GitHub pull requests."
Add these topics:
- cli
- golang
- github
- release-notes
- ai-workflow
The agent will usually run commands like:
gh repo create shiplog --public --clone --add-readme
cd shiplog
go mod init github.com/YOUR_USERNAME/shiplog
gh repo edit --description "Generate Markdown release notes from merged GitHub pull requests."
gh repo edit --add-topic cli --add-topic golang --add-topic github --add-topic release-notes --add-topic ai-workflowThis is a small step, but it teaches the main idea.
The agent is not only editing code.
It is setting up the development environment around the code.
Before the agent writes code, give it a spec.
Use the spec skill.
I want to build a Go CLI called shiplog.
The tool generates Markdown release notes from merged GitHub pull requests.
It should:
- detect the current GitHub repo from the local git remote
- accept a previous tag and a new tag
- find merged pull requests between those refs
- group pull requests by label
- print clean Markdown release notes to stdout
- optionally write the output to a file
Write a complete spec covering:
- requirements
- command structure
- flags and arguments
- technical approach
- external dependencies
- error handling
- test strategy
Save it to specs/initial-spec.md.
Review the spec before moving on.
This is where you catch bad assumptions while they are still cheap.
Check:
- Is the CLI small enough?
- Are the commands clear?
- Are the first tasks independently buildable?
- Is there a realistic happy path for the release pipeline?
Now turn the spec into GitHub Issues.
Use the plan skill.
Take the spec at specs/initial-spec.md and break it down into GitHub issues.
Each issue should include:
- a clear title
- a short description
- acceptance criteria as a checklist
- relevant context from the spec
Push the issues to GitHub using gh issue create.
Use labels:
- feature
- bug
- chore
- docs
A good issue breakdown might look like this:
- Initialize Go CLI structure.
- Detect GitHub repository from git remote.
- Fetch merged pull requests between refs.
- Group pull requests by labels.
- Render Markdown release notes.
- Add file output flag.
- Add tests and fixtures.
- Add GitHub Actions CI.
- Add release workflow.
Create labels first:
gh label create feature --color 0E8A16 --description "New user-facing functionality"
gh label create bug --color D73A4A --description "Bug fixes"
gh label create chore --color C5DEF5 --description "Maintenance work"
gh label create docs --color 0075CA --description "Documentation"Then create issues:
gh issue create --title "Initialize Go CLI structure" --label featureThe board matters because it gives the agent a clean queue.
Instead of asking for one giant change, you give it one reviewable task at a time.
The safest agent workflow is narrow.
Give the agent one issue, one branch, and one verification path.
Use the implement skill.
Take issue #1 from the project board.
1. Move the issue to In Progress.
2. Check out a new Git branch named after the issue.
3. Write the code to satisfy the acceptance criteria.
4. Run formatting and tests.
5. Use a fresh review context to inspect the diff.
6. Fix valid review findings.
7. Open a pull request back to main using gh pr create.
The PR description should include:
- summary
- testing notes
- follow-up work
- Closes #1
Expected commands:
git checkout -b feature/initialize-go-cli
go fmt ./...
go test ./...
gh pr create --base main --head feature/initialize-go-cliA useful PR body is short and factual:
## Summary
- Initialize the Go CLI project structure
- Add the first command entrypoint
- Add basic tests
## Testing
- `go test ./...`
Closes #1The review step is important.
The same context that wrote the code is often too attached to its own assumptions.
A fresh review context catches different mistakes.
Do not blindly accept every review comment.
Make the agent triage feedback.
Use the address PR feedback skill.
Pull down all comments on this PR using gh pr view and gh api.
Work through them one by one.
For each comment, decide whether it is:
- valid feedback that needs a code change
- valid feedback that does not need a code change
- feedback you disagree with
Apply fixes where appropriate.
When you push a fix, reply on the comment thread saying what changed.
For comments you do not act on, reply with the reason.
Useful commands:
gh pr view --comments
gh pr checks
gh pr diffThis is where judgment matters.
The agent should help you process feedback, not turn every suggestion into code.
When the PR is ready, squash merge it.
gh pr merge --squash --delete-branchThen repeat the same loop for the next issue.
Take the next issue from the project board.
Move it to In Progress.
Create a branch.
Implement the acceptance criteria.
Run tests.
Review the diff in a fresh context.
Open a PR.
Address feedback.
Prepare it for squash merge.
This is deliberately boring.
Boring is good here.
The agent gets more useful when the workflow around it is predictable.
Once the CLI works, ship it.
For a Go CLI, a simple release workflow can build platform binaries and attach them to a GitHub release when you push a tag.
Planning prompt:
I want to set up a release pipeline for this Go CLI as a GitHub Action.
When I push a Git tag like v0.1.0, the workflow should:
1. Check out the code at the tag.
2. Build binaries for macOS arm64, macOS amd64, Linux amd64, and Windows amd64.
3. Name the binaries clearly.
4. Generate release notes from merged PRs since the previous tag.
5. Create a GitHub release.
6. Attach all platform binaries to that release.
Before you write any code, walk me through your plan.
I want to sanity-check the approach.
Example workflow:
name: Release
on:
push:
tags:
- "v*.*.*"
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Build binaries
shell: bash
run: |
mkdir -p dist
platforms=(
"darwin amd64 shiplog-darwin-amd64"
"darwin arm64 shiplog-darwin-arm64"
"linux amd64 shiplog-linux-amd64"
"windows amd64 shiplog-windows-amd64.exe"
)
for platform in "${platforms[@]}"; do
set -- $platform
GOOS=$1 GOARCH=$2 go build -o "dist/$3" ./cmd/shiplog
done
- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
gh release create "${GITHUB_REF_NAME}" dist/* \
--repo "${GITHUB_REPOSITORY}" \
--title "${GITHUB_REF_NAME}" \
--generate-notesThe key details are:
permissions: contents: writeallows the workflow token to create releases.fetch-depth: 0gives the workflow access to tag history.--generate-notesasks GitHub to generate release notes for the tag.GH_TOKEN: ${{ github.token }}letsghauthenticate inside the workflow.
Commit the workflow, tag the release, and push the tag.
git add .github/workflows/release.yml
git commit -m "ci: add release workflow"
git tag v0.1.0
git push origin main
git push origin v0.1.0Watch the workflow from the terminal:
gh run list --limit 5
gh run watch
gh release view v0.1.0This is the payoff.
The agent did not just produce a file.
It moved through a real software delivery loop.
This workflow still needs human oversight.
Watch for:
- weak specs that create vague issues
- giant issues that produce unreviewable PRs
- agents merging without enough verification
- review comments applied without judgment
- release workflows that work once but are hard to maintain
The fix is not a bigger prompt.
The fix is smaller work, clearer acceptance criteria, and verification at every step.
Copyable prompts and command references live in:
The one thing to remember:
GitHub can become the control plane for an AI development workflow.
The honest limitation:
An agent can move issues, branches, PRs, and releases, but you still need to review the spec, scope, feedback, and verification.
What to try next:
Build one tiny CLI or internal tool with this loop.
Do not start with your biggest repo.