Updates
Check and Install
Check the latest public version without changing the installation:
ecctl update --check
Install it:
ecctl update
Both commands return structured output showing the current version, target version, whether an update is available, and whether installation completed or is still pending.
Failures use stable update error codes and a retryable flag. The localized
message is suitable for display, while detail retains the diagnostic cause
for troubleshooting and automation.
To select a release explicitly, pass an unprefixed semantic version. A
downgrade or same-version reinstall requires --force:
ecctl update 0.2.0
ecctl update 0.2.0 --force
Homebrew installations can only select the latest stable release. Direct binary installations can select an available historical or prerelease version.
Validation and Installation
For releases that publish the updater v2 protocol, OSS is the primary update
source. For the latest stable release, ecctl reads the OSS version.txt
pointer and then downloads that version's manifest and Sigstore bundle. For an
explicit version, ecctl goes directly to that version's manifest and does not
consult the latest-version pointer. The version directory and signed manifest
version identify an explicit release; no /<version>/version.txt object is
required.
The Sigstore bundle is verified locally against trust roots embedded in ecctl.
The accepted certificate is restricted to GitHub Actions' OIDC issuer and this
repository's .github/workflows/release.yml workflow on main or a matching
SemVer release tag. Verification
does not contact GitHub, Sigstore, Rekor, or another online service. Only after
the raw manifest signature and identity pass does ecctl parse the manifest,
validate checksums.txt, and verify the selected archive's SHA-256 digest and
size.
Availability and integrity failures are handled differently:
- If OSS is unreachable, returns a missing asset, or ends an otherwise valid response early, ecctl can use the compatible immutable GitHub Release path.
- An invalid bundle, unexpected signing identity, malformed manifest, or checksum, size, or archive mismatch is an integrity failure. ecctl stops and does not fall back to another source.
Historical releases without a v2 manifest continue to use immutable GitHub Release metadata as the trust source while preferring OSS for matching asset bytes. A validation failure always stops the update without installing untrusted or incomplete files.
This protocol protects release authenticity and artifact integrity, not mirror availability or absolute freshness. A mirror can still withhold a newer release or keep serving the highest valid release a client has already seen. ecctl detects a rollback below its previously verified stable-version high-water mark, but it cannot prove that no unseen newer release exists.
For direct installations on macOS and Linux, ecctl replaces the executable only after validation and restores the previous executable if post-installation validation fails. An interrupted update is checked and recovered the next time you explicitly run an update command.
On Windows, the running executable cannot be replaced in place. ecctl starts a
helper and returns update_pending: true with updated: false; replacement
continues after the update command exits. A later explicit ecctl update
reports any incomplete or failed replacement. Releases older than the first
self-updating Windows build must be installed manually.
Clients released before updater v2 cannot use the signed OSS-only path and may still fail when GitHub's API is unavailable. Install or reinstall the first ecctl release that contains updater v2 using the documented package, Homebrew, or direct-download installation method. Very old updater v2 clients may also need this bootstrap procedure after a future Sigstore trust-root rotation that does not overlap their embedded roots.
Homebrew Installations
When ecctl detects a supported Homebrew-managed installation, ecctl update
updates it through the matching Homebrew installation. You do not need to run
brew update first.
--force reinstalls the current stable version. If the Homebrew installation
cannot be identified safely, the update stops with an error instead of
overwriting a managed executable directly.
Automatic Version Checks
Operational commands periodically check whether a newer stable version is available. This advisory check never blocks the requested command. Notices are written only to an interactive terminal on stderr, at most once per version per day, so JSON stdout remains unchanged.
Automatic checks use the same signed v2 resolution or immutable GitHub fallback
as an explicit update check. The cache stores only
verified_latest_version and never replaces it with a lower verified version.
The older unsigned latest_version cache field is ignored after upgrading.
Skip automatic checks in controlled or offline environments:
export ECCTL_DISABLE_UPDATE_CHECK=1
Automatic checks also apply to help, version, completion, and update invocations.