ubgo is in early alpha: libraries and APIs may still change.

Skip to content
ubgo Alpha

Volt, now part of ubgo

Build, release and ship Go CLIs, in any repo layout.

Volt is the layer on top of ubgo. The volt tool scaffolds a CLI, runs the CI gate, builds for every platform and makes tagged releases it checks after publishing. The kit modules give your CLI the parts every CLI needs, one go get at a time.

brew install khanakia/tap/volt
a release, end to end
$ volt status
# what needs releasing?
$ volt release ./cmd/notes --bump patch
testing cmd/notes
reserved tag notes/v0.2.1
built notes_v0.2.1_darwin_arm64.tar.gz ... (5 platforms)
released notes/v0.2.1 — 6 asset(s), verified
From the voltkit README, "A release, end to end".

Where Volt sits

ubgo libraries are the parts your code runs on. Volt is the tooling that turns your code into a released, installable program. Your app sits on top of both.

3 · Your app

A CLI, a library or a service

mytool (volt new cli)your libraryyour service app starters are coming

2 · Volt tooling

voltkit →

The Volt tool

volt newvolt statusvolt civolt covervolt buildvolt releasevolt gen

Kit modules you import

appdiroutputskillcmdversioncmd

Real link: voltkit's versioncmd module requires ubgo/buildinfo in its go.mod.

The Volt tool

Every command, as the voltkit README lists it. Latest release of the tool: volt/v0.3.1.

volt new cli <name>

Scaffold a CLI from the volt-cli templates (--template cobra, --list).

volt status

Per-stream release state: last tag, commits since, suggested next version.

volt ci [dir]

The gate: gofmt, vet, golangci-lint with an embedded config, race tests. Changed modules by default; --fix applies auto-fixes.

volt cover [dir]

Coverage per module and a statement-weighted total. --badge writes a README badge, --check fails when it is stale, --min sets a CI floor.

volt build <dir> --version vX.Y.Z

Cross-compile matrix into archives and checksums.txt; the version stamp is checked in the built binary.

volt release <dir> <version>

Tests, reserve the tag, build, publish, then verify the published artifact. --bump, --snapshot, --from-tag.

volt gen

Write workflow stubs and install scripts. Hand-edited files are refused with a diff, never overwritten.

volt doctor

Is this repo releasable? Tools, auth, remote, version-pin drift.

volt upgrade

Re-apply template changes to a scaffolded project with a three-way merge, so your edits survive.

Also volt gen install, volt gen skills and volt update. Full list in the voltkit README.

One tag rule for every layout

Libraries tag by directory path, because that is the only shape the Go module proxy resolves. CLIs tag by binary name. A repo that holds one thing tags bare. The same rule works for a single CLI, a library, a monorepo of CLIs and mixed repos.

v1.4.0                 the repo root
notes/v1.4.0           a CLI at cmd/notes (tag = binary name)
pkg/textutil/v0.1.0    a library submodule (tag = directory path)

From the voltkit README, "The tag grammar".

See it on a real monorepo

volt-demo-clis holds two CLIs, a root library and nested libraries. volt status shows every releasable stream and only those:

$ volt status
.                library  v0.1.0    up to date
cmd/notes        cli      v0.2.0    up to date
cmd/snap         cli      v0.1.0    up to date
pkg/mathx        library  v0.1.0    up to date
pkg/textutil     library  v0.1.0    up to date

From the volt-demo-clis README. pkg/testutil is marked internal: true, so it is tested but never listed or released.

The kit: parts every CLI needs

Each is its own module with its own tag, so a CLI adopts them one at a time and picks up fixes with go get -u.

versioncmd

v0.2.1

A ready-made version subcommand with build provenance.

root.AddCommand(versioncmd.New(versioncmd.WithBinaryName("mycli")))

output

v0.2.0

The stable JSON envelope every command's --json emits.

output.JSON(os.Stdout, "notes.list", notes, len(notes))
// → {"schema_version":1,"kind":"notes.list","count":2,"data":[...]}

appdir

v0.2.0

Where state lives, resolved by policy and never hardcoded; it reports which rule decided.

paths, _ := appdir.Resolve(meta)

From the voltkit README, "The kit". Also skillcmd: a skills subcommand that serves the project's published skills, matched to the binary's version.

Start a CLI

volt-cli holds the templates. They are fetched at a pinned tag, never main, so a bad commit there cannot break scaffolding.

$ volt new cli mytool                      # minimal
$ volt new cli mytool --template cobra
$ volt new cli --list
VariantGives you
minimalstdlib-only CLI: flag parsing, version stamping, zero dependencies
cobracobra root command with --version

From the volt-cli README.

Run it in CI

volt-action installs the released Volt binary, checksum-verified, and runs one command. It has no logic of its own; the pipeline lives in the binary.

- uses: ubgo/volt-action@v1
  with: { args: ci }

From the volt-action README. A release hook can stop a release before anything is created, as the volt-demo-clis README shows:

$ RELEASE_BLOCKED=1 volt release ./cmd/notes --bump patch
hook pre_release: ./scripts/release-gate.sh
gate: releases are blocked (RELEASE_BLOCKED=1) — refusing notes/v0.2.1
Error: pre_release hook refused the release — nothing was tagged

The Volt repos

The demos are real repos released with Volt, and Volt is tested against them.

App starters are coming.