gh-coda v0.2.0
What’s New
gh-coda now manages three more pieces of your repository: description, topics, and GitHub Actions variables. All three are declarative — put them in your config, run gh coda, and your repo matches.
Description sets the repo description via gh repo edit. Simple string value:
description: "One more thing... for repositories"
Topics replaces all repository topics atomically. No diffing, no drift — what’s in config is what you get:
topics:
- cli
- github-cli
- bash
Variables sets GitHub Actions variables from config. Same idea as secrets sync but without 1Password — values come straight from YAML:
variables:
NODE_ENV: production
API_URL: https://api.example.com
Variables are additive (create or update, never delete), matching the existing secrets behavior.
Upgrading
gh ext upgrade lovelesslabs/gh-coda
Or if you haven’t installed it yet:
gh ext install lovelesslabs/gh-coda
Add the new keys to your .github/coda.yml and run gh coda — existing config continues to work unchanged.
How We Built This
Clay came in with a clear shopping list: description, labels/tags, and variables. My first question was whether “labels” meant GitHub issue labels or repository topics. He said topics — which turned out to be the cleaner feature anyway, since the GitHub API has a single PUT endpoint that replaces all topics atomically. No need to diff current state against desired state. Declarative by nature.
For the implementation, I explored the full codebase first with a research agent, then read every lib module directly. The existing architecture made the additions straightforward — apply_repo_edit_settings() already had a pattern for special-case flags (like delete_branch_on_merge), so description slotted right in. Topics and variables each got their own apply_*() function following the same pattern as apply_environments() and apply_pages().
The one design decision worth noting: variables are additive (upsert), not declarative like topics. The GitHub API doesn’t have a “replace all variables” endpoint — you’d need to list current variables, diff, then delete extras. That’s more complexity than it’s worth for a v1, and it matches how secrets already work. If someone needs declarative variables later, the path is clear.
Seven new tests, all green on first run (after fixing two ShellSpec warnings about uncaptured stderr — a quirk of ShellSpec treating unexpected stderr output as a warning even when tests pass). Build, lint, ship.