Small, framework-free Go modules extracted from go-tool-base — each independently versioned, dependency-inverted, and usable on its own.
Every module lives at gitlab.com/phpboyscout/go/<name> with its own docs at <name>.go.phpboyscout.uk. Import only what you need; pull no framework weight you don't. Provider and adapter modules sit under the module they serve.
New here? These are written up end to end, in the order they make sense: Building a command-line tool in Go · Building a web service in Go
Use a go-billy filesystem anywhere an afero one is expected — a complete adapter with optional locking that makes a live handle concurrency-safe.
Resolve, verify and cache approved artefacts from the estate channel — fetch by name and version, verify the signed manifest against embedded and WKD trust, get back a path. Reusable without the framework around it.
Transport-agnostic request authentication — API-key, JWT/OIDC, and mTLS verifiers, a verified identity, and a pluggable authorization predicate.
Resolve the AWS configuration a service client is built from — once and shared, or afresh per operation, as the caller chooses.
Resolve the Azure credential a service client is built from — once and shared, or afresh per operation, as the caller chooses.
A safe entry point for opening URLs — scheme allowlist, length bound, control-character rejection.
Turn a repository's Conventional-Commits history — or a release-notes archive — into a structured, categorised changelog. Generates via go-git and parses existing notes back into a typed model.
Multi-provider AI chat client — a ChatClient with a ReAct tool-calling loop, streaming, cross-provider fallback, and encrypted persistence. SDK-free core; opt into providers by blank import.
Providers
Anthropic Claude provider for chat. Its own module so a Claude-only tool never links the OpenAI or Gemini SDKs.
Google Gemini provider for chat. Its own module so only Gemini users link the genai SDK.
OpenAI & OpenAI-compatible provider for chat (Ollama, vLLM, Groq, …). Carries the OpenAI SDK and tiktoken; nothing else pays for them.
Receive, reply and moderate across chat platforms — with no vendor SDK in the core. Where chat talks to models, this talks to people: read a channel, reply in a thread, moderate, run slash commands, and swap Discord for Slack later without a second code path.
Providers
Discord provider for chat-platform: read channels, reply in threads, moderate and run slash commands. Blank-import it and reach it by name; your code never mentions Discord again.
Resolve a value that is expensive to build — exactly once, race-free, shared by every caller, and retried rather than cached if it fails. The general case the provider modules are built on, and nothing about it is cloud-specific: any client behind a costly SDK has this shape.
A hardened configuration container — hierarchical merge, safe hot-reload with last-known-good retention, typed sections and struct-tag validation behind one small interface. Rewritten off Viper into a Store that owns config I/O end to end.
Adapters
Adapt an afero filesystem to config's own FS interface, for consumers that already hold one.
Read configuration from any io/fs.FS — an embed.FS, a zip or tar — as a read-only layer. io/fs is read-only by design, so it adds no dependency at all.
Adapt a go-billy filesystem (as used by go-git) to config's FS interface — reads and writes through its native rename, with a read-only mount surfaced as ErrReadOnlyFS.
Read and write a configuration file on a remote host over SSH. Inject your own sftp.Client; atomic PosixRename commit where the server offers it, polled hot-reload at a calm default cadence.
Read and write a configuration file that lives in an AWS S3 bucket. Inject your own s3.Client; copy-then-delete commit with a findable staging key, optional key prefix, polled hot-reload at 60s.
Read and write a configuration file in a GCP Cloud Storage bucket. Inject your own storage.Client; a real server-side atomic Move commit — no orphan window — and polled hot-reload at 60s.
Read and write a configuration file in an Azure Blob Storage container. Inject your own azblob.Client (azidentity stays yours); synchronous copy-then-delete commit, polled hot-reload at 60s.
Read and write configuration from HashiCorp Consul's KV store — the first remote backend, with per-key merge, atomic compare-and-swap writes and blocking-query hot-reload. Inject your own Consul client; only Consul users carry its SDK.
A prefix of an etcd v3 cluster as an ordinary layer — real compare-and-swap writes and a real change feed behind hot reload.
Read AWS SSM Parameter Store as a config layer — path-prefix scoping, SecureString read decrypted under a sensitive layer so the leak guard protects it. Read-only (SSM has no compare-and-swap); poll-based hot-reload.
Read and write Azure App Configuration — per-key ETag compare-and-swap writes, label scoping, sentinel-key polled hot-reload. Inject your own client; only Azure users carry its SDK.
Read GCP Parameter Manager as a config layer — one parameter as a whole document, or a prefix of many parameters. Read-only; poll-based hot-reload. Inject your own client.
Read HashiCorp Vault KV v2 secrets as a config layer — one secret, or a whole prefix. Read-only and marked sensitive, so the core refuses to write a secret into a plainer layer beneath. Inject your own authenticated client.
Read AWS Secrets Manager as a config layer — a whole prefix in one request, or one secret as a JSON document. Read-only and marked sensitive, so the core refuses to write a secret into a plainer layer beneath. Five modules: the leanest backend adapter here.
Read secrets from Azure Key Vault as a config layer. You build the client — vault URL and credential both — and hand it in, so only Key Vault users carry the SDK.
Read secrets from Google Cloud Secret Manager as a config layer. Weigh the dependency cost first: it pulls 39 modules, five times the AWS or Azure equivalent and the heaviest module in this toolkit — though if you already talk to any Google API you have substantially all of it.
Make the OS keychain a config layer, so tokens are stored there rather than in a plaintext config file. Read and write — a first token routes into the keychain, and one already there can never be written to the file beneath.
Read a directory of single-value files as a config layer — a mounted Kubernetes ConfigMap, Docker secrets, or systemd credentials, where each filename is a key. Handles the atomic-writer layout a naive directory listing turns into phantom keys, and adds no dependency at all.
Read dotenv (.env) through config's codec seam — keys nest on underscores, values are literal (no ${VAR} interpolation). Read-only, and adds no dependency at all.
Read and write HCL through config's codec seam — blocks and labels as path segments, comment-preserving edits via hclwrite. HCL as configuration, not Terraform: external variables and functions are refused at load.
Read INI through config's codec seam — [section] headers and dotted keys nest as section.key. Read-only, and adds no dependency at all.
Read and write JSON and JSON Lines through config's codec seam, structure-preserving — an edit changes one value and leaves key order and formatting intact.
Read Java .properties through config's codec seam — dotted keys nest, with the format's separators, escapes and line continuation. Read-only, and adds no dependency at all.
Read and write TOML through config's codec seam — tables as nested keys, arrays of tables as slices, and structure-preserving edits (comments and key order survive) via go-toml's source ranges.
Read XML through config's codec seam — attributes and elements in one namespace, repeated elements as slices. Read-only, and adds no dependency at all.
JSON Schema validation over the store — compose partial schemas per section, and get each failure attributed back to the layer that supplied the offending value.
Service-lifecycle supervisor — startup ordering, health probes, graceful shutdown, self-healing restarts.
Storage-mode abstraction for user-supplied secrets — env-var reference, OS keychain, or literal — behind a pluggable backend with an auditable keychain opt-out.
Check a tool's documented command examples against its real command tree, so a renamed flag fails a pipeline instead of quietly misleading a reader.
OpenPGP session-key recovery and certificate assembly for keys you cannot read — a KMS, an HSM, a smartcard. The RFC 6637 derivation, the RFC 3394 unwrap, packet framing and fingerprints. Standard library only, asserted by a test.
Key service
AWS KMS key service for encryption — DeriveSharedSecret for ECDH and a crypto.Signer for certification. Its own module so consumers that don't use KMS never inherit the AWS SDK.
Structured error reporting for CLIs — actionable hints, exit codes carried on the error value, debug-gated stack traces, and a pluggable support channel.
The error package the estate owns: stack traces, user-facing hints, structured attributes for logging, and an aggregate that behaves like the standard library's, so nothing goes missing below a Join. It imports nothing outside the standard library.
Forge release operations behind one contract — a provider registry, release types and a credential chain for GitHub, GitLab, Gitea, Codeberg, Bitbucket and plain download sources. Your code depends on forge.Provider, never a vendor client, and the core imports no forge SDK at all. Ships a conformance harness so a third-party provider can prove it honours the protocol.
Providers
Bitbucket release provider for forge — implements forge.Provider over the Bitbucket Downloads API.
Gitea and Codeberg release provider for forge, over the official gitea SDK.
GitHub release provider for forge (github.com and Enterprise), over go-github.
GitLab release provider for forge, over the official client-go.
Resolve the Google Cloud credential and hand it back as client options. GCP is the provider where building the service client is not free, so the seam stops one step earlier and the client stays yours to build and close.
A light, framework-free gRPC client dial factory — a decoupled Target, go/tls credentials, and the transit client interceptors, wired onto the gRPC SDK.
A hardened, framework-free *http.Client factory — secure TLS defaults, downgrade-proof redirects, and the transit retry/circuit-breaker/auth middleware.
A framework-free local development CA — on first run it mints a per-machine root, installs it into the OS & browser (NSS) trust stores, and issues short-lived leaf certs for localhost/LAN hosts, so any transport serves browser-trusted HTTPS with zero manual setup. Emits a tls pair.
NATS as an estate convention — a controls-managed embedded server, and a client that is the same code whether the broker is in this process or a cluster somebody else runs.
Hardened OpenTelemetry setup — OTLP logs, metrics, and traces from one typed config, with graceful OTEL_* env fallback.
Resolve the ONNX Runtime shared library — pick the platform's archive from the estate artefact channel, extract the library, cache it.
Structured, themeable output for CLI tools — one Renderer facade for text, JSON, YAML, CSV, TSV and Markdown, plus tables, spinners, progress bars and status lines. Framework-free core, opt-in cobra subpackage.
Strip credential-like content from free-form strings before they reach logs or telemetry.
Bounded, DoS-safe regex compilation for patterns from untrusted sources.
Git repository operations over go-git — clone, commit, branch, worktrees and tree inspection — behind focused role interfaces, with interchangeable in-memory and filesystem backends. Authenticates to GitHub, GitLab, Bitbucket and Gitea while importing none of them: no forge SDK enters your dependency graph.
OpenPGP/WKD release signing & verification. A light crypto.Signer-based backend contract, the signing mechanics, and the verification trust model — no framework, no cloud SDK.
Backend
AWS KMS signing backend for signing — a KMS-held key as a crypto.Signer. Its own module so consumers that don't sign with KMS never inherit the AWS SDK.
Hardened, framework-free TLS plumbing — a curated default config (TLS 1.2 floor, AEAD suites), typed cert pairs, and server/client builders.
Shared HTTP & gRPC transport middleware — structured logging, OpenTelemetry, circuit breaking, rate limiting and client retry, framework-free.
A framework-free HTTP + gRPC + gateway server stack — hardened server constructors, health endpoints, authentication and security headers, on go/controls + go/authn + go/transit + go/tls.
Cardinality-safe Prometheus instrumentation — a scrapeable /metrics endpoint (Go runtime, process and build-info collectors), optional pprof, mounted on your server or standalone. The pull/scrape counterpart to the OTel observability module.
Serve an OpenAPI spec and an interactive Stoplight Elements docs site from one Register call, mounted on the transport mux. Keeps the ~2.4 MB embedded docs UI out of servers that don't need it.
Resolve the Vault client an adapter talks to — once and shared, or afresh per operation. With Vault the client is the connection prerequisite, carrying address, namespace, token and retry policy together, so there is no separate config object to hand on.
Find a project's root by walking up from a starting directory to a marker file (go.mod, .git, a manifest) — over an injected afero filesystem, so the walk stays fully testable in memory.
Edit a YAML document without destroying it — comments, key order, quoting and block styles survive a targeted change. Built for config, useful on its own.
go-tool-base's reusable packages are being extracted into this subgroup one at a time — the transport stack (httpclient, grpcclient, transport) and the config family (config, yamldoc, config-afero) have landed alongside the foundations (tls, authn, transit, observability, controls).