byob-go-cli
Bring Your Own Beads — Go CLI edition. A forkable template repository for Go CLI tools. Holds my preferred architectural decisions and idiomatic tips as beads records, ready to be cloned into a new project (or injected into an existing one) as the starting point for coding agents.
Status: experimental. The decision set, memory tier, and distribution mechanics are all likely to evolve. Expect breaking changes to category names, bead IDs, and the
make import/make exportworkflow between releases. Pin to a specific tag if you need stability.
What this is
This is not a library and not a Go package — it's a template. You fork it by copying it, re-init its beads database with a project- specific prefix, and then add your own task beads on top of the inherited decision beads. Coding agents working in the fork consult the decision beads as "how to structure things" and implement the tasks following those decisions.
Two layers of guidance live in the beads DB:
- Library beads — architectural decisions grouped into
categories, shipped under a custom
byobissue type so they're distinguishable from your project's own work. Full Problem / Idea / Tradeoffs / Sketch template. Consulted on demand viabd list --type=byobandbd show. - Memories — one-line idiomatic tips (e.g. "wrap errors with
%w", "usesync.OnceValue", "callt.Helper()in test helpers"). These auto-inject into every agent session viabd prime, so they are always-on context without ceremony.
Library beads are grouped under category roots (parentless beads)
covering the breadth of a Go CLI — architectural choices, CLI
ergonomics, testing patterns, observability, and the packaging and
release surface. Once imported, bd list --type=byob --no-parent
enumerates the categories, and bd list --type=byob -l errors (or
any category label) drills in.
Agents: if you've been asked to apply byob to an existing repo, see CLAUDE.md first. The workflow is "seed the target's beads DB from the release, then file task beads" — not "review and fix."
Decisions
21 category epics, each grouping a handful of decisions in the Problem / Idea / Tradeoffs / Sketch shape.
-
Agent onboarding
0 decisionsYou are working inside a forked copy of byob-go-cli, a personal template repository for Go CLI tools. The beads database you're looking at contains the template's architectural decisions alongside the tasks for this specific project.
-
Command shape
6 decisionsOptions struct + NewCmdXxx constructor + pure runFunc three-part separation.
-
Config
3 decisionsLayered, lazily loaded configuration with discovery and provenance.
-
Errors
4 decisionsSemantic error types mapped to exit codes by the top-level runner.
-
Factory + DI
1 decisionCentral factory struct with lazy-loaded dependencies passed into every command.
-
HTTP client
5 decisionsA single
*http.Clienton the Factory, built from a composablehttp.RoundTrippermiddleware chain; deterministichttptestseams in tests. -
Input validation
5 decisionsDefense against untrusted input beyond the flag-value checks already in
byob-errors.1: path traversal, config-shape validation, shell injection, SQL injection, and enum/range checks at the Options boundary. -
Interfaces
3 decisionsInterface-driven seams for swappable implementations and test doubles.
-
IOStreams
3 decisionsSingle abstraction for stdin/stdout/stderr with TTY detection and color support.
-
Layout
1 decisionConventional directory split and cobra command grouping.
-
Lifecycle
3 decisionsProcess-lifecycle and cancellation: signal handling, context propagation through runFuncs.
-
Logging
4 decisionsStructured, contextual, leveled logging threaded through every command without ceremony.
-
Output
3 decisionsTTY-adaptive human output plus first-class structured export.
-
Progress
4 decisionsAdaptive progress that looks right on a TTY and degrades off-TTY. Spinners for unknown-total, bars for known-total.
-
Prompter
5 decisionsNarrow Prompter interface on the Factory with TTY detection, scripted test double, and a library pick that won't rot.
-
Release
10 decisionsPure-Go discipline (CGO_ENABLED=0, go:embed) as the foundation; Makefile+ldflags for day-to-day builds; goreleaser for tag-triggered cross-compile, archives, checksums, optional homebrew/nfpm channels. Both paths inject the same ldflags vars so version output is path-independent.
-
Runtime directories
4 decisionsPer-OS directories for cache, state, and data (config is covered in byob-config), plus the atomic-write discipline that keeps them consistent under concurrent invocations.
-
Security
5 decisionsSupply-chain and secret-handling posture: pin by hash not tag, scan for known CVEs on every push, ship SBOMs and signatures from the release pipeline, and refuse to accept secrets as flag values.
-
Storage
6 decisionsMulti-engine persistent storage for CLI state: sqlite + postgres behind a consumer-scoped Store interface. CockroachDB rides the postgres wire protocol.
-
Testing
4 decisionsTest-first command structure: runF injection, in-memory IO, test doubles.
-
User docs
5 decisionsNarrative user docs distinct from generated reference (byob-output.3). README carries orient-and-quickstart only;
--helpLong/Example fields carry the detailed reference; narrative docs cover concepts and troubleshooting. Release notes come from git history, not a hand-maintained CHANGELOG.
Memories
24 one-paragraph idiomatic tips. Read all.
atomic-rename-samedirblank-ident-assertcontext-first-paramdecisions-lookupdefer-unlockdoc-comment-shapeerrors-is-aserrors-message-styleerrors-wrap-wgoroutine-exit-pathgot-want-orderinitialism-casingno-blank-error-discardno-get-prefixpass-by-value-defaultprinciples-dry-kiss-solidprompter-tty-checkquote-strings-in-errorsreceiver-namesync-oncevaluetest-cleanuptest-helpertest-tempdirvalidate-at-boundaries