
A Go client library for the Homebrew Formulae API. No authentication required — the API is public and read-only. Includes a production-ready transport with retries, adaptive rate limiting, concurrency control, structured logging, and optional OpenTelemetry tracing.
Quick Start
go get github.com/deploymenttheory/go-sdk-brew
import (
"context"
"fmt"
"log"
brew "github.com/deploymenttheory/go-sdk-brew/brew"
"github.com/deploymenttheory/go-sdk-brew/brew/services/analytics"
)
func main() {
client, err := brew.NewClient("") // defaults to https://formulae.brew.sh
if err != nil {
log.Fatal(err)
}
ctx := context.Background()
// List all formulae
formulae, _, err := client.Formulae.List(ctx)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total formulae: %d\n", len(formulae))
// Get a formula by name
wget, _, err := client.Formulae.GetByName(ctx, "wget")
if err != nil {
log.Fatal(err)
}
fmt.Printf("wget %s: %s\n", wget.Versions.Stable, wget.Desc)
// Install analytics for the last 30 days
stats, _, err := client.Analytics.ListByCategory(ctx, analytics.CategoryInstall, analytics.Period30d)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Top formula: %s (%s installs)\n", stats.Items[0].Formula, stats.Items[0].Count)
}
API Coverage
The SDK covers all endpoints of the Homebrew Formulae API:
| Method |
Endpoint |
Description |
List(ctx) |
GET /api/formula.json |
All Homebrew formulae |
GetByName(ctx, name) |
GET /api/formula/{name}.json |
Single formula by name |
Casks (client.Casks)
| Method |
Endpoint |
Description |
List(ctx) |
GET /api/cask.json |
All Homebrew casks |
GetByName(ctx, name) |
GET /api/cask/{name}.json |
Single cask by name |
Analytics (client.Analytics)
| Method |
Endpoint |
Description |
ListByCategory(ctx, category, period) |
GET /api/analytics/{category}/{period}.json |
Ranked install analytics (items array) |
ListCoreByCategory(ctx, category, period) |
GET /api/analytics/{category}/homebrew-core/{period}.json |
homebrew-core analytics (formulae map) |
ListCaskInstalls(ctx, period) |
GET /api/analytics/cask-install/homebrew-cask/{period}.json |
Cask install analytics (formulae map) |
Analytics categories: analytics.CategoryInstall, analytics.CategoryInstallOnRequest, analytics.CategoryBuildError
Analytics periods: analytics.Period30d, analytics.Period90d, analytics.Period365d
Examples
The examples directory contains a working example demonstrating all three services:
Configuration Options
Creating a client
import brew "github.com/deploymenttheory/go-sdk-brew/brew"
// Default base URL (https://formulae.brew.sh)
client, err := brew.NewClient("")
// Custom base URL
client, err := brew.NewClient("https://formulae.brew.sh")
// With options
client, err := brew.NewClient("",
brew.WithTimeout(30*time.Second),
brew.WithRetryCount(3),
brew.WithLogger(logger),
)
Available options
All configuration is passed via functional options to NewClient.
Basic Configuration
brew.WithBaseURL("https://formulae.brew.sh") // Override base URL
brew.WithTimeout(30*time.Second) // Request timeout (default: 30s)
brew.WithRetryCount(3) // Retry attempts on transient errors (default: 3)
brew.WithRetryWaitTime(2*time.Second) // Initial retry wait (default: 2s)
brew.WithRetryMaxWaitTime(30*time.Second) // Max retry wait with backoff (default: 30s)
brew.WithTotalRetryDuration(2*time.Minute) // Total retry budget across all attempts
TLS / Security
brew.WithTLSClientConfig(tlsConfig) // Custom *tls.Config
brew.WithInsecureSkipVerify() // Skip TLS verification (dev only)
Network
brew.WithProxy("http://proxy.example.com:8080") // HTTP/HTTPS/SOCKS5 proxy
brew.WithTransport(customTransport) // Custom net/http Transport
brew.WithUserAgent("MyApp/1.0") // Set User-Agent
brew.WithGlobalHeader("X-Custom", "value") // Add a single global header
brew.WithGlobalHeaders(map[string]string{...}) // Add multiple global headers
Observability
brew.WithLogger(zapLogger) // Structured logging with go.uber.org/zap
brew.WithDebug() // Verbose request/response logging (dev only)
OpenTelemetry tracing is configured at the transport level via brew.WithTransport. Wrap your existing transport with otelhttp.NewTransport before passing it in, or use brew.WithOpenTelemetry if enabled in your build.
Concurrency & Rate Limiting
brew.WithMaxConcurrentRequests(10) // Max parallel in-flight requests (default: 10)
brew.WithMandatoryRequestDelay(50*time.Millisecond) // Fixed delay between requests
The transport also applies an EMA-based adaptive delay automatically when API response times degrade.
Example: Production Configuration
import (
"time"
"go.uber.org/zap"
brew "github.com/deploymenttheory/go-sdk-brew/brew"
)
logger, _ := zap.NewProduction()
client, err := brew.NewClient("",
brew.WithTimeout(30*time.Second),
brew.WithRetryCount(3),
brew.WithRetryWaitTime(2*time.Second),
brew.WithRetryMaxWaitTime(30*time.Second),
brew.WithMaxConcurrentRequests(10),
brew.WithLogger(logger),
brew.WithUserAgent("my-app/1.0"),
)
Response Shape
All service methods return (result, *resty.Response, error):
formula, resp, err := client.Formulae.GetByName(ctx, "wget")
if err != nil {
// Handle error — includes API errors (404, 500, etc.) and network errors
}
fmt.Println(resp.StatusCode()) // 200
fmt.Println(formula.Name) // "wget"
fmt.Println(formula.Versions.Stable)
fmt.Println(formula.Dependencies)
Analytics response shapes
The three analytics endpoints return different Go types because the Homebrew API uses different JSON shapes for each:
// General analytics: ranked items array
result, _, _ := client.Analytics.ListByCategory(ctx, analytics.CategoryInstall, analytics.Period30d)
for _, item := range result.Items {
fmt.Printf("#%d %s — %s installs (%s%%)\n", item.Number, item.Formula, item.Count, item.Percent)
}
// homebrew-core: formulae map (formula name → []CoreFormulaItem)
core, _, _ := client.Analytics.ListCoreByCategory(ctx, analytics.CategoryInstall, analytics.Period30d)
for name, entries := range core.Formulae {
fmt.Printf("%s: %s installs\n", name, entries[0].Count)
}
// Cask installs: formulae map (cask token → []CaskInstallItem)
casks, _, _ := client.Analytics.ListCaskInstalls(ctx, analytics.Period30d)
for token, entries := range casks.Formulae {
fmt.Printf("%s: %s installs\n", token, entries[0].Count)
}
Testing
# Unit tests (no network required — fixture-based mocks)
go test ./brew/services/...
# Acceptance tests (hits live https://formulae.brew.sh)
go test -v ./brew/acceptance/... -timeout 120s
# Optional env vars for acceptance tests
BREW_BASE_URL=https://formulae.brew.sh # override API base URL
BREW_REQUEST_TIMEOUT=30s # per-test context timeout
BREW_VERBOSE=true # enable detailed logging
Documentation
Contributing
Contributions are welcome. Please read our Contributing Guidelines before submitting pull requests.
License
This project is licensed under the MIT License — see the LICENSE file for details.
Support
Disclaimer
This is a community SDK and is not affiliated with or endorsed by the Homebrew project.