Skip to content

Applications

The app topic groups every command that acts on an application running in a cluster, both catalog installs (kind: CatalogApp) and source-built apps (kind: Application). The behaviour is the same for both: the application is the unit of operation, whatever put its image in the registry.

Almost every verb under app takes an application name or slug as its first positional argument, and accepts -c, --cluster <name|id> to pick the cluster (auto-detected when the active profile has only one). The output flags follow the rest of the CLI: -o, --output table|json (or text|json on the streaming commands), -f, --force to skip confirmations, --no-wait to queue and exit.

Two verbs are the exception, because they run locally and do not target a running application: flui app init and flui app manifest. Both are under Project setup.

This page is the reference for the verbs and their flags. The task pages cover the same ground step by step: Watch and operate a running application, Set an application’s configuration and secrets, and Remove an application and its data.

Read this before you delete anything

flui app delete also deletes the application’s persistent volumes. The data is gone, and Flui cannot bring it back.

Because this is the most destructive thing you can do to an application, the command reads the cluster first and prints what it will delete before it asks. When it cannot read the cluster, it says “unknown”, never “none”. Full detail in Deletion.

Project setup

flui app init [<framework>]

Copies Flui’s deploy files (a Dockerfile and a flui.yaml) from an official framework template into the current directory, turning an existing Git repository into something flui deploy can build.

Terminal window
flui app init --list # list supported frameworks
flui app init nextjs # latest supported Next.js
flui app init nextjs@16 # pin a major version
flui app init fastapi --target ./api
flui app init nestjs --force # overwrite existing files
flui app init nuxt --dry-run # print the actions, write nothing
Flag / ArgEffect
<framework>Framework template, optionally with a major-version pin (nextjs, nextjs@16). Omit when using --list.
--listPrint the supported frameworks and versions, then exit.
--forceOverwrite existing files without prompting.
--dry-runPrint the actions that would be taken; write nothing.
--target <dir>Target directory. Default: the current working directory.

app init adds Flui files to a repository you already have. To create a new repository from a template instead, use flui template use; see Templates.

flui app manifest

Prints the authoring reference for flui.yaml (kind: Application): every field, what it does, and which fields the spec accepts but does not apply on source deploys. It runs fully offline, with no cluster and no login, and the field list comes from the published spec schema, so it always matches what flui deploy validates.

Terminal window
flui app manifest # the field reference
flui app manifest --json # the raw JSON Schema
flui app manifest --example # an annotated example
flui app manifest --example nextjs # port + healthcheck for a framework

This prints the shape of a manifest, not the manifest of a particular application. Point an assistant at it when it needs to write a valid flui.yaml.

Inspection

flui app list

Lists the applications in the cluster with their high-level state. Catalog installs made of several parts show as one row; -x, --expanded breaks them out into their components.

Terminal window
flui app list
flui app list --expanded
flui app list --output json

flui app status <name>

Shows the live runtime status of one application: how many replicas are ready against desired, the current release, and any condition that needs attention.

Terminal window
flui app status my-api
flui app status my-api --output json

flui app logs <name>

Fetches application logs from the cluster. By default it returns the last 100 lines; you can filter by level, search the text, or widen the window.

Terminal window
flui app logs my-api
flui app logs my-api --level error
flui app logs my-api --tail 500
flui app logs my-api --search "connection refused"
FlagDefaultEffect
-l, --levelnoneFilter by error, warn, info, debug.
-n, --tail <n>100Number of lines to return.
-s, --search <q>noneFull-text search.
-o, --output text|jsontextOutput format.

flui app metrics <name>

Instant resource metrics for one application: CPU, memory, network I/O, replica count, then the health checks of the last hour and what to do: add a replica, add a node, or nothing. Use it to spot-check a workload’s footprint, to line a spike up against a deploy, or to decide whether it needs another copy. --output json carries the same advice as capacity_advice.

Terminal window
flui app metrics my-api
flui app metrics my-api --output json

Configuration

The values an application runs with come from three places: the manifest, what you pass at deploy time, and what is stored against the app. Set an application’s configuration and secrets explains which one wins. These two verbs read and write the stored set.

flui app env list <app>

Lists the application’s variables in three states: plain values, sensitive keys that are set (only the fact, never the value), and keys still awaiting a value, declared by the manifest but never supplied.

Terminal window
flui app env list my-api

“Awaiting a value” is a state, not an error: the command exits 0 either way. No sensitive value is printed, because the API answers with a mask and none is available to print.

flui app env set <app> <KEY>

Delivers the value of a sensitive variable. There is no --value flag. A value passed as an argument lands in your shell history, is visible to every other process on the machine while the command runs, and, when an agent composed the command, is copied into a model’s context on the way.

So the command prompts for the value, or reads it from standard input.

Terminal window
flui app env set my-api STRIPE_SECRET_KEY
pbpaste | flui app env set my-api STRIPE_SECRET_KEY --stdin
FlagEffect
--stdinRead the value from standard input rather than prompting.
-c, --clusterCluster name or ID.

The command prints the key and whether it is now configured; the value is never echoed and cannot be read back later. It takes effect on the next rollout: flui app redeploy <app>.

Two cases are refused: a key linked to a building block’s own secret, and the display mask sent back as if it were a value. In a non-interactive shell the command refuses to prompt and tells you to use --stdin.

Runtime diagnostics

flui app crashes <name>

Lists recent crash diagnoses for the application: automatic reports produced when a workload restarted unexpectedly, summarising the exit code, the signals the runtime saw, and the probable cause.

Terminal window
flui app crashes my-api
flui app crashes my-api --output json

flui app crash <name> <id>

Shows one crash diagnosis in full, including the reasoning the platform used to classify it. --dismiss marks it resolved so it stops appearing as an active issue on the dashboard. --apply makes the change the diagnosis proposes (a higher memory limit after an out-of-memory kill), and the application restarts. Flui never makes that change on its own.

Terminal window
flui app crash my-api 5d3f... # show one diagnosis
flui app crash my-api 5d3f... --apply # accept the change it proposes
flui app crash my-api 5d3f... --dismiss # mark it resolved

Get <id> from flui app crashes.

flui app traffic <name>

HTTP traffic for one application, measured at the edge where requests enter the cluster rather than inside your code: request rate, the split by status class, error percentages, latency, and a breakdown by method and by status code.

Terminal window
flui app traffic my-api
flui app traffic my-api --window 1h
flui app traffic my-api --output json
FlagDefaultEffect
-w, --window <d>5mRate window. Longer is smoother on low traffic.
-o, --outputtabletable or json.

An application that is not exposed has no edge traffic, and the command says so instead of printing zeroes.

Latency percentiles come from a histogram with fixed buckets. When those buckets are too coarse to separate this application’s responses, the command prints the boundaries it had and labels the percentiles as estimates. The mean is measured, not estimated.

flui app alerts <name>

Alerts for the application, one row per episode, newest first. Each row shows the alert name, its severity, a one-line summary and its timing.

Terminal window
flui app alerts my-api
flui app alerts my-api --firing # only what is still firing
flui app alerts my-api --output json
FlagDefaultEffect
--firingoffOnly alerts still firing.
-n, --limit <n>20How many to show.
-o, --outputtabletable or json.

A resolved alert marked with * stopped reporting instead of sending a resolution, so its end time is approximate. The mark tells you the alert went quiet, which does not mean it recovered.

flui app build <name>

Status of the latest build of a source-built application (kind: Application). With --watch the command stays in the foreground, polling until the build reaches a terminal status.

Terminal window
flui app build my-api
flui app build my-api --watch
flui app build my-api --refresh # force the backend to re-poll the CI
FlagDefaultEffect
--refreshnoneForce the backend to re-poll GitHub Actions now.
-w, --watchnonePoll until the build reaches a terminal status.
--interval <s>5Polling interval in seconds.

flui app builds <name>

Recent build history (default: last 10; releases also defaults to 10, versions to 20).

Terminal window
flui app builds my-api
flui app builds my-api --limit 50

Release management

A release is one rollout of an image into the cluster: a deploy or a rollback. An image can be released more than once, and not every image gets released.

flui app releases <name>

Release history.

Terminal window
flui app releases my-api
flui app releases my-api --current # only the running release
flui app releases my-api --limit 50

flui app versions <name>

Image versions in the container registry for this application, each marked as the current deployment, a previous release, or unreleased.

Terminal window
flui app versions my-api
flui app versions my-api --limit 50
flui app versions my-api --output json

flui app redeploy <name> [<target>]

Re-deploys an existing image without rebuilding. The target is a tag, a short digest (12+ hex chars), or a full sha256:<digest>. Alternatively, --build <id> deploys the image produced by a specific earlier build.

Terminal window
flui app redeploy my-api a1cac27
flui app redeploy my-api sha256:812bdfd0a833...
flui app redeploy my-api --build <build-id>

This is the rollback path: pick a known-good app versions entry and redeploy it. It is also how a newly delivered variable reaches a running application.

flui app auto-deploy <name>

Shows or changes whether an application redeploys itself when its branch moves. Off by default.

Terminal window
flui app auto-deploy my-api
flui app auto-deploy my-api --on
flui app auto-deploy my-api --off

Lifecycle

flui app start / flui app stop / flui app restart

The everyday lifecycle verbs. stop scales to 0 replicas (workloads disappear but their configuration and volumes are kept); start brings the application back at one replica; restart performs a rolling restart, replacing one replica at a time.

Terminal window
flui app start my-api
flui app stop my-api
flui app restart my-api

flui app stop is equivalent to flui app scale my-api --replicas 0.

flui app scale <name>

Sets how many replicas an application runs: a fixed count, or a range the count follows with the CPU load. Replicas that find no room wait for a node, which makes the cluster’s scaling group buy one. For an app deployed from flui.yaml, the range is its deploy.scaling.

Terminal window
flui app scale my-api --replicas 3
flui app scale my-api --replicas 0 # same as `app stop`
flui app scale my-api --min 2 --max 6 --cpu 70
flui app scale my-api --no-autoscale # back to a fixed count
FlagEffect
-r, --replicas <n>A fixed count, 0 to 20.
--min <n>, --max <n>The range the count follows with the load, 1 to 20.
--cpu <percent>CPU use per replica, as a share of what it reserves, above which one is added (10 to 95).
--[no-]autoscaleLet the count follow the load, or go back to a fixed count.

--replicas cannot be combined with the range flags or --[no-]autoscale.

What scale can do depends on the application’s storage class (see Storage classes and dedicated placement for the model):

  • Shared storage. Every replica reads and writes the same network filesystem, so the platform can run as many replicas as you ask for, on any node. This applies to stateless apps and to anything using the default storage class.
  • Dedicated storage. The application is pinned to the node that holds its local disk, and there is only one such disk. Raising replicas above 1 would mean several copies competing for the same on-disk state, which is unsafe. For these apps, the platform does not support horizontal scaling. Give the workload more capacity by resizing its host node instead (see flui env scale-master/scale-node).

flui app resources <name>

Shows or changes the CPU and memory an application reserves and the ceilings it may reach. Changing either restarts the application.

Terminal window
flui app resources my-api
flui app resources my-api --memory-limit 1Gi --dry-run
flui app resources my-api --cpu-request 250m --memory-request 512Mi
FlagEffect
--cpu-request, --cpu-limitCPU reserved, and the ceiling.
--memory-request, --memory-limitMemory reserved, and the ceiling.
--dry-runSay what would change, change nothing.
--apply-proposalApply the memory change Flui proposes, as it stands now. Cannot be combined with the value flags or --dry-run.
--at-next-windowWith --apply-proposal: hold the change for the maintenance window that governs the app.
--container <name>Pick the container in an app that has more than one. Default: the first one.
-o, --outputtable (default) or json.

flui app maintenance get|set|cancel <name>

Changes that restart something can wait for a maintenance window. get shows which window applies to the application, when it next opens and the changes held for it (--json for machine output). set makes the application follow the cluster’s window (--follow), use its own (--slot, repeatable, with --timezone, default UTC), or apply changes at any time (--anytime). cancel <id> drops a held change before it runs.

Terminal window
flui app maintenance get my-api
flui app maintenance set my-api --slot "sun 04:00 1h" --timezone Europe/Rome
flui app maintenance set my-api --anytime
flui app maintenance cancel my-api <change-id>

Scheduled jobs

A scheduled job runs a command on the application’s own image and configuration, on a cron schedule. Because it is the same environment your app runs in, a job can reuse the app’s code, its database connection and its variables without a second deployment to maintain.

flui app schedule create <app>

Terminal window
flui app schedule create my-app \
--name nightly-cleanup \
--schedule "0 3 * * *" \
--command "node dist/cleanup.js"
flui app schedule create my-app \
-n report -s "*/15 * * * *" \
-x "php artisan report:run" --timezone Europe/Rome
FlagDefaultEffect
-n, --name <s>requiredSchedule name (lowercase alphanumeric and dashes).
-s, --schedule <s>requiredCron expression, five fields.
-x, --command <s>requiredShell command, run through /bin/sh -c.
-t, --timezone <tz>cluster timeIANA timezone, e.g. Europe/Rome.
--concurrencyForbidOverlap policy: Allow, Forbid or Replace.
--disabledoffCreate it suspended, not running.

The default overlap policy is Forbid: if a run is still going when the next one is due, the next one is skipped. That is the safe default for jobs that touch shared state. Replace stops the running one and starts the new one; Allow lets them overlap.

flui app schedule update <app> <name>

Changes a schedule in place. Only the flags you pass change: -s, --schedule, -x, --command, -t, --timezone, --concurrency.

Terminal window
flui app schedule update my-app nightly-cleanup --schedule "0 4 * * *"

flui app schedule suspend|resume <app> <name>

suspend stops new runs without deleting the schedule; a run already in progress finishes. resume turns it back on.

Terminal window
flui app schedule suspend my-app nightly-cleanup
flui app schedule resume my-app nightly-cleanup

flui app schedule list <app>

Lists the application’s schedules with their cron expression, whether they are enabled or suspended, the last time each one was scheduled, and the command.

Terminal window
flui app schedule list my-app
flui app schedule list my-app --output json

flui app schedule runs <app> <name>

Recent runs of one schedule with their status (Succeeded, Failed, Running) and whether each was started by the schedule or by hand. How far back the history goes depends on what the cluster keeps.

Terminal window
flui app schedule runs my-app nightly-cleanup

flui app schedule logs <app> <name>

Logs of one run. Defaults to the most recent run; -r, --run targets a specific one, named as it appears in schedule runs.

Terminal window
flui app schedule logs my-app nightly-cleanup
flui app schedule logs my-app nightly-cleanup \
--run my-app-nightly-cleanup-28912345

An old run whose workload has already been cleaned up has no logs left, and the command says so instead of failing.

flui app schedule trigger <app> <name>

Runs the schedule now, whatever its cron timing says. Use it to check a job works without waiting until 3am.

Terminal window
flui app schedule trigger my-app nightly-cleanup

flui app schedule delete <app> <name>

Removes the schedule.

Terminal window
flui app schedule delete my-app nightly-cleanup

Data management

Two separate tools work on an application’s persistent volumes:

  • Snapshots live inside the cluster: a copy of a volume, kept beside it. Each one is a full volume of the same size, and you pay for it as one until you delete it. Restoring is a local volume-to-volume copy, faster than fetching from object storage but not instant. The cost adds up with retention, so keeping many around quickly reduces the cluster’s free capacity.
  • Backups are kept in S3-compatible object storage outside the cluster. They are much cheaper, slower to restore, and survive a cluster destroy. Sent to a registered destination, they are encrypted snapshots you can restore whole or file by file.

The two sets are independent; neither implies the other.

The difference matters when you remove an application. A backup sits outside the cluster, and a removal does not reach it. A snapshot is a volume on the same cluster, carrying the same application’s label, so a removal deletes it too. A snapshot protects you against a bad upgrade, not against deleting the app.

flui app snapshot create <name>

Creates a snapshot of an application’s volume. If the application has more than one volume, pass -v, --volume <name>.

Terminal window
flui app snapshot create my-app
flui app snapshot create my-app --description before-upgrade
flui app snapshot create my-app --volume data
flui app snapshot create my-app --pause

A volume a database is writing to is refused, because the copy might not restore cleanly. --pause stops the workloads holding the volume for the length of the copy; --allow-inconsistent copies anyway.

flui app snapshot list

Lists snapshots. Without filters, it lists every snapshot in the cluster; filter by application with --app.

Terminal window
flui app snapshot list
flui app snapshot list --app my-app
flui app snapshot list --app my-app --output json

flui app snapshot restore <name> <snapshot-id>

Restores a snapshot into a new side-by-side volume. The application is left untouched: the new volume is created alongside it and can be promoted later with snapshot swap. Pass --swap to restore and promote in one step.

Terminal window
flui app snapshot restore my-app <snapshot-id>
flui app snapshot restore my-app <snapshot-id> --swap
flui app snapshot restore my-app <snapshot-id> --swap --volume <name>

With --swap the CLI also needs to know which application volume to retarget. Without --volume it assumes the volume is named data, the conventional default. Pass --volume <name> whenever your app’s primary volume has a different name, or whenever it has more than one.

flui app snapshot swap <name> <restored-volume>

Swaps the application’s live volume for a different one, usually the one snapshot restore just created. It triggers a rolling restart, and the previous volume is kept until you delete it. The CLI asks you to confirm before applying; -y, --yes (or --force) skips the prompt.

Terminal window
flui app snapshot swap my-app my-app-data-restored-20260511
flui app snapshot swap my-app my-app-data-restored-20260511 --volume <name>
flui app snapshot swap my-app my-app-data-restored-20260511 --volume <name> --force

The same --volume rule applies as for restore --swap: without it the CLI assumes data.

flui app snapshot delete <name> <snapshot-id>

Deletes a snapshot. Asks you to confirm; skip with -y, --yes (or --force).

Terminal window
flui app snapshot delete my-app <snapshot-id>
flui app snapshot delete my-app <snapshot-id> --force

flui app snapshot discard <name> <volume>

Deletes a restored or previous volume the application does not use, the kind snapshot restore and snapshot swap leave behind.

Terminal window
flui app snapshot discard my-app my-app-data-restored-20260511

flui app backup create <name>

Takes a backup of an application’s volume now. With --destination it is an encrypted snapshot recorded against a registered destination, kept until you delete it, and restorable whole or file by file. With --bucket, a full plaintext copy is archived instead, to a bucket you name; with neither, the cluster’s provider auto-provisions one. The command follows the backup to the end unless you pass --no-wait.

Terminal window
flui app backup create my-app --destination <dest-id> # preferred
flui app backup create my-app # auto-provisioned bucket
flui app backup create my-app --description nightly
flui app backup create my-app --bucket my-archive \
--endpoint https://s3.example.com \
--access-key <key> --secret-key <secret>
FlagEffect
-D, --destination <id>A registered backup destination (see flui backup destination list). Cannot be combined with --bucket.
-b, --bucket <name>Destination S3 bucket. Auto-provisioned when omitted.
-e, --endpoint <url>S3 endpoint URL. Required when --bucket is set.
-r, --region <code>S3 region (default: auto).
-v, --volume <name>Volume name when the app has more than one.
-d, --description <s>Human-friendly tag appended to the key prefix.
--access-key <k>S3 access key. Required when --bucket is set. Default: FLUI_S3_ACCESS_KEY.
--secret-key <s>S3 secret key. Required when --bucket is set. Default: FLUI_S3_SECRET_KEY.
--key-prefix <s>Override the destination key prefix. Default: flui/<cluster>/<app>/<timestamp>/.
--pause / --allow-inconsistentAs for snapshot create.
--no-waitReturn once the backup is queued.

When --bucket is set, all three of --endpoint, --access-key and --secret-key are mandatory (the last two can come from the matching environment variables). Pass them together or not at all; passing the bucket without credentials fails up front.

How far auto-provisioning goes depends on the provider. Where the compute key also reaches object storage, it is fully automatic; elsewhere, object storage credentials must be connected first (see the providers integrated today). There is also a top-level flui backup topic for scheduled, policy-driven backups with their own destinations and jobs. app backup is the ad-hoc, single-app variant.

flui app backup list|browse|restore <name>

list shows the application’s volume backups, newest first. browse <name> <backup> [path] lists a folder inside one without changing anything. restore <name> <backup> brings it back, whole, into a new volume by default. --swap puts it in place of the current data and keeps the previous data as a separate volume; -p, --path (repeatable) restores only those files, over the current ones or, with --into, into a folder beside them; --to restores into another application.

Terminal window
flui app backup list my-app
flui app backup browse my-app <backup-id> uploads
flui app backup restore my-app <backup-id> --swap
flui app backup restore my-app <backup-id> --path uploads/avatar.png

flui app backup before-deploy <name>

Takes a backup before each deploy. --required makes a deploy wait for it; --off turns it off.

flui app backup skip <name>

Marks the application as intentionally not backed up, so it stops being listed as needing a decision. -n, --note says why; --undo reverses it.

flui app backup delete <name> <backup>

Removes a volume backup and its record; it cannot be restored afterwards. --yes skips the question. See Backups.

Terminal window
flui app backup delete my-app <backup-id> --yes

Volumes

flui app volume resize <app>

Makes an application’s volume bigger. Volumes only grow.

Terminal window
flui app volume resize my-app --size 20
flui app volume resize my-app --volume uploads --size 50

-s, --size is in GiB; without it the command shows what is possible and changes nothing. -v, --volume picks the volume when there is more than one.

Deletion

flui app delete <name>

Permanently removes the application and everything it was using in the cluster, including its persistent volumes. The data is deleted, not moved to a bin, and Flui cannot bring it back.

Before it asks, the command reads the cluster, works out which storage belongs to this application, and prints it: one sentence with the total, then each volume by name and size.

This also deletes 10 GiB of data in 1 volume.
It cannot be undone.

The platform writes that sentence once, so the CLI, the dashboard and an agent all quote the same number.

If the cluster cannot be reached, or its credentials cannot be read, the command says so and tells you to assume data will be lost. An empty list means “none found” only when the reading succeeded.

The volumes this would delete could not be read from the cluster.
Assume data will be lost — it is not known to be none.

The confirmation is not a yes/no. You type the application’s name exactly, which makes you read the list above it. --force skips that question but not the listing: the preview is printed either way.

Terminal window
flui app delete my-app
flui app delete my-app --force # skip confirmation
flui app delete my-app --no-wait # queue and exit
FlagEffect
-c, --clusterCluster name or ID.
-f, --forceSkip the typed confirmation. Also the acknowledgement a system-protected app requires.
--no-waitReturn as soon as the removal is queued.

If the application you name is one part of a catalog install, the preview lists every part and the removal takes all of them, so no bundle is left half-removed.

Some applications are system-protected (typically the components Flui itself depends on inside the control cluster). For those, --force is required as an explicit acknowledgement.

For a catalog install the CLI waits for the uninstall to finish, up to five minutes, unless you pass --no-wait. For a source-built application it queues the delete and returns; check with flui app list.

For the full procedure, including how to take a backup first, see Remove an application and its data.

Storage no application owns

A cluster can hold volumes that no application owns any more, left by an older removal or by something removed outside Flui. They are unattached, not listed anywhere else, and still billed.

Terminal window
flui cluster volumes
flui cluster volumes --output json
flui cluster volumes --remove user-a1b2c3/data-uptime-kuma-0

A volume is only reported when nothing mounts it and no existing application owns it. When in doubt the scan leaves a volume out: one it cannot attribute to a departed application is not offered for deletion. Removing one is permanent.

flui app image delete <name> <version-id>

Removes an image version from the container registry. Two guards protect your ability to roll back:

  • The version that is currently deployed can never be deleted. This guard cannot be bypassed.
  • The version of the most recent release is also refused; --force overrides this second guard only.
Terminal window
flui app image delete my-api 845914920
flui app image delete my-api 845914920 --force
flui app image delete my-api 845914920 --yes # skip the prompt
FlagEffect
--forceOverride the latest-release guard only.
-y, --yesSkip the confirmation prompt.
-c, --clusterCluster name or ID.

--force and --yes do different things: --force lifts a guard, --yes skips the question.

Get <version-id> from flui app versions <name> --output json. It is the numeric registry id, not the tag.