**The portal link puts itself back up.** It already retried a connection that raised, but a session that ended *cleanly* — a portal restarting, a proxy closing an idle socket — returned normally and went straight back round the loop with no wait at all, so an engine could spin against a portal that was merely saying goodbye politely. Every ending now reconnects on a delay, and the delay turns on whether the attempt got as far as attaching: one that stood up and dropped is a network event and retries at once, one that never stood up waits longer each time. Jittered, so a portal coming back is not met by every installation it serves in the same instant. Ping timeouts are named rather than defaulted, since they are what bounds how long a suspended laptop's dead socket looks alive, and the keepalive task is awaited so the reason a link went reaches the log instead of the garbage collector. **`fluksio enroll <code>`** is the whole command now; hub.fluksio.com is the default and `--portal` names another. The one command run before anything works should not need two flags. **`fluksio run` syncs first.** The reason a run exists is usually the edit before it, so remembering to sync was remembering to do something the computer could do — including the worker refresh, which is what makes an edit to your own package take effect at all. `--no-sync` opts out for a tight loop. That last one needed discovery fixed: it only ever looked at top-level `*.py`, so a repository whose code is in a package — the ordinary shape — found nothing from its own root. It now descends into the packages it holds. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ue1tkFWB1bcGy3aWhCKpU
9.7 KiB
The fluksio command
pip install fluksio
Installs the engine and the fluksio command. Python 3.12 or newer, Linux or
macOS.
There is a second, smaller distribution — fluksio-worker — for a machine that
should only run nodes for an engine elsewhere. It has none of the engine in
it. See Remote workers.
The command is two things at once: serve, enroll and worker are an
installation, while login, sync, run and runs talk to one that may be
anywhere.
Where an installation lives
.fluksio beside your code, found the way .git is: from the working
directory, or any directory above it. Two repositories on one machine are
therefore two engines, with their own flows, runs and token. fluksio serve
makes one where there is none, and it ignores itself from within — a
.gitignore of *, so a database and a credential cannot be committed by
accident.
--global uses ~/.fluksio instead, shared by every directory. --data-dir
(or FLUKSIO_HOME) names any directory outright and wins over both.
fluksio serve
Runs the engine.
fluksio serve
On the first start it creates an admin account and prints its password once. Nothing else has to be running: no database server, no message broker, no Docker.
| Option | Default | What it does |
|---|---|---|
--data-dir PATH |
./.fluksio (or $FLUKSIO_HOME) |
where this installation keeps everything |
--host HOST |
127.0.0.1 |
what to bind |
--port PORT |
8000 |
what to listen on |
--log-level LEVEL |
info |
uvicorn's log level |
--admin-email ADDR |
admin@example.com |
the account created on first run |
--admin-password PW |
generated | set it instead of having one generated |
--enroll CODE |
— | pair with a portal as part of coming up |
--portal URL |
— | the portal --enroll redeems at |
--enroll with --portal is the one-command setup: it pairs before the engine
starts, so the connection is dialled as part of coming up rather than needing a
restart. It is skipped if the installation is already enrolled.
!!! warning "One process"
`fluksio serve` holds the flow engine. A second one is a *second engine* —
duplicated subscriptions, duplicated cron ticks, two webhooks answering the
same path. Run one, and distribute work with
[workers](workers.md) instead.
!!! note "$HOME on a cluster"
A login node's home directory is often NFS, where SQLite's write-ahead log
does not work — the database would be locked or corrupt. `fluksio serve`
warns when it notices; point `--data-dir` at local disk.
What it prints
Created the admin account admin@example.com
password: k3Qm-8vTpLdX
Shown once. Change it from the dashboard.
Fluksio 0.1.0 — data in /home/you/.fluksio
API http://127.0.0.1:8000/api/v1
No portal. Pair this installation with:
fluksio enroll <code>
An enrolled installation says which portal it is on instead, and notes that the dashboard is served from there rather than here.
fluksio enroll
Pairs an existing installation with a portal.
fluksio enroll ABCD-1234
| Option | What it does |
|---|---|
--portal URL |
a portal of your own, instead of https://hub.fluksio.com |
--as EMAIL |
the local account a portal session arrives as |
--data-dir PATH |
which installation, if not the one this directory is in |
Get the code from the portal under Installations → Add installation. It is
single-use and expires in fifteen minutes. --as matters when the installation
has several superusers — without it, enrolment refuses rather than guessing.
Afterwards, fluksio serve dials the portal as it comes up, and keeps dialling:
a portal that restarts, a wifi that changes, a laptop that suspends and wakes
somewhere else all end the same connection, and the link is put back up without
anybody noticing. A connection that stood up and then dropped is retried at
once; one that never stood up waits a little longer each time, up to half a
minute. See Accounts and the portal.
fluksio worker
Runs nodes for an engine elsewhere. Everything after worker belongs to the
agent's own parser — it is the same program fluksio-worker installs, so the
two are interchangeable:
fluksio worker --url wss://api.example.com/api/v1/workers/attach \
--token "$FLUKSIO_WORKER_TOKEN" --labels gpu
See Remote workers.
Talking to an engine
The four commands below are the client half: they run wherever you work, and address an engine over its API rather than being one.
fluksio login
fluksio login --url https://api.example.com
For an engine somewhere else. One you started yourself needs no login:
fluksio serve writes the token as it comes up and says where it put it.
The token goes in this project's .fluksio/client.json, or with --global in
~/.fluksio/client.json. Every command below reads it from there — nearest
first, walking up from the working directory — or from FLUKSIO_URL and
FLUKSIO_TOKEN, or from its own --url and --token. A token an older
version wrote to ~/.config/fluksio/client.json is still read.
fluksio sync
fluksio sync [PATH_OR_MODULE ...] # default: the current directory
Imports what you name, collects the flows the decorators declared, and uploads each one with a generated import shim per node. A directory that is a package is walked; a dotted name is imported as it stands; nothing is loaded from a file path, because the shim has to import the same way.
| Flag | What it does |
|---|---|
--dry-run |
print the flow documents and shims, upload nothing |
--no-publish |
leave the upload as a draft |
--force |
overwrite a flow, or a node body, that was edited on the canvas |
Every sync retires the engine's workers, including one that had nothing to upload — a worker holds your package in memory, so an edit to it is invisible until the process goes. See Getting started: data science.
fluksio run
fluksio run train --lr 0.05 --seed 7 [--wait]
Syncs the working directory, then submits a run — so the command after an edit
is this one and nothing else. Flags that are not its own are the flow's
inputs, typed by what the flow declares them as. --wait blocks until the run
finishes and exits non-zero if it failed.
--no-sync runs what is already on the engine. Worth it in a tight loop where
you know nothing changed, since syncing retires the workers and the next call
pays its imports again. A directory that declares no flows syncs nothing and
says nothing — a flow drawn on the canvas is run the same way.
fluksio runs
fluksio runs [--flow train] [--limit 20]
The runs an engine has recorded, newest first: id, status, flow, duration, the commit of the repository it came from, and its parameters.
What lives in the data directory
.fluksio/ (or ~/.fluksio, with `--global`)
├── client.json the token `serve` wrote, mode 600
├── .gitignore `*` — a database and a credential, ignored from within
├── fluksio.db SQLite: users, runs, metrics, observability, agents
├── flows/ a git repository — one directory per flow
│ ├── house/
│ │ ├── flow.json the published structure
│ │ ├── nodes/*.py the published node code
│ │ ├── flow.draft.json unpublished edits, if any
│ │ └── nodes.draft/*.py
│ ├── _lib/ shared node sources
│ ├── _dashboards/ dashboards, drafts and all
│ └── requirements.txt what the Modules screen installs
├── artifacts/ content-addressed bytes, two levels deep
├── user-venv/ the interpreter your node code runs on
├── secrets.enc encrypted credentials, deliberately outside flows/
├── alerts.json alert channels and rules
├── panels.json wall-panel pairings
├── oauth-key.pem signs agent tokens
├── cloud.json the portal enrolment, if there is one
├── secret_key signs sessions and derives the secrets key
└── env optional settings file
Two things follow from this layout and are worth internalising:
flows/ is a real git repository. git log is the history of every change
anyone made to any flow. A run records the commit it ran at, so git show on
that hash is literally the code that produced the number.
Backing up the data directory backs up the installation. Everything else is rebuildable. Copy it while the engine is stopped, or use SQLite's online backup for the database if it is not.
Settings
Settings come from the environment, or from an env file in the data
directory. The ones you are most likely to touch:
| Variable | Default | What it does |
|---|---|---|
DATA_DIR |
./.fluksio via the CLI; ~/.fluksio with --global |
everything below it derives from this |
DATABASE_URL |
SQLite in the data dir | any SQLAlchemy URL |
NODE_VENV |
auto |
which interpreter node code runs on: auto adopts the venv Fluksio was installed into, managed builds one of its own, or name an interpreter |
REDIS_HOST |
unset | flow state in Redis instead of memory; survives a restart |
FRONTEND_HOST |
— | the address used in mails, OAuth metadata and panel links |
ENVIRONMENT |
local |
production closes the interactive API schema |
MCP_ENABLED |
false |
opens the agent endpoint |
SECRET_KEY |
generated once | signs sessions, derives the secrets key |
The full list is in Configuration.