Installation

 Linux,  MacOS,  FreeBSD and  Termux

Fetch and install the latest release with the installation helper script:

curl -fsSL https://flow-control.dev/install | sh

Install the latest nightly build:

curl -fsSL https://flow-control.dev/install | sh -s -- --nightly

with debug symbols:

curl -fsSL https://flow-control.dev/install | sh -s -- --nightly --debug

See all available options for the installer script:

curl -fsSL https://flow-control.dev/install | sh -s -- --help

By default the GUI, flow-gui, is installed as well and integrated with the desktop: on Linux and FreeBSD that is a desktop entry and an icon, on MacOS an app bundle. The MacOS install puts both binaries inside /Applications/Flow Control.app, or ~/Applications/Flow Control.app when /Applications is not writable, and links them into the install destination, so flow on the command line and Flow Control in Finder are the same install.

Install without the GUI:

curl -fsSL https://flow-control.dev/install | sh -s -- --no-gui

Install the GUI, but leave the desktop alone:

curl -fsSL https://flow-control.dev/install | sh -s -- --no-integrate

Downloads are verified against the gpg key published at flow-control.dev/public.gpg, pinned to fingerprint 4E6C F723 4FFC 4E14 5310 74F9 8EB1 E1BB 660E 3FB9. Verification uses gpgv, gnupg’s signature verification tool, and is not optional: without it the installer stops and asks you to install it rather than continuing unverified.

Most distributions ship gpgv as a package of its own, which is worth knowing because installing gnupg does not always bring it with it. FreeBSD has it in security/gnupg, named gpgv2. MacOS ships neither, so install gnupg first with homebrew, macports, nix or gpgtools.

Piping the installer into sh runs it before anything has checked it, so the script itself is only as trustworthy as the TLS connection that fetched it. To verify the installer too, download it and its signature, check them against a key you already have, and only then run it:

curl -fsSL -O https://flow-control.dev/install
curl -fsSL -O https://flow-control.dev/install.sig
gpgv --keyring /path/to/public.gpg install.sig install
sh install --key /path/to/public.gpg

Check that the signature is from 4E6C F723 4FFC 4E14 5310 74F9 8EB1 E1BB 660E 3FB9; gpgv reports a good signature from any key in the keyring it is given, so the fingerprint it names is the part that matters. --key then makes the installer verify the download against the same local key instead of the published one.

Which version gets installed is decided by a small manifest at flow-control.dev/version-latest, or version-latest-nightly for nightlies, holding nothing but the release tag. It is signed with the same key, so a release mirror cannot answer with an older tag than the one that was actually published. The installer refuses to proceed if that manifest is missing or does not verify.

The key is saved in ~/.local/state/flow for later updates. If the published key ever stops matching the saved copy, the installer stops and asks you to check it, in the same spirit as a changed ssh host key.

You can disable verification if you really want, but only by explicitly asking:

curl -fsSL https://flow-control.dev/install | sh -s -- --no-verify

The installer also writes an update-flow script next to the binaries, which re-runs the install with the same options. Run it to update:

update-flow

update-flow verifies the installer it downloads before running it, and refuses to run one that is not signed by the pinned key. It also refuses if gpgv has gone missing since the install, so that removing gnupg cannot turn a verified install into an unverified update. Both refusals can be overridden for a single run with update-flow --no-verify.

At the top of the installer are variables to pre-answer the installation questions. Configure them to your liking.

We have some tips for Android

 Windows

For Windows the installer script is a little different.

Fetch and install the latest release to %AppData%/Roaming/flow/bin:

Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

One script installs every variant. Since it is piped into Invoke-Expression it cannot take parameters, so the choices are made with environment variables.

Install the latest nightly build:

$env:FLOW_NIGHTLY = 1
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

Install the latest nightly build with pdb debug symbol files:

$env:FLOW_NIGHTLY_DEBUG = 1
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

The Windows installer also installs the GUI, flow-gui.exe, and adds a Start Menu shortcut for it. Install without the GUI:

$env:NO_GUI = 1
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

or keep the GUI and skip only the Start Menu shortcut:

$env:NO_INTEGRATE = 1
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

Install somewhere else than %AppData%/Roaming/flow/bin:

$env:DEST = "C:\tools\flow"
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

The installer stops early when the installed build is already the latest one. Re-install it anyway:

$env:FORCE_UPDATE = 1
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

FLOW_NIGHTLY_DEBUG implies FLOW_NIGHTLY, as debug builds are only published for nightlies, and NO_GUI implies NO_INTEGRATE. If you save the script to a file instead of piping it, the same choices are switches: -Nightly, -Debug, -NoGui, -NoIntegrate, -Force, -Dest <path>, -NoVerify, -KeyFile <file> and -AllowDowngrade.

Downloads are verified against the gpg key published at flow-control.dev/public.gpg, pinned to fingerprint 4E6C F723 4FFC 4E14 5310 74F9 8EB1 E1BB 660E 3FB9. Verification uses gpgv, gnupg’s signature verification tool, and is not optional: without it the installer stops and asks you to install it rather than continuing unverified.

Windows does not ship gnupg, so install it first:

winget install GnuPG.GnuPG

then open a new terminal, so that gpgv is on your PATH.

Piping the installer into Invoke-Expression runs it before anything has checked it, so the script itself is only as trustworthy as the TLS connection that fetched it. To verify the installer too, download it and its signature, check them against a key you already have, and only then run it:

Invoke-WebRequest "https://flow-control.dev/install.ps1" -OutFile install.ps1
Invoke-WebRequest "https://flow-control.dev/install.ps1.sig" -OutFile install.ps1.sig
gpgv --keyring C:\path\to\public.gpg install.ps1.sig install.ps1
.\install.ps1 -KeyFile C:\path\to\public.gpg

Check that the signature is from 4E6C F723 4FFC 4E14 5310 74F9 8EB1 E1BB 660E 3FB9; gpgv reports a good signature from any key in the keyring it is given, so the fingerprint it names is the part that matters. -KeyFile, or $env:KEYFILE, then makes the installer verify the download against the same local key instead of the published one.

Which version gets installed is decided by a small manifest at flow-control.dev/version-latest, or version-latest-nightly for nightlies, holding nothing but the release tag. It is signed with the same key, so a release mirror cannot answer with an older tag than the one that was actually published. The installer refuses to proceed if that manifest is missing or does not verify.

The key is saved in %AppData%\flow for later updates. If the published key ever stops matching the saved copy, the installer stops and asks you to check it, in the same spirit as a changed ssh host key.

You can disable verification if you really want, but only by explicitly asking:

$env:NO_VERIFY = 1
Invoke-RestMethod "https://flow-control.dev/install.ps1" | Invoke-Expression

The Windows installer also writes an update-flow.ps1 next to the binaries, so you can just run update-flow in a terminal to update. It repeats the install with the options you chose, so updating a nightly stays on nightlies and a custom destination keeps updating in place. FORCE_UPDATE is the exception: it applies to the run you ask for and is not carried into later updates.

update-flow verifies the installer it downloads before running it, and refuses to run one that is not signed by the pinned key. It also refuses if gpgv has gone missing since the install, so that removing gnupg cannot turn a verified install into an unverified update. Both refusals can be overridden for a single run with update-flow -NoVerify.

 Build from Source

See the Building section of README.md in the source repository for build instructions.

 Manual install from tarballs or zip files

See the downloads page for binaries that you can manually install. Just download, unpack, and place the binary anywhere you want. There are no runtime files required and configuration directories and files are created on demand.