Flyghtdeck documentation
User-facing guide to running your scripts on Flyghtdeck. Pick a section from the sidebar, or read top to bottom — the pieces build on each other.
Quickstart
From zero to a running script in a few minutes. You'll need a Flyghtdeck account and, to run scripts locally once, a Docker daemon on the machine you use.
- Create a workspace — open the workspace switcher in the top bar and choose New workspace. Name it and press Create.
- Add a script — in the Scripts sidebar press +, name it
(e.g.
hello), and write something in the Editor tab:echo "Hello from Flyghtdeck" - Pick a container — a workspace needs a container to run in. Use a Flightdeck default, or build your own. Set one as the workspace's default container.
- Hit Run — the script runs in an isolated container. Open the run from the log panel to watch output and see how long it took.
That's the loop: workspaces hold scripts, scripts run in containers, and environments supply the variables. For the next steps, work through Core concepts.
Core concepts
Everything in Flyghtdeck hangs off four things:
Organisations
The sharing boundary. Workspaces, members and groups live here; what a member sees is what their groups grant. Every account gets a personal organisation at sign-up.
Workspaces
Named collections of scripts, environments, variables and containers. A workspace is what a team works against.
Scripts
Shell scripts that run in an isolated container, optionally gated by parameters.
Environments
Named sets of variables & secrets a run resolves values from.
Workspaces
A workspace is your working area: it owns a tree of scripts, a set of environments and containers. Switch between workspaces with the dropdown in the top bar. Each workspace points at a default environment and a default container — the ones a run uses unless you pick otherwise. Create workspaces with the switcher's New workspace, and rename or delete one from its … in the same menu.
Organisations
Organisations are the sharing boundary. Everyone gets a personal organisation at sign-up, which can't be deleted. You can create more organisations to group a team, and switch which organisation you're acting in from the account menu (top-right).
- Invite members — from the organisation's Members tab, create an invite link and share it with the person joining. You can label an invite with an email to record who it's for, but the label doesn't lock it: whoever opens the link while signed in claims the seat. The link itself is the credential — share it directly with the person it's meant for.
- Revoke — withdraws a pending invitation before it's claimed.
- Remove — drops an accepted member from the organisation.
- Leave — members can leave; the organisation and its workspaces stay.
An organisation also carries things shared with every workspace in it: the Environment tab holds organisation-level variables and secrets, and the Containers tab holds shared containers. Owners can upload a custom picture for the organisation.
Permissions & groups
An Owner manages access through groups. A group is a set of members plus a permission bundle. Access is "handed out" — a member in no group sees nothing by default. Group membership commits instantly; permission changes are a draft — press Save to commit them, or Revert to walk back.
In the group's Permissions tab you can use Simple mode and pick a
preset, or drop into Advanced for fine-grained control. Advanced shows an
organisation-level table and a Workspace access matrix — one section per workspace.
Each workspace starts hidden until you grant its read verb, which makes
the whole workspace visible to the group.
Scripts
A script is a shell program that Flyghtdeck runs in an isolated container. Create one with the + in the Scripts sidebar, write it in the Editor tab, then hit Run. A script is:
- Shell-authored — write plain bash (or whichever shell your container provides).
- Saved — the editor stores the latest version; older runs keep their own copy in history.
- Runnable on demand — every run happens in its own container, so runs are isolated from each other.
- Optional parameters — input fields you define (see below), which become environment variables inside the run.
The ⋯ menu on a script also lets you Rename, Duplicate, Copy name and Delete it.
Dangerous scripts
If a script performs a destructive or high-impact action, mark it dangerous. Running a dangerous script requires a deliberate slide-to-confirm — the slider has to be dragged fully across before the run starts. This is the heaviest tier of confirmation the app offers, so reserve it for scripts that could cause real damage if triggered accidentally.
Folders
Scripts live in a tree. Folders are just virtual paths in the sidebar — they let you group related scripts without moving files around. Create folders with the + in the Scripts sidebar, expand/collapse them with the caret, and move scripts between folders from the row's ⋯ menu. The sidebar's top ⋯ can collapse or expand every folder at once.
Parameters
Give a script inputs and they become environment variables in the run's container — in fact
a run's environment variables are exactly its parameters, which is why
references matter. Because of that, a parameter name must be a
valid POSIX identifier: letters, digits and _ only,
and must not start with a digit.
Text
A freeform value the runner enters at run time.
Boolean
An on/off checkbox.
Enum
A fixed set of choices the runner picks from.
A parameter can be mandatory (the script won't start without it — marked with
a *) and can carry a default value. Parameter values are stored
with each run, so history shows exactly what a run was launched with.
Running & monitoring
Press Run to start a script. The Console tab streams live output: the command that ran, its stdout, a timer, and a live cursor while it's still working. The status bar shows the run queue — how many runs are in flight and how many are waiting — and you can Stop a running script.
The History tab lists past runs. Each run records its status
(pending, running, succeeded, failed,
timed out, cancelled), exit code, duration and the parameters it
launched with — so it's easy to tell what happened and why.
Finished runs can send you a notification (bell in the top bar) — pick which outcomes you hear about in Settings → Notifications. Script rows in the sidebar carry a status dot, and a run that's active pulses.
Environments & variables
An environment is a named, per-workspace set of variables (and secrets). A run resolves values from two tiers: the organisation's own variables (always in scope for every workspace) overlaid by the run's chosen environment — on a name clash, the environment's value wins. Pick which environment a run uses in the Console's environment dropdown; a workspace has a default environment used unless you change it.
Values never reach a script on their own — they arrive through parameter references. Defining a variable makes it available; referencing it from a parameter is what injects it.
Environment row verbs (from its ⋯): Set as default, Rename, Duplicate, Copy name and Delete.
Plain variables
A plain variable is a name/value pair, e.g. REGION=eu-west-1. Like parameter
names, a variable name must be a valid POSIX identifier. Define variables in an environment's
table with the + — or in the organisation's Environment tab to share
them with every workspace — then reference them from any parameter as
{{REGION}}.
Secrets
A secret is a variable whose value is encrypted and write-only: once set,
the app never shows it back to you or to anyone else. In the table it appears as
••••••••. Use secrets for API keys, tokens, passwords and other things you don't
want sitting in plain text. You can overwrite a secret with a new value at any time,
but a variable created as a secret stays a secret — the flag can't be switched off later.
echo $TOKEN prints •••• instead of the value. The
masking is best-effort (a deliberate transformation like base64 defeats it), so
treat it as a seatbelt, not a vault door.
Referencing values
In the Console's parameter fields and in parameter defaults you can reference a variable by
name with the {{KEY}} syntax, e.g. {{DB_PASSWORD}}. As you type a
reference, the app offers a typeahead of the resolvable names — the organisation's variables
plus the active environment's. Hover a resolved reference to preview what it points to (a
secret previews as ••••, never its value); a reference that can't be resolved
shows red.
References resolve when the run launches: the value is injected into the container and never
written into run history, which is how a secret reaches your script without being stored
anywhere in run metadata. A parameter like GITHUB_TOKEN defaulting to
{{GITHUB_TOKEN}} exports the decrypted value into that run only. If a reference
still doesn't resolve at launch (a typo, or a variable deleted since), the literal
{{KEY}} text is passed through unchanged — visible in the run's output rather
than silently swapped for an empty value.
Containers
A container defines the image your scripts run in. It has a base image, a few optional build steps that produce a derived image, and run settings such as a per-run timeout. Containers come in three scopes, matching the sections in the Containers sidebar:
- Flightdeck — app-shipped defaults, identical for every customer, read-only. Duplicate one as the starting point for your own. The section can be hidden from the sidebar (bring it back with the Flightdeck containers switch in Settings → Appearance).
- Organisation — shared containers every workspace in the organisation can run; editing them takes an organisation-level grant.
- Workspace — created by you for this workspace.
Each workspace marks one container as its default, used unless a run picks another. From a container's ⋯: Set as default, Duplicate, Copy name, and (for your own) Edit / Delete. Edits are a draft — Save or Revert.
Build steps
The build steps are shell commands run once when the image is built, then cached. This is where you install the toolchain your scripts need — for example:
apt-get update
apt-get install -y git curl jq openjdk-21-jdk-headless python3
Base-image + build steps bake a derived image that every run of that container starts from, so the expensive setup happens once, not on every run.
Docker access
A container can be given Docker access — the host's Docker daemon is mounted
into the run, which you need for docker build/push or Testcontainers
suites. It's also root-equivalent on the worker, so it's off by default and you switch it on
deliberately, per container.
Runs in a Docker-access container are otherwise ordinary runs — no extra confirmation is added. If a particular script warrants its own guard, give it one with the per-script dangerous switch.
Settings
Settings lives under the account menu (top-right → Settings). It's split into per-user preferences and per-organisation management.
- Profile — your name, sign-in method, email, account-created date, and sign out. GitHub identities can sync their name/username/avatar. Deleting your account lives under an Advanced fold (it's permanent and also removes organisations you own).
- Appearance — theme, and the switch that restores the hidden Flightdeck container section.
- Notifications — which run outcomes reach the bell.
- Organisations — one page per organisation: its members, groups & permissions, shared environment variables & containers, and settings.
- About / Feedback / Legal.
Preferences
Preferences are per browser, not shared across users or devices:
- Theme — dark (default) or light. The run terminal stays dark either way, since logs read best on a dark surface. The quick toggle in the top bar flips the same setting.
- Flightdeck containers — a switch that brings back the hidden app-shipped default containers.
Example scripts
These use only existing Flyghtdeck features — parameters, secrets resolved with
{{KEY}} references, build steps and Docker access. Remember that a run's
environment variables are exactly its parameters: each example lists the parameters to
define, with secrets arriving as parameter defaults like {{GIT_TOKEN}}.
Check out a private git repository
Use a container whose build steps install git. Store a personal access token in
a secret named GIT_TOKEN, then give the script two parameters:
REPO (text, mandatory — e.g. yourorg/private-repo) and
GIT_TOKEN (text, default {{GIT_TOKEN}}).
set -euo pipefail
# REPO and GIT_TOKEN are parameters; GIT_TOKEN's default resolves your environment secret.
git clone "https://${GIT_TOKEN}@github.com/${REPO}.git" repo
cd repo
echo "Checked out $(git rev-parse --short HEAD)"
git log -1 --oneline
Build & push an image using secrets
Requires a container with Docker access on and git in its
build steps. Store REGISTRY_USER and REGISTRY_TOKEN as secrets, and
define parameters REPO, REGISTRY_HOST, TAG (default
latest), plus REGISTRY_USER/REGISTRY_TOKEN defaulting
to their {{…}} references.
set -euo pipefail
echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY_HOST}" --username "${REGISTRY_USER}" --password-stdin
git clone "https://github.com/${REPO}.git" repo
cd repo
docker build -t "${REGISTRY_HOST}/${REPO}:${TAG}" .
docker push "${REGISTRY_HOST}/${REPO}:${TAG}"
echo "Pushed ${REGISTRY_HOST}/${REPO}:${TAG}"
Back up a Postgres database to S3
Build steps: apt-get install -y postgresql-client awscli. Store
DB_PASSWORD, AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
as secrets and default the matching parameters to their references — the AWS CLI picks the
key variables up automatically. Plain-text parameters: DB_HOST,
DB_NAME, DB_USER, BACKUP_BUCKET.
set -euo pipefail
stamp="$(date +%Y%m%d-%H%M%S)"
dump="/tmp/${DB_NAME}-${stamp}.dump"
pg_dump "postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:5432/${DB_NAME}" -Fc -f "${dump}"
aws s3 cp "${dump}" "s3://${BACKUP_BUCKET}/"
echo "Backed up to s3://${BACKUP_BUCKET}/${DB_NAME}-${stamp}.dump"
{{KEY}}, and let the run inject them as environment variables.
Mark anything destructive (like truncating or dropping data) as a dangerous
script so every run needs a deliberate slide-to-confirm.