Documentation
¶
Overview ¶
Package version — daemon-side periodic update poller. Every `Interval` ticks (default 1h) the poller calls `CheckForUpdate`; when a transition from no-update → update-available is detected it broadcasts a SystemNotification onto the supplied publisher (typically biam.WatchHub.BroadcastSystem). Connected watchers — orchestrator, dashboard, `task watch`, MCP clients dialling the watch socket — render the inline banner immediately, no polling.
Why daemon-side rather than per-CLI: the CLI is short-lived; the daemon (`clawtool serve`) is the long-running process the operator already keeps up. One canonical poller, single GitHub round-trip per host per hour, push to every active surface.
Telemetry: each transition emits a `clawtool.update_check` event with the same allow-listed payload SessionStart uses, so the operator gets a unified PostHog view of update detection across surfaces.
Package version — update-check primitive. Hits the GitHub Releases API for the latest tag and reports whether the local build is older. Cached for 24h in ~/.cache/clawtool/update.json so a `clawtool doctor` (or any other surface that calls CheckForUpdate) doesn't pay a network roundtrip on every invocation.
No background polling, no telemetry — this is a stateless, user-initiated check. The cache exists purely to avoid being rude to the GitHub API.
Package version exposes the clawtool build version.
Three layers, picked in order:
ldflags override — `go build -ldflags='-X github.com/cogitave/clawtool/internal/version.Version=v…'`. goreleaser sets this on every release tarball, so installed binaries always carry the exact tag.
runtime/debug.ReadBuildInfo — module-cached `go install` binaries surface the tag here. Local `go build` from a working tree returns "(devel)".
The release-please-tracked constant below — fallback for dev workflows where neither (1) nor (2) yields a real version.
`Resolved()` is the single function every caller (overview, upgrade, claude-bootstrap, telemetry) must use to read the effective version. Reading `Version` directly (the constant) will diverge from what the binary actually is when goreleaser stamped a different value via ldflags.
Index ¶
Constants ¶
const Name = "clawtool"
x-release-please-start-version
const UpdateCheckURL = "https://api.github.com/repos/cogitave/clawtool/releases/latest"
UpdateCheckURL is the GitHub Releases API endpoint we hit. The public API permits ~60 unauthenticated requests/hour per IP; the 24h cache keeps us well under that even on shared CI runners.
Variables ¶
var Version = "0.21.7" // x-release-please-version
Version is the build-stamped semver string. Declared as `var` (not `const`) so goreleaser can override it via `-ldflags='-X github.com/cogitave/clawtool/internal/version.Version=…'` at link time. `-X` cannot patch constants; that's why this is a var even though it's effectively immutable at runtime.
Functions ¶
func Resolved ¶ added in v0.22.8
func Resolved() string
Resolved returns the authoritative installed-binary version. First-call computation is cached for the process lifetime — the binary's version doesn't change while it's running.
Output strips any leading "v" so callers can pass it straight into Compare() without normalising at every call site.
Types ¶
type Poller ¶ added in v0.22.9
type Poller struct {
// contains filtered or unexported fields
}
Poller wraps the periodic update probe + publisher. Lifetime = daemon process. Stop via ctx cancellation.
func NewPoller ¶ added in v0.22.9
func NewPoller(pub PublishFn, cfg PollerConfig, track func(outcome string)) *Poller
NewPoller constructs the poller with the given publisher and optional telemetry tracker. `track` is called on every check with the outcome enum ("up_to_date" | "update_available" | "check_failed"); pass nil to skip telemetry.
type PollerConfig ¶ added in v0.22.9
type PollerConfig struct {
// Interval between checks. Default 1h. Tests pass 50ms.
Interval time.Duration
// Timeout per HTTP round-trip. Default 5s.
Timeout time.Duration
// Now overrides time.Now for deterministic testing of
// transitions. Production passes nil.
Now func() time.Time
}
PollerConfig overrides the defaults — useful for tests that need a tighter tick. Empty struct = production defaults.
type PublishFn ¶ added in v0.22.9
type PublishFn func(kind, severity, title, body, actionHint string)
PublishFn is the slim function shape the poller needs from the caller. server.go wraps biam.WatchHub.BroadcastSystem; tests pass a recorder closure. Keeping this as a function instead of an interface avoids dragging biam into the version package's import graph (version stays a leaf).
type UpdateInfo ¶ added in v0.9.0
type UpdateInfo struct {
// HasUpdate is true when the upstream tag is newer than the
// local build. Defaults to false on any error so we never nag
// the user about a non-confirmed update.
HasUpdate bool
// Latest is the tag string from GitHub (e.g. "v0.10.0"). Empty
// on error.
Latest string
// Current is the local build version (Version package var).
Current string
// FetchedAt is when we last asked GitHub. Surfaced so the user
// knows how stale the answer is. UTC.
FetchedAt time.Time
// Err is non-nil when the check itself failed (network, parse,
// rate-limit). Callers display "could not check" instead of
// pretending no update exists.
Err error
}
UpdateInfo is the result a caller surfaces in the UI.
func CheckForUpdate ¶ added in v0.9.0
func CheckForUpdate(ctx context.Context) UpdateInfo
CheckForUpdate is the entry point. Returns the cached result when fresh; otherwise hits the API, persists, returns. Never blocks longer than the HTTP client's timeout.