flyghtdeck Docs

User guide

Flyghtdeck Docs

Flyghtdeck runs your shell scripts on machines you set up once, with the variables, secrets and run history kept beside them. This guide covers everything in the app.

Quickstart

A first run needs three things: a workspace to hold the work, a runner to run it on, and a script. The first time you sign in, a short setup sheet offers to make all three for you. To do it by hand:

  1. Create a workspace. Open the workspace switcher in the top bar and choose + New workspace. Name it after what it runs, for example Deployments.

  2. Build a runner. Open Runners, press + and pick Templates. Choose a template, keep pressing Next, then Create runner. The box is built once and kept.

  3. Add a script. Open Scripts, press + and name it hello. On the Editor tab replace the starter body and press Save:

    echo "Hello from Flyghtdeck"
  4. Run it. On the Console tab press Run. The log streams as the script works:

    14:02:11 [Flightdeck] INFO ./hello started
    14:02:11 Hello from Flyghtdeck
    14:02:11 [Flightdeck] INFO ./hello exited 0 after 0s

From here, give the script parameters, keep its credentials as secrets, and invite the people who should run it.

How it fits together

ThingWhat it is
OrganisationThe sharing boundary. It owns workspaces and has members; groups decide what each member can see and do. Every account starts with a personal organisation.
WorkspaceThe scripts, environments and runners for one job of work.
ScriptA shell script with optional parameters, run on demand.
EnvironmentA named set of variables and secrets, such as dev or production. A run uses one.
RunnerA persistent Linux box, built once from a setup script, that runs execute on.
RunOne execution of a script: its parameters, log, status and exit code.

The app has three pages in its left rail (a bottom bar on phones): Scripts, Environments and Runners. Each shows the current workspace. Settings, including organisations, are under the account menu at the top right.

Scripts and folders

Press + at the top of the Scripts sidebar and type a name. The name is a path: slashes make folders, so deploys/api/release creates a script called release inside deploys/api/. A path must be unique in the workspace, ignoring case.

Folders are only the paths of the scripts in them. There is no empty folder: one appears when a script is created, renamed or moved into it, and goes when its last script leaves. Each folder row has its own + to add a script there.

Row actions

ActionWhat it does
RunStarts a run. Becomes Cancel or Stop while one is in flight.
RenameChanges the name. A slash in the new name also moves the script. Not available while it is running.
DuplicateCopies the body and parameters into the same folder as name copy.
MoveSets the destination folder. Use / for the root.
Copy name, Copy pathCopies release or /deploys/api/release.
DeleteDeletes the script.

A folder's menu has Rename, which moves every script in it, and Delete, which deletes every script inside it.

Finding scripts

Working with others

If someone else changes a script you have open, the sidebar shows Conflict and Run is disabled for that script. Press the refresh icon beside it to load the current version.

Editing a script

A selected script has four tabs.

TabWhat is there
ConsoleThe environment and runner pickers, the parameter fields, Run, and the live log.
EditorThe script body and its parameter definitions.
HistoryPast runs with their logs and parameters.
SettingsRequire confirmation to run, and Delete.

Saving is explicit. Changes to the body and the parameters are one draft, marked by a dot on the Editor tab, until you press Save. Revert discards the draft and Compare shows the draft beside the saved version. A draft survives moving between pages but not a browser refresh.

Scripts run with bash

Every script is run by bash, whatever its first line says. To run Python, Node or anything else, call it from the script: python3 tool.py.

Parameters

Parameters are the inputs a run is started with. Define them on the Editor tab under Parameters; each one reaches the script as an environment variable of the same name.

TypeIn the ConsoleDefault
textA text field.Optional. The field starts with it.
booleanA checkbox, sent as true or false.false or true.
enumA list to pick from.The first option. Options are comma-separated.

Referencing a variable

A parameter value can point at a variable with {{NAME}}, either typed in the Console or set as the parameter's default. Typing {{ opens a list of the names available. The reference is resolved when the run starts, against the organisation's variables and the chosen environment's.

REGION    text   default  {{AWS_REGION}}
TARGET    enum   options  {{STAGING_HOST}}, {{PRODUCTION_HOST}}

Hover a reference to see what it resolves to; a secret shows as ****. A reference that matches nothing is tinted red and reaches the script as the literal text. History keeps the reference, never the resolved value.

A reference is only needed to pass a variable under a different name or to choose between several. Every variable already reaches the script under its own name.

Running a script

The Console header chooses where a run goes.

Press Run. While a run is in flight the button turns red and reads Cancel if the run is still queued or Stop once it is executing. Stop ends the process straight away, with no confirmation.

Require confirmation to run

For a script that could do damage if started by accident, turn on Require confirmation to run on its Settings tab. Run then opens a slider that has to be dragged across before the run starts. With the keyboard, move the handle to the end with the arrow keys and press Enter.

Logs

The Console streams a run's output as it happens. Each line has the time it was written; hover it for the full timestamp. Lines the platform writes itself start with [Flightdeck] and are coloured by level. Everything else is your script's output, shown as it was printed.

09:30:02 [Flightdeck] INFO ./release started
09:30:03 flyght: Checking out main from https://github.com/acme/api.git into api
09:30:05 flyght: Checked out main at 4f2a91c Bump version
09:31:40 BUILD SUCCESS
09:31:40 [Flightdeck] INFO ./release exited 0 after 1m 38s

History and statuses

The History tab lists the script's 50 most recent runs, newest first, with the status, run number, environment, duration and exit code. Open a finished run for its Logs and the Parameters it was started with. A run that is still going opens in the Console.

StatusMeaning
QueuedWaiting for a free slot.
RunningExecuting on the runner.
SucceededThe script exited 0.
FailedThe script exited with another code, or could not be started.
Timed outThe run reached the runner's time limit and was killed.
CancelledSomeone cancelled or stopped it.

A finished run can be deleted from its row, which removes the record and its log. The address bar always points at what you are looking at, so a script, a tab or a single run can be shared as a link with anyone who has access.

Inside a run

What a script can rely on when it starts:

Shared boxes

Runs on the same runner share one machine. Two scripts running at once can see each other's files and processes, so keep a runner for work that trusts each other.

The flyght command

flyght is a small command placed on the path of every run. It has one job so far: checking out a GitHub repository.

flyght git checkout <url> <branch> [--into <dir>] [--keep] [--provider github]

Its progress lines start with flyght:. A failure prints flyght: error with a short code and the reason, and exits 1, for example needs a token and GITHUB_TOKEN is not set or Branch release not found. flyght help prints the usage and flyght version the version.

Environments

An environment is a named set of variables and secrets in a workspace, such as dev, staging and production. A run uses one environment, picked in the Console. Environments are optional: a workspace with none still runs scripts, with the organisation's variables only.

The sidebar also has an Organisation row. It holds the variables shared with every workspace in the organisation, described below.

Variables and secrets

An environment has two tables: plain variables and secrets. Press + Add variable or + Add secret, type a name, press Tab, type the value. Edits save by themselves a moment after you stop typing.

Secrets

A secret's value is encrypted and write-only. Once saved it shows as •••••••• and is never shown again, to you or anyone else.

Masking is a seatbelt

Run logs replace any secret value of four or more characters with ****, so an accidental echo "$TOKEN" does not leak it. A script that transforms the value first, for example with base64, defeats the mask. Anyone who can edit and run a script can read the secrets its runs are given.

Organisation variables

Variables and secrets set on the organisation reach every run in every workspace of it, whichever environment the run uses. Manage them on the Organisation row of the Environments page, or under Settings, the organisation, Variables. They suit values that are the same everywhere, such as a GITHUB_TOKEN.

Which value wins

A run's environment variables are built in three layers. When the same name appears in more than one, the later layer wins.

OrderSourceNotes
1Organisation variables and secretsAlways present.
2The run's environmentOverrides the organisation's.
3The run's parametersOverride both. {{NAME}} references are resolved against layers 1 and 2.

Everything is exported: there is nothing to switch on per variable. A script reads $AWS_REGION directly once a variable of that name exists.

Runners

A runner is the machine your scripts run on: a persistent Linux box, built once from a setup script and kept between runs. A fresh box is Ubuntu with Java 25, Node 24, Python 3.13, git and curl. The setup script adds whatever else your scripts expect.

Creating a runner

Press + on the Runners page. The wizard has five steps.

  1. Start. Choose Copy (the same setup as one of your runners, on a new box), Templates (a preconfigured setup) or Custom (write the setup yourself).

  2. Choose. Pick the runner to copy or the template. Either can be edited on the next step.

  3. Setup. Edit the setup script and choose the memory the box may grow to: 2, 4, 8 or 16 GB. The Suggestions panel adds ready-made blocks; order matters, so install a tool before a line that uses it. The script stops at its first failing line.

  4. Preview (optional). Runs the setup on a fresh box and shows its log, so you can see it work before keeping it. A previewed box becomes the runner. If you skip this, the setup runs when you create the runner.

  5. Finish. Name the runner and, optionally, list the domains it may reach. Press Create runner.

A setup has 30 minutes to finish. If it fails the box is thrown away and the wizard shows the log: go back, fix the script and preview again.

Templates and suggestions

TemplateWhat it installs
Java 25 + Maven + DockerMaven 3.9 and a Docker daemon beside the box's Java 25, for Maven builds and Testcontainers suites.
Java 17 + MavenTemurin 17 through SDKMAN alongside Java 25, with Maven 3.9.
Python 3 + uvuv beside the box's Python 3.13, for fast, locked dependencies.
Node + pnpmThe box's Node 24, raised, with pnpm through corepack.
DockerA Docker daemon on the box.
FlyghtdeckJava, Maven, Docker, Node, Playwright's Chromium, the AWS CLI and the Fly CLI: what Flyghtdeck's own scripts use.

The Suggestions panel on the Setup step offers the same pieces one at a time: the AWS CLI, Docker, the Fly CLI, a git identity, Git LFS, Gradle, Java 17, 21 and 25, Maven, Node, pnpm, Playwright browsers, Python, uv, and a block for any Ubuntu package.

Runner settings

A runner's Settings tab holds what can change after it is built.

SettingWhat it does
NameShown in the Console's runner picker.
Run timeoutSeconds before a run on this box is killed. 3600 (an hour) by default, 24 hours at most.
NetworkThe domains the box may reach, one per line. See below.
Default runnerMakes this the workspace's default.
Reset the boxWipes everything runs have left on it, back to exactly what the setup produced.
Delete this runnerDestroys the box and everything on it.

Network

Leave the list empty and the box reaches anything. Add domains and it reaches only those:

github.com
*.npmjs.org
s3.eu-west-2.amazonaws.com

A * covers one level of subdomain. The limit is applied from outside the box, so a script cannot widen its own reach, and it applies after setup, so a build can still install what it needs.

Reset and delete

Workspaces

A workspace holds the scripts, environments and runners for one job of work, and belongs to an organisation. The switcher in the top bar lists the workspaces you can see and keeps you on the same page when you change.

Organisations

Every account has a personal organisation, made at sign-up. It is yours alone: it cannot be renamed, deleted or shared. To work with other people, create an organisation: Settings, then the + beside Organisations. Creating one makes you its owner and switches you into it.

When you belong to more than one, the account menu lists them. Pick one to act in it; the workspace switcher then shows that organisation's workspaces.

An organisation's page in Settings has up to five tabs.

TabWhat it doesWho sees it
MembersThe people in the organisation and pending invitations.Everyone
GroupsBundles of permissions and the members who hold them.Owner
VariablesVariables and secrets shared with every workspace.Owner, and members granted it
RunnersRunners every workspace can use, and the default for new workspaces.Owner, and members granted it
SettingsName, picture and deleting the organisation.Owner

Deleting an organisation removes its workspaces with their scripts, run history and secrets, and every member's seat. It asks for the organisation's name, then for a second confirmation when other members are affected.

Members and invitations

  1. The person joining signs in and copies their Account reference from Settings, Profile, then sends it to you.

  2. On the organisation's Members tab press + Invite member and paste the reference.

  3. They receive an email with a link, if their account has an email address. You can also copy the link from the invitation's ⋯ and send it yourself. Only the invited account can open it.

  4. They choose Join organisation. Put them in a group, because a member in no group sees nothing.

Groups and permissions

The owner can do everything and is the only one who manages members, groups and the organisation itself. Everyone else gets access through groups: a group is a set of members and the permissions they hold. Access is only ever handed out. A member in no group sees no workspaces, and a new workspace is hidden from every group until it is granted.

Simple: pick a level

LevelWhat it allows
AdminEverything inside the organisation.
EditorCreates, edits and runs things; no deleting.
RunnerSees everything and runs scripts.
ViewerSees everything, changes nothing. New groups start here.

A level applies to the organisation and to every workspace in it.

Advanced: tick by tick

The Advanced view is a matrix of Read, Run, Create, Edit and Delete. A group whose ticks match no level reads Custom.

Permission changes are a draft until you press Save; Revert restores what was saved. Adding or removing a group's members takes effect immediately.

Signing in

Sign in with your GitHub account. Flyghtdeck is in early access, so creating an account also needs the early access key from your invitation. Enter the key, then continue with GitHub.

The first sign-in opens a setup sheet: pick a theme and your notifications, then optionally a first workspace, runner and script. Nothing is created until you press Finish, and you can leave the sheet at any point.

Notifications

When a run you started finishes, a notification lands in the bell at the top of the app. Click one to open that run in History.

SettingWhat it doesStarts
Successful runsA run finishes cleanly.Off
Failed runsA run fails or times out.On
Email notificationsAlso sends them to your account's email address.Off
Desktop notificationsAlso shows them as system banners while a Flyghtdeck tab is open. This browser only.Off

Settings

Settings are under the account menu at the top right.

SectionWhat is there
ProfileYour name, sign-in method, email and account reference; sync from GitHub; sign out; delete account.
AppearanceDark or light theme, kept in this browser. The toggle in the top bar does the same.
NotificationsWhich run outcomes reach you, and how.
OrganisationsOne page per organisation, and creating a new one.
FeedbackA message straight to the team.
AdvancedUsage statistics: reports which pages and features you use, tied to your account reference; never names, script contents or logs. On by default.

Deleting your account

Profile, Advanced, Delete account. You are asked to type your username. It is permanent: your account goes, with the workspaces you created, their run history, and any organisation you were the only member of. Your GitHub account is not touched.

Plan limits

Limits belong to an organisation and follow its owner's plan. On the starter plan they are currently:

LimitStarterAt the limit
Runs at once1More runs wait in the queue.
Workspaces3New workspace shows Limit reached.
Members3Invite member shows Limit reached. The owner and pending invitations count.
Runners per workspace10The wizard refuses with the reason.
Organisation runners10The wizard refuses with the reason.
Runners building at once3Wait for a build to finish.

There is no limit on scripts, environments or variables.

Example scripts

Check out a private repository and build it

Runner: the Java 25 + Maven + Docker template. Secret: GITHUB_TOKEN, a token that can read the repository. Parameter: BRANCH, text, default main.

set -eu

flyght git checkout https://github.com/acme/api.git "$BRANCH"
cd api
mvn --batch-mode package

The checkout stays on the runner, so the next run only fetches what changed and Maven's cache is already warm.

Deploy a static site to S3

Runner: add the AWS CLI 2 suggestion to the setup. Variables: BUCKET, DISTRIBUTION and AWS_DEFAULT_REGION. Secrets: AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and GITHUB_TOKEN. The AWS CLI reads its variables by itself. Turn on Require confirmation to run.

set -eu

flyght git checkout https://github.com/acme/website.git main
aws s3 sync website/public "s3://$BUCKET" --delete --no-progress
aws cloudfront create-invalidation --distribution-id "$DISTRIBUTION" --paths '/*'

Keep one environment per target, each with its own BUCKET, DISTRIBUTION and keys. The same script then deploys wherever the Console's environment picker points, and the keys can never belong to a different site than the bucket.

Back up a Postgres database

Runner: add the apt packages suggestion with postgresql-client, and AWS CLI 2. Variables: PGHOST, PGDATABASE, PGUSER and BACKUP_BUCKET. Secrets: PGPASSWORD and the AWS key pair. pg_dump reads the PG* variables by itself.

set -eu

stamp="$(date +%Y%m%d-%H%M%S)"
dump="/tmp/$PGDATABASE-$stamp.dump"

pg_dump --format=custom --file="$dump"
aws s3 cp "$dump" "s3://$BACKUP_BUCKET/" --no-progress
rm "$dump"
echo "Backed up to s3://$BACKUP_BUCKET/$PGDATABASE-$stamp.dump"

Name variables after the tool

Give a credential the name its tool already reads, such as GITHUB_TOKEN, AWS_ACCESS_KEY_ID or PGPASSWORD. The script then needs no plumbing, and the value never appears on a command line.

Messages you may see

MessageWhat to do
No runners. Create one on the Runners pageThe workspace has nothing to run on. Create a runner.
Runner is resettingWait for the reset to finish, then run again.
Missing required parametersFill in the fields marked * in the Console.
This script changed elsewherePress the refresh icon in the Scripts sidebar.
Script already has a run in flightWait for the run to finish, or stop it.
Script exceeded the time limitRaise the runner's run timeout, or make the script faster.
Run waited longer than the limitThe queue did not clear within an hour. Check for a stuck run in the Queue and start it again.
Lost touch with the serverThe run was stopped because its runner lost contact with Flyghtdeck. Run it again.
Limit reachedThe organisation is at a plan limit.

Getting help

Flyghtdeck is in alpha and changes often. If something is rough, missing or wrong in these pages, send it from Settings, Feedback, or write to admin@flyghtdeck.com.