It started, as these things often do, with an error message.
I use beads—a CLI issue tracker that lives in your git repo—every single day. It's become indispensable for tracking work across coding sessions. But here's the thing: beads is written in Go, and I've never written a line of Go in my life.
So when my routine update command failed spectacularly, I found myself staring at an error I couldn't begin to debug manually.
The Error That Started Everything
go install github.com/steveyegge/beads/cmd/bd@latestA command I'd run dozens of times before. This time:
# github.com/dolthub/gozstd
stream.go:14:48: undefined: DefaultCompressionLevel
stream.go:31:59: undefined: CDict
stream.go:47:20: undefined: Writer
stream.go:56:22: undefined: NewWriterLevel
stream.go:101:61: undefined: DDict
stream.go:110:6: undefined: Reader
stream.go:117:8: undefined: NewReaderI didn't know what gozstd was. I didn't know what CDict or DDict meant. But I had Claude Code open, and a hunch that maybe—just maybe—we could figure this out together.
Following the Breadcrumbs
The first clue came from checking my Go environment:
> go version && go env GOOS GOARCH CGO_ENABLED
go version go1.25.5 windows/amd64
windows
amd64
0That last line—CGO_ENABLED=0—would turn out to be the key to everything.
Claude explained: "The dolthub/gozstd library is a CGO wrapper around the C zstd compression library. On Windows, CGO is disabled by default unless a C compiler is installed."
CGO. The bridge between Go and C code. Disabled on my Windows machine because I don't have MinGW or any C compiler installed. Why would I? I'm not a Go developer.
We filed a bug report, documenting the issue thoroughly. But then came the first twist.
Plot Twist: The Solution Already Existed
> gh release view v0.47.1 --repo steveyegge/beads
asset: beads_0.47.1_windows_amd64.zip
asset: beads_0.47.1_windows_arm64.zipPre-built Windows binaries. They'd been there all along.
irm https://raw.githubusercontent.com/steveyegge/beads/main/install.ps1 | iexProblem solved, right? I could have stopped there. But something nagged at me. Other Windows users would hit this same wall. They'd try go install, get a cryptic error about compression libraries, and maybe give up entirely—never knowing that pre-built binaries existed.
Could we actually fix the root cause?
Down the Rabbit Hole
I asked Claude to clone the repo and investigate. What followed was a masterclass in dependency archaeology.
> go mod why github.com/dolthub/gozstd
github.com/steveyegge/beads/internal/storage/dolt
github.com/dolthub/driver
github.com/dolthub/dolt/go/cmd/dolt/commands/engine
github.com/dolthub/dolt/go/cmd/dolt/cli
github.com/dolthub/dolt/go/store/nbs
github.com/dolthub/gozstdThe dependency chain revealed itself:
The problematic gozstd was six layers deep, buried in Dolt's storage layer. Dolt is a version-controlled database—powerful stuff, but it brings heavy dependencies.
Here's the thing: beads has multiple storage backends. SQLite is the default. Dolt is optional. But the way the code was structured, even if you never used Dolt, you still pulled in all its dependencies at compile time.
The Fix Takes Shape
The solution emerged: build tags. Go's mechanism for conditional compilation. If we could make the Dolt backend only compile when CGO was available, Windows users could build beads with just the SQLite backend.
Claude refactored the storage factory to use a registration pattern:
// factory.go - always compiled
var backendRegistry = make(map[string]BackendFactory)
func RegisterBackend(name string, factory BackendFactory) {
backendRegistry[name] = factory
}
func NewWithOptions(ctx context.Context, backend, path string, opts Options) (storage.Storage, error) {
switch backend {
case "sqlite", "":
return sqlite.New(ctx, path)
default:
// Check if backend is registered (e.g., dolt with CGO)
if factory, ok := backendRegistry[backend]; ok {
return factory(ctx, path, opts)
}
if backend == "dolt" {
return nil, fmt.Errorf("dolt backend requires CGO; use sqlite or install from pre-built binaries")
}
return nil, fmt.Errorf("unknown storage backend: %s", backend)
}
}Then a separate file with a build constraint:
//go:build cgo
// factory_dolt.go - only compiled when CGO is available
package factory
import "github.com/steveyegge/beads/internal/storage/dolt"
func init() {
RegisterBackend("dolt", func(ctx context.Context, path string, opts Options) (storage.Storage, error) {
return dolt.New(ctx, &dolt.Config{Path: path, ReadOnly: opts.ReadOnly})
})
}The architecture shift was elegant:
The First Failure
But we weren't done yet. The build still failed:
> go build ./cmd/bd/...
# github.com/dolthub/gozstd
undefined: DefaultCompressionLevelThe factory was fixed, but something else was still importing Dolt directly. A quick grep revealed the culprit:
> grep -r "storage/dolt" .
cmd/bd/init.go: "github.com/steveyegge/beads/internal/storage/dolt"The init command—the one that sets up new beads repositories—was directly importing and using the Dolt package. It needed to go through the factory instead:
// Before: Direct import
import "github.com/steveyegge/beads/internal/storage/dolt"
store, err = dolt.New(ctx, &dolt.Config{Path: storagePath})
// After: Factory pattern
import "github.com/steveyegge/beads/internal/storage/factory"
store, err = factory.New(ctx, backend, storagePath)Victory
> set CGO_ENABLED=0 && go build ./cmd/bd/...No output. In Unix philosophy, silence means success.
We verified it worked both ways:
> set CGO_ENABLED=0 && go build ./cmd/bd/... # Windows without C compiler
> set CGO_ENABLED=1 && go build ./cmd/bd/... # Systems with CGOBoth succeeded. The fix was complete.
The Pull Request
The PR went up with a clear explanation:
**Problem:** `go install` fails on Windows due to CGO dependency in dolt backend **Solution:** Use Go build tags to make the dolt backend conditional **Result:** SQLite backend (the default) works without CGO
Reflection
I contributed a meaningful fix to a Go project without knowing Go. Not a documentation fix. Not a typo correction. An actual architectural change involving build tags, registration patterns, and conditional compilation.
How? By treating the AI as a collaborator rather than a oracle. I didn't ask "fix this for me." I said "let's investigate" and "can we fix this?" The pronoun matters. We traced the dependency chain. We tried the first fix and watched it fail. We found the second import and fixed that too.
The AI brought Go expertise I lack. I brought context about how the tool is actually used, the patience to follow the investigation wherever it led, and the judgment about whether a fix was worth pursuing.
Some might argue this isn't "real" programming. That I didn't learn Go, I just had an AI write it for me. But I'd counter: I understood the problem deeply. I followed the architecture. I made decisions about approach. The syntax was delegated, but the engineering wasn't.
And now, the next Windows user who tries go install github.com/steveyegge/beads/cmd/bd@latest will just... have it work.
That feels like a contribution worth making.
Update: Merged
The PR was accepted. Steve Yegge's review:
"LGTM. Clean build tag approach for optional CGO dependency. Good error message for users who need dolt without CGO."
Sometimes the best validation isn't just that the code works—it's that someone who does know the language looked at what you produced and said "yeah, that's the right way to do it."
The bug report and pull request are public if you want to follow the full conversation.
