Documentation menu

Maintaining Flog

Installer and release channels

scripts/install is flog's canonical POSIX installer. https://flog.run/install serves that file byte-for-byte; the website does not copy or reimplement it. For executable self-updates, see the flog update command reference.

Once an initial public stable Release is promoted, the normal command is:

curl -fsSL https://flog.run/install | sh

The script supports Linux and macOS on amd64 and arm64. It requires curl, tar, awk, tr, wc, cmp, standard file utilities, and either sha256sum or shasum. It installs to $HOME/.local/bin/flog by default. If that directory is not already on PATH, it appends a literal PATH line to existing writable, regular shell profiles. For Bash, each existing .bashrc and .bash_profile is handled independently so both non-login and login shells receive the setup without assuming that one file sources the other. Zsh uses .zshrc, and fish uses config.fish. Existing equivalent lines, marked or unmarked, are left alone. If a profile is unsafe or cannot be edited, the installer prints manual instructions for that file. A custom FLOG_INSTALL_DIR is never interpolated into profile shell code. Profile updates happen only after a successful installation; the installer never uses sudo or guesses a privileged destination.

Like Bun's installer, the profile update is an append, not an atomic no-follow operation. Checks reject symlinks that are present when inspected, but a symlink swapped in just before the append could redirect the write. Concurrent regular-file edits are not replaced, although simultaneous PATH edits may still produce duplicate lines. Avoid piping the installer into a shell in an environment where another process can alter your profile files.

Installer controls#

  • FLOG_INSTALL_DIR=/absolute/path selects an explicit destination.
  • FLOG_VERSION=1.2.3 installs one exact historical or prerelease version. It still performs version-2 discovery first so the canonical project key is known before constructing the exact version URL; it does not select a mutable channel tip.
  • FLOG_CHANNEL=next selects a channel advertised by public Release discovery. A successful nondefault selection stores the channel's durable numeric ID; selecting the current default clears that override. Without an override, the installer follows the current discovered default. If discovery declares no default, an explicit channel is required. A channel cannot be combined with FLOG_VERSION.
  • FLOG_CONFIG=/absolute/path/config.toml overrides the per-user config path. The default is os.UserConfigDir()/flog/config.toml (normally $XDG_CONFIG_HOME/flog/config.toml or $HOME/.config/flog/config.toml on Linux, and $HOME/Library/Application Support/flog/config.toml on macOS). Put an override inside a dedicated user-owned directory; the installer restricts that directory to mode 0700 and refuses a root-level config.
  • FLOG_RELEASES_URL=https://mirror.example/releases selects a compatible manifest origin.
  • FLOG_ALLOW_HTTP=1 permits HTTP for isolated local tests. Production use must retain HTTPS; without this opt-in, HTTP manifests, artifacts, and redirect targets are rejected.

Discovery and manifest protocol#

New installs and self-updates fetch strict schema-versioned JSON from https://repopack.com/api/v0/projects/flog/releases/products/flog/channels?version=2. Schema repopack.release.channels version 2 declares the canonical project key, identity_required_after, a numeric or null default_channel, and channel entries containing a durable numeric id, mutable name, release or rolling kind, and a canonical same-origin absolute or origin-relative url. The temporary project_ref compatibility field is not used for identity or URL construction. Duplicate, missing, malformed, and ambiguous canonical identity fields are rejected. The POSIX installer parses this JSON with dependency-free AWK; it does not use jq, Python, Node, eval, or sourced shell code.

The selected URL contains the canonical project key and numeric channel identity. Release channels use /channels/id-<id>; rolling channels use /channels/id-<id>/rolling/<job>. No legacy ?identity= query is added. Channel renames therefore do not redirect a saved choice to a different channel. A missing saved ID fails closed, and an explicit old name that has been reused by a different ID is refused.

Public channel and exact-Run records are strict Repopack JSON. The clients reject duplicate or conflicting identity fields, verify Release lifecycle/tag/source or rolling Run/source identity, and map the selected target into the existing audited Release/rolling model. Conceptually, a selected Release contains:

flog-release-v1
version	1.2.3
revision	0123456789abcdef0123456789abcdef01234567
artifact	darwin	amd64	<64-character-sha256>	<immutable-https-url>
artifact	darwin	arm64	<64-character-sha256>	<immutable-https-url>
artifact	linux	amd64	<64-character-sha256>	<immutable-https-url>
artifact	linux	arm64	<64-character-sha256>	<immutable-https-url>

Release records require all four supported targets, an exact semantic version, a full source commit, one unique artifact per target, and one SHA-256 checksum and byte size per artifact. Artifact URLs identify one immutable Release version under the discovered project key. Rolling artifacts identify one exact Run as /channels/id-<id>/rolling/<job>/runs/<run>/artifacts/<file>.

Rolling development builds map to the separate flog-rolling-v1 contract. It identifies the fixed Flog product, discovered channel name and ID, Job, one exact Run, source ref and full source SHA, canonical 0.0.0-dev.<12-character-SHA-prefix> version, and all four target archives with byte sizes, SHA-256 digests, and identity-pinned temporary Run URLs. The client requires the rolling Job name to equal the source ref. It also downloads the Run's SHA256SUMS, verifies that artifact's declared size and digest, and requires its exact four lines to match the archive metadata. The client refetches <channel-url>/runs/<run> immediately before replacement. Rolling manifests are not Releases: they have no tag, version_url, lifecycle, or permanent artifact URL.

Installation safety#

The installer resolves a Release channel to an immutable version manifest, or selects one exact rolling Run. It downloads into a mode-0700 staging directory located inside the destination directory, verifies the archive's SHA-256 checksum, requires the exact archive entries BUILD-INFO.json, LICENSE, and flog, and streams only the flog entry into the staged executable. The final rename occurs on the same filesystem and is the only operation that replaces an existing installation. All installs verify the declared byte size and all BUILD-INFO.json identity fields. Rolling installs additionally refetch the exact-Run manifest. A newer Run becoming current cannot change the selected download; eviction, a new Release hold, or changed evidence makes the operation fail before replacement.

Network errors, all redirects, malformed manifests, missing targets, checksum failures, malformed archives, interrupted downloads, and destination errors remove staging data and preserve an existing executable. Repeating the same version installation produces the same installed bytes.

Repopack Release adapter#

Job #3's automatic master Runs produce project-visible SHA-versioned development artifacts for rolling unstable; they do not create Releases or channel promotions. For a semantic release, manually run Job #1 from the exact full source SHA with an explicit version as documented in releases.md, then download its artifacts and verify SHA256SUMS.

Repopack Release is the sole authority for published versions, artifact URLs, visibility, lifecycle, channel discovery, and channel tips. New clients discover and require the canonical flog project key, then read records for the fixed flog product:

https://repopack.com/api/v0/projects/flog/releases/products/flog/channels?version=2
https://repopack.com/api/v0/projects/flog/releases/products/flog/channels/id-2
https://repopack.com/api/v0/projects/flog/releases/products/flog/versions/<version>

Discovery supplies the durable IDs and identity-pinned channel URLs used by the installer and updater. The returned channel records validate public lifecycle, exact product and version/Run identity, full source SHA, and exactly one archive for every supported target. Archives remain hosted by Repopack and are never copied into the website.

Anonymous clients can read public records. An authorized client transport may read project-visible records, but neither the website nor POSIX installer embeds a token, sends browser cookies, or silently retries invalid credentials as anonymous. A public-to-project visibility change, missing authorization, withdrawal, rolling eviction, or revoked (410) resource fails closed. Deprecated (299) Releases remain downloadable and produce a warning. Invalid or expired credentials remain failures. Channel and exact-version responses use no-store, so promotion and revocation are not hidden by a long-lived website cache. Exact-version requests address the immutable Release version directly and therefore continue to work after a later stable promotion.

The rolling adapter likewise fails closed for a private, empty, stale, Release-held, evicted, malformed, or ambiguous Run. It anonymously reads only a public rolling listing and exact Run; the website contains no Repopack credential. Rolling Runs remain mutable, temporary evidence and never become immutable Releases.

The Go, POSIX and website implementations share one documented protocol abstraction: version-2 discovery pins canonical key, product, numeric channel, kind and rolling Job; project_ref is compatibility-only, and every returned URL is checked for the same origin and exact canonical path before use. The fixtures in internal/releasechannel and web/test/fixtures/releases exercise the same four targets and identity shapes. Non-conflicting metadata may be added, but duplicate keys and identity changes are rejected.

Requests reject redirects and re-fetch discovery and mutable records rather than treating an old response or ETag as continuing authorization. Flog does not use a 304 without locally retained, freshly authorized evidence. Repopack may return an ETag, but Flog currently requests revalidation and consumes a complete response for each operation.

Legacy /project/<project>/releases/... projections remain a compatibility boundary for already-deployed clients and the unchanged Flog-facing channels.v1, manifest.v1, and rolling.v1 routes. Those routes intentionally continue projecting legacy artifact URLs that deployed parsers validate. New installer and updater code never generates or follows those aliases, and the website never uses them for its upstream reads. Deployment must ship the reviewed Flog client and website adapters first, retain the compatibility routes, and then perform read-only anonymous stable, unstable, and exact-version smoke checks. Alias removal or a cutoff recommendation belongs to a later separately approved Repopack rollout; this migration does not authorize one.

Publishing and promoting#

Publication, channel membership and tip promotion are guarded Release operations, not website, installer, build Job or ordinary deployment actions. The permanent flog product and stable channel already exist. For a normal stable release, first verify the channel exists and is public, then use one guarded publication with --promote-to stable after a read-only preview:

rp release channel show flog stable
rp release publish flog "$version" --job 1 --run "$run" --promote-to stable --dry-run
rp release publish flog "$version" --job 1 --run "$run" --promote-to stable
rp release channel show flog stable
rp release channel members flog stable

--promote-to atomically publishes, joins the existing channel and sets its tip under one confirmation. It does not create a channel or change its visibility. If the channel is not public, stop and obtain separate authorization for a visibility change before publishing a stable release. A successful preview does not reserve the result; publication revalidates the Run, tag, Release identity and channel state. Separate membership and promotion commands remain available for intentionally staged rollouts; a published Release without channel membership is project-only. Do not remove older stable members: their continued membership keeps standalone installer FLOG_VERSION installs working for historical versions. Use --attach during publication only when an existing canonical refs/tags/releases/flog/<version> tag already points to the exact source and matches the prepared Release.

All publication, membership, visibility and tip mutations require guarded browser confirmation. Do not perform them as an incidental part of a code or deployment task. A successful Job Run or published but unattached Release never changes the installer-visible stable version. Default installation continues to select the public immutable stable Release and never falls back to a development Run.

SHA-256 protects downloaded bytes against corruption and substitution relative to the HTTPS adapter response. Release-manifest signing and offline key management are tracked separately; until that is implemented, HTTPS integrity and controlled, reviewed channel promotion remain mandatory. Flog task #20 tracks signing and offline key management.

Self-update#

An installed POSIX release can update itself through the same manifests and artifact checks as the installer:

flog update
flog update --channel unstable
flog update --channel stable
flog update --channel next

With no saved override, the installer and updater follow the current channel ID declared by discovery as the default. This means an operator can change the default without leaving old installations pinned to its former name. If the default is null, an explicit selection is required. An explicit --channel stores that channel's durable ID only when it is nondefault; explicitly selecting the current default clears an existing override. The state changes only after a successful operation. Later plain flog update calls resolve a saved override by ID, so it survives a rename and fails rather than following a reused name. FLOG_CHANNEL overrides saved state, and --channel overrides the environment.

Exact immutable Release selection remains available only in the standalone installer through FLOG_VERSION; flog update --version and updater FLOG_VERSION selection are intentionally unsupported.

The canonical user config is one XDG-compatible flog/config.toml. It records only its schema and the installed version:

schema = 2
version = "0.1.9"

Selecting a nondefault channel adds only its product-local numeric identity:

schema = 2
version = "0.0.0-dev.dc9601f6c421"
channel = 3

There is no per-executable installations directory. Flog updates the executable being run and uses the Release API for current channel, Run, source, artifact, and checksum evidence rather than persisting those details. Two rolling Runs may share a printed version, so the updater downloads and verifies the selected artifact and compares its executable bytes instead of treating version text as exact Run identity. The config is bounded, strictly parsed, mode 0600, and held below a mode-0700 directory.

The former schema-1 directory-pointer config and matching schema-1/schema-2 per-executable record migrate one way after a successful operation. Migration uses only the record whose path and binary digest match the executable being updated; unrelated records are not adopted or removed. Older flog.update-state sidecars migrate under the same successful-operation rule. A rolling-looking binary without a trustworthy saved channel requires an explicit channel selection.

--releases-url selects a compatible manifest mirror, and --config selects an absolute alternate config path. The equivalent environment controls are FLOG_CHANNEL, FLOG_RELEASES_URL, and FLOG_CONFIG; command-line values take precedence. FLOG_ALLOW_HTTP=1 exists only for isolated local fixtures and must not be used in production.

Self-update supports the same Linux/macOS amd64/arm64 matrix as the installer. It verifies strict channel and immutable release manifests, redirect protocols, the archive SHA-256, exact archive entries, and BUILD-INFO.json before writing a staged executable beside the running binary. A same-directory rename is the only replacement operation. Network, validation, checksum, archive, staging, permission, interruption, and rename failures leave the previous executable in place. Config is fully staged before replacement. If its final atomic rename fails after executable replacement, Flog restores a staged copy of the previous executable; if rollback also fails, the error reports both failures. A failed or canceled operation never claims that a channel switch was remembered. The command never invokes sudo, changes profiles, or chooses another installation path; a non-writable executable directory produces an actionable error.

When local executable or state damage requires manual repair, flog update preserves the original actionable error and points to https://flog.run/install. It never downloads or executes that installer on the user's behalf. If Flog cannot run at all, manually review and run the installer:

curl -fsSL https://flog.run/install | sh

Use an explicit FLOG_CHANNEL only when that channel is publicly available and you deliberately want to select it.

Flog 0.1.8 predates the rolling protocol and cannot bootstrap with flog update --channel unstable. Before public rollout, the initial compatible client must be installed from a reviewed immutable stable Release (or a separately verified exact development archive in a test environment). Only then can an operator explicitly select unstable after its public feed is approved.