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/pathselects an explicit destination.FLOG_VERSION=1.2.3installs 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=nextselects 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 withFLOG_VERSION.FLOG_CONFIG=/absolute/path/config.tomloverrides the per-user config path. The default isos.UserConfigDir()/flog/config.toml(normally$XDG_CONFIG_HOME/flog/config.tomlor$HOME/.config/flog/config.tomlon Linux, and$HOME/Library/Application Support/flog/config.tomlon 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/releasesselects a compatible manifest origin.FLOG_ALLOW_HTTP=1permits 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.