🚀 Join the waitlist now! waitlist.floot.dev
LogoFlootdocs

licensing

Sign in, seats, devices, the offline window, and the commands that manage them.

Every floot create checks that the machine it runs on is licensed. You never set that up by hand: sign in once, and the first command that needs a license does the rest. This page explains what happens, and the commands for looking at it and undoing it.

Four ideas cover all of it:

  • You sign in to your Floot account. That is only authentication.
  • A seat belongs to an organization and, once used, is bound to one person.
  • A device is one machine registered against that seat. A seat holds up to three at a time.
  • A lease is the thirty-day license file each registered machine keeps, which is what lets floot create work without a network.

Sign in

Terminal
floot login

The CLI starts listening on a local port, opens your browser at the Floot web companion, and waits. Approve the consent screen there and the browser hands a single-use token back to the terminal, which trades it for the CLI's own session:

Terminal
Waiting for the browser to finish the login.
Logged in as you@example.com

If you do nothing for five minutes the CLI gives up with login not completed. The session belongs to the terminal alone, with its own refresh chain, so signing out of the CLI never signs you out of the browser or the reverse.

If a session is already stored, floot login prints Already logged in as you@example.com. With a terminal attached it then asks Sign in as a different account?; answer no and it exits. Pass --force to replace the session without being asked. Without a terminal and without --force it just exits. A machine holds one account: to switch, run floot logout and then floot login.

Signing in without a browser on the same machine

Over SSH or inside a container there is no browser to open. Use the paste fallback:

Terminal
floot login --no-browser

The CLI prints a page to open in a browser on any machine, and asks for what that page shows:

Terminal
Open this page in a browser on any machine:
Paste the token shown there:

The web page also shows the token, with a copy button, whenever it is opened without a local port. Pasting needs a terminal that can prompt; without one the command fails with a usage error rather than waiting.

Signing in from floot create

You do not have to run floot login first. With a terminal attached, floot create notices there is no session and asks:

Terminal
You are not signed in. Press Enter to open the browser.

The same login runs in place and the create carries on. Without a terminal the command stops with You are not signed in. Run `floot login`. and exit code 77.

When a stored session ends, the CLI wipes it and says so:

Terminal
Your session has expired. Run `floot login`.

Seats and seat binding

An organization holds Floot seats. The first time you run floot license or floot create after signing in, the CLI asks for a seat under the organization you are working in and, if it finds a free one, binds it to you. From then on that seat is yours in that organization, and later runs find it again.

The CLI only ever asks about one organization. It never falls back to another one on its own. If you belong to more than one organization and want a specific one to license this machine, name it by its slug:

Terminal
floot license --seat-org <organization slug>
floot create my_app --seat-org <organization slug>

The slug is the short handle of the organization, such as acme. You can find it in three places: the list the CLI prints when it needs you to choose, the Organization line of floot license, and the organization's General settings in the web companion. It is matched without regard to case, and nothing else is accepted in its place.

--seat-org is unrelated to the --org flag on create, which sets the bundle identifier prefix of the project.

The CLI looks the slug up among the organizations you are an active member of, so an online run with --seat-org has to reach Floot, and fails with the ordinary network error when it cannot. A slug that matches none of them is refused before anything is asked of the licensing service, with the slugs you can use, and exit code 77:

Terminal
You are not an active member of an organization with the slug `acme-typo`.
Your organizations:
  Acme Inc (acme)
  Side Project (side-project)
  Untitled Studio

Each line is an organization's name followed by its slug. An organization that has no slug is listed by name alone and cannot be named with --seat-org. It licenses a machine as the organization you are working under, or when you choose it from the prompt described below.

Offline, --seat-org is matched against the organizations the CLI saw the last time it was online. A slug renamed since then keeps working offline under its old spelling until the next online run, and a script that hard-codes the old slug stops working online, where the list above shows the new one.

A machine bound under two organizations holds one device and one lease for each, using the same pair of device keys. Every seat counts its own devices.

When there is no seat to bind, the refusal says which of two situations it is, names the organization, and points at the web companion:

Terminal
<organization> has no Floot seats. See https://app.floot.dev for the seats on your account.
All of the Floot seats in <organization> are in use. See https://app.floot.dev for the seats on your account.

Both exit with code 77. When you belong to another organization that could license this machine, a hint is added before the pointer to the web companion, and the refusal is followed by your organizations so you have the slug to pass:

Terminal
<organization> has no Floot seats. Another organization you belong to can license this machine. Run the command again with `--seat-org` to name it. See https://app.floot.dev for the seats on your account.
Your organizations:
  Acme Inc (acme)
  Side Project (side-project)

The list is every organization you are an active member of, not only those with a free seat. Without the hint, no list is printed.

Choosing an organization at the prompt

With a terminal attached and no --seat-org, that hinted refusal does not end the run. The CLI prints the refusal, then asks:

Terminal
<organization> has no Floot seats. Another organization you belong to can license this machine. Run the command again with `--seat-org` to name it.
Which organization should license this machine?

The choices are your other organizations, shown the same way as the list above, leaving out the one that was just refused. An organization with no slug can be chosen here by its name. Pick one and the command carries on under it, exactly as if you had passed its slug with --seat-org. floot license and floot create both do this.

An account that is not working under any organization gets the same prompt, with every organization it belongs to.

The CLI tries once. If the organization you picked refuses too, you get that refusal and no second prompt. The choice stays on this machine: it is remembered as the organization this machine last worked under, and the organization you are working under in the web companion does not change.

You are never asked up front. A run that succeeds under the organization you are working under prints no prompt, however many organizations you belong to, and so does a refusal that carries no hint. Without a terminal there is nobody to ask, so scripts and CI get the refusal and the list, and exit code 77.

An account that is not an active member of the organization it asked about gets a different answer, since seats are not the problem there, and the same exit code:

Terminal
This account is not an active member of <organization>.

Devices

The first time a signed-in machine needs a license, the CLI does four things in one go, without asking you to restart anything:

  1. Generates two key pairs on the machine. One proves the machine is the one registered and signs its requests; the other unlocks the downloads meant for it.
  2. Asks Floot for a challenge under the organization it is working in.
  3. Proves it holds the keys by signing the challenge, and registers the machine under its hostname as the device name.
  4. Stores the thirty-day lease that comes back.

The private halves of the keys never leave the machine, and there is no copy anywhere else and no way to recover them. A machine that loses its keys is treated as a lost device: retire it and register it again. If the CLI is refused a seat, the keys it generated stay in place, so trying again once a seat is available reuses them.

The three-device limit

A seat holds three active machines. Registering a fourth would exceed that, so the CLI stops and lets you free a slot right there:

Terminal
Your Floot seat in <organization> already has three active machines. Retire one to register this machine.
Which machine should be retired?
Retiring <name> frees its slot. That machine stops renewing its license and keeps working offline until it expires.
Retire <name>?

Each choice in the list shows the machine's name, its platform and when it was last seen. Confirm and the CLI retires that machine, asks for a fresh challenge and finishes registering this one. If a second refusal follows, you get the ordinary error instead of another round of questions.

Without a terminal there is nobody to ask, so the CLI prints the same first line followed by the place to fix it, and exits with code 77:

Terminal
Your Floot seat in <organization> already has three active machines. Retire one to register this machine. Manage your machines at https://app.floot.dev/devices.

floot license

Terminal
floot license [--renew] [--seat-org <organization slug>] [--offline]

Prints what this machine is licensed for, and registers the machine first if it has never been licensed:

Terminal
Organization    Acme Inc (acme)
Seat            <seat id>
Bound to        you@example.com
Updates through 2027-03-01
Layers          <the layers your seat includes>
Lease expires   2026-10-28
Machine         my-laptop (active)

The Organization line is the organization's name and, in parentheses, the slug --seat-org takes. A seat with lifetime updates prints lifetime on the Updates through line.

A machine that holds licenses for several organizations, with no --seat-org and no record of the organization it last worked under, asks which one to use:

Terminal
This machine holds 2 licenses. Which organization should it use?

The choices are the organizations this machine holds a license for. The answer is remembered, so the question is asked once. It works the same with --offline, and in floot create. Without a terminal the CLI uses the license that expires last and says so:

Terminal
This machine holds 2 licenses and no organization was named, so it is using Acme Inc (acme), whose license expires last. Pass `--seat-org` with an organization slug to choose another.

A plain floot license reads the lease already on disk and never asks for a newer one. --renew does ask: it sends a signed request and replaces the stored lease with the fresh one, printing License renewed. --offline prints from the stored lease without any network call, and ends with a marker so a stale expiry is never mistaken for a live one:

Terminal
offline: read from the license stored on this machine.

The same marker prints when a plain run simply could not reach Floot. Combining --offline with --renew is a usage error, since one asks for a fresh lease and the other forbids asking anything.

floot devices

Terminal
floot devices list
floot devices remove <name or id>

floot devices list shows every machine on your seat: its name, platform, status (active or revoked) and when it was last seen, with (this machine) next to the one you are typing on:

Terminal
my-laptop                macos      active   last seen 2026-09-27  (this machine)
build-box                linux      active   last seen 2026-09-02

floot devices remove retires one machine by name or by id, freeing its slot. If two active machines share a name, the command asks for the id instead of guessing.

Terminal
Retired build-box.

Removing the machine you are on also removes its lease from this machine:

Terminal
Retired my-laptop and removed its license from this machine.

Its device keys are wiped only once no lease is left on the machine, because the same keys serve every seat the machine is registered against. Neither command renews anything.

Lost or stolen machines

There is no --lost flag. Reporting a machine lost is done in the web companion, because the machine in question is the one you no longer have. It also signs out your other CLI sessions, which each recover with one floot login, with no re-registration.

Signing out

Terminal
floot logout

Ends this terminal's session and keeps the device and its lease:

Terminal
Logged out.
The device key and any license lease on this machine are kept.

Offline creates therefore keep working until the lease runs out. Renewal needs a session, so after a plain logout the lease simply lapses at its expiry.

On a shared machine, hand it on clean:

Terminal
floot logout --revoke-device

This also retires the machine from every seat it is registered against, freeing those slots, wipes its device key and lease, and signs out:

Terminal
Retired this machine from its seat and removed its device key and license.
Logged out.

A machine registered under two organizations prints 2 seats in place of its seat. If the retirement fails, the terminal stays signed in and says so, so you can try again. The exception is a session Floot has already ended, which signs the terminal out because there is nothing left to retry with.

Two cases do nothing to a seat. Without a session, the command exits with code 77 and You are not signed in, so this machine's device slot was not freed. A machine with no lease prints This machine is not registered against a seat, so no slot was freed., wipes any leftover device key and signs out.

The offline window

A lease lasts thirty days. Every online floot create renews it silently, so a machine that creates at least monthly never sees it expire. When Floot cannot be reached, floot create builds from a release already cached on the machine, and the lease is what proves the machine may. The create page describes what that run checks.

When a lease is within seven days of ending, a create prints one heads-up and carries on:

Terminal
Your license lease ends in 5 days. Connect to the internet and rerun to renew it.

If it could not be renewed on an online run, the line reads Your license lease could not be renewed and ends in 5 days. instead.

The CLI also remembers the latest date and time it has seen, and refuses to run if the system clock has moved more than a day behind that.

Every refusal, and its remedy

Each refusal names the check that failed and the one thing that fixes it. The exit code tells a script what kind of failure it was: 77 means a permission the machine lacks, 70 means damage or a defect, and 69 means something unavailable.

MessageExitWhat to do
This machine is not licensed yet. Connect to the internet and rerun.77The machine has no lease. Run once online.
Your license file is damaged or unreadable. Rerun online (renewal is automatic), or run `floot login`.70Run once online; if that does not fix it, sign in again.
Your system clock appears to have moved backwards. Fix the date and time, then retry.70Correct the system date and time.
Your license lease expired on <date>. Connect to the internet and rerun to renew it; if your CLI is out of date you will be asked to run `floot update` first.77Run online. If the version block appears, run floot update and rerun.
This machine's device keys do not match its license. Run `floot login` to register this machine again.77Sign in again to register this machine afresh.
Kit <version> failed signature verification. Rerun online to download it again.70Run online to replace the cached copy.
Kit <version> needs a newer Floot CLI. Run `floot update`.69Update the CLI.
Your update window ended <date>, so kit <version> is not included in your seat. See Releases at https://app.floot.dev.77Releases in the web companion lists what your seat can build with. Run floot create without --bundle to use one of those.
Your seat does not include the <layer> layer. See Releases at https://app.floot.dev.77Leave that layer out, or check Releases in the web companion.
This machine's download authorization is stale. Rerun online to refresh it.70Run online once.
Cached kit files are corrupted. Rerun online to download them again.70Run online to download them again.
Kit <version> is not cached on this machine. Connect once to download it, or run `floot create` without `--bundle` to use a release you already have.69Connect once, or drop --bundle.
No kit is cached on this machine. Connect once to download Floot.69Connect once.
You have no license for <organization> on this machine. Connect to the internet and rerun, or pick another organization with `--seat-org`.77Run online, or name an organization this machine holds a license for. The organization is shown as Name (slug) when the machine has seen it before, and as the slug you typed otherwise.

The checks run in a fixed order and stop at the first one that fails, so you only ever see one message. When several cached releases fail differently, the message is the one for the newest.

Refusals from Floot itself

When Floot is reachable and says no, the CLI never falls back to the cache, since the answer was a decision and not an outage.

MessageExitWhat to do
Your session was signed out. Run `floot login`.77Sign in again. The device and lease are untouched.
You are not an active member of an organization with the slug `<slug>`., followed by your organizations77Pass one of the slugs listed. The CLI decides this itself from your memberships, before asking for a license.
This machine has been retired from its Floot seat. Register it again to keep using it.77The machine was retired, from the web companion or from another terminal. Nothing changes on this machine: it keeps working offline until its lease ends, at most thirty days. The Devices page in the web companion lists the machines on your seat.
This Floot CLI is older than this server supports. Run `floot update` and try again.69Run floot update.
Kit <version> is not available. Run `floot create` without `--bundle` for the latest release you can use.69Drop --bundle.
No Floot release is available for this CLI and seat., followed by a notice line69 or 7769 when a newer CLI is needed, 77 when your seat's update window does not reach a release. The notice line says which.
<message> Try again in <N> minutes.69Wait; a rate limit is never answered from the cache.

Entitlement notices always point you at Releases in the web companion, and never ask you to do anything else:

Terminal
You are creating with Floot 1.9.3. Version 2.1.0 is available, but your update window ended 2026-03-01. See Releases at https://app.floot.dev.

Continuous integration

Ephemeral CI runners are not supported in v1

A seat holds three devices, and a fresh CI runner registers as a new device every run. There is no official way to run floot create on ephemeral CI runners today.

The only headless affordance is the FLOOT_ACCESS_TOKEN environment variable. When it is set, the CLI uses it as the session in place of anything stored. It carries no refresh token, so it is never renewed: whoever sets it keeps it current. It sets up a session and nothing else. The machine still needs to be registered against a seat like any other.

On this page