ardaplayer
reference.

One binary does every job: it is the runtime on a device, the developer's window on a desk, the USB installer's engine and the boot logo. This page is its command line — every flag, the developer settings file, the folder layout and where each build runs. ardaplayer -h prints the same, grouped and wrapped to your terminal.

Working — v1.2.3

The shape of a call

Day to day you need one command, ardaplayer -dev myapp/. Everything else on this page is for devices, installers and special cases — look it up when you need it.

Flags and the application path may come in any order. A path names an application directory — the folder that holds app/. Refusals come as error: with the fix on its own line; the flag package's own usage dump is switched off so a mistyped flag gets the same shaped answer.

shell
$ ardaplayer -dev myapp/                 # develop: a window, local, nothing dialled
$ ardaplayer -dev -device -console myapp/ # develop as a real device, inspector open
$ ardaplayer -headless myapp/            # the same app with no screen at all
$ ardaplayer -kiosk                      # what the device's service runs
$ ardaplayer -h                          # the help, grouped as below
i
There is no separate CLI for the control plane Deploying, adopting devices, settings and support all happen in the portal, and a release reaches devices because you pushed a commit to a connected branch. ardaplayer is the device's own program; these flags are how you drive it on a desk and how the device's service starts it.

Developing

ardaplayer -dev DIRWorking

Developer mode: app/ is unencrypted source, the window is sized rather than fullscreen, and arda.dev.json in the application directory is read. Local by default — the stores open and the app runs, but no control plane is dialled and nothing is registered; Arda.device().phase reads local. An encrypted container is refused before any file beside it is read.

ardaplayer -dev -device DIRWorking

Dial the control plane and enrol this app's own identity: each application directory is its own device, with its keypair under DIR/state/. The activation code appears in the terminal and in the window; claim it in the portal and the app syncs, receives settings and shows in the device list like any other. Also "device": true in the file.

-watchWorking

Reload the page whenever a file in app/ changes. Developer mode only, and off unless asked for.

-consoleWorking

Open the inspector at start — in developer mode and on the activation screen, never on an encrypted package. Off unless asked for; Inspect is a right-click away regardless, on every window.

-window WxHWorking

The app's screen size, e.g. 1280x800, in a window instead of fullscreen. Developer mode defaults to 1280x800. This is the app's screen: window.innerWidth is what you asked for.

-scale FACTORWorking

Draw the window at this fraction of its size, 0.75 or 75%. The app still gets the full -window resolution and is only shown smaller — for designing against a screen bigger than the one in front of you. A bare number is a factor: 2 is 200 %. Anything outside 0.1–10 (10 %–1000 %) is refused, so -scale 75 is an error, not 75 %. Ignored, and said so, on a bare screen.

-bg COLOURWorking

The screen's colour before the app has painted anything, and wherever a page paints none of its own. Any CSS colour; the default is black, because the engine's own white is a full-screen flash at every boot. A page that sets no background at all is given white, as a browser would.

-chromeWorking

Open the app in a Chrome-family browser even when this build carries a webview. On macOS it is the only way to a remote page debugger.

-cogWorking

Open the app in cog — WPE WebKit drawn straight on the DRM card, the runtime every device uses — even when X is installed; on a Wayland desktop that is a window, the device's exact engine on your desk. Without the flag the rule is: X or Wayland when there is one, cog when there is no display server at all.

-plane URL, -plane-ca FILE

For ArdaForm's own testing of a new server: dial another control plane, and check its certificate against a PEM file. They work only with a player built for that server. Leave them out.


Running a device

ardaplayer -kioskWorking

Device boot, what the installed service runs: fullscreen on every connected screen, the app optional — with none the activation screen is shown. A usable screen gets the boot screen; no screen means the same lifecycle headless, and a screen that appears later is noticed. The kiosk also does the boot duties on a Raspberry Pi image — the display-panel probe against config.txt, the Wi-Fi profile guard — and is a no-op for both on any other machine.

ardaplayer -headless [DIR]Working

No window at all: the device lifecycle only, for services and test rigs. Given an application directory it runs the app in the player's own JavaScript runtime with the same window.Arda and no DOM — Arda.headless is true before the first line, document throws with the fix named, and <script type="module"> is skipped with a warning.

ardaplayer -installer DIRWorking

The USB installer stick: run the install app in DIR fullscreen with the disk-writing engine armed and no control plane dialled. DIR is an ordinary application directory; the payload description and the device image sit in the directory above it. In developer mode the engine is a simulation with the real refusals, so the install app is developed like any other.

-claim CODEWorking

A portal-minted install code, for a device that has not enrolled. The same code the installer stick writes to the device; a refused code falls back to the on-screen activation code in the same session.

-inspectWorking

Run as a device without a screen of its own: the portal's Device view, terminal and ssh are offered. A kiosk does this by itself; the flag is for a desk run you want to reach from the portal. Only the Linux desktop build also arms WebKit's page debugger on loopback — device builds carry none.

-bleWorking

Advertise over Bluetooth even when activated, for diagnostics. An unactivated device advertises by itself, and an activated one starts again after five minutes offline.

-mirrorWorking

Keep storage/ exactly what the server says: files added by hand are deleted on every sweep. The default leaves them alone.

ardaplayer -unbind [DIR]Working

Remove this device and exit: erase its identity and datasets — and, on a live device, the deployed app — and remove it from the control plane. A live device asks for its device password, the eight characters shown on the portal's device screen; a developer device (-unbind myapp/) does not. The plane forgets first and the device erases itself only once that is confirmed, so an interrupted unbind is safe to run again.


Other

ardaplayer -installWorking

Make this machine a device: move the executable to the system location, install and enable the start-at-boot service running -kiosk, and exit. Linux only; elsewhere it prints what it would do. The images and the USB stick have already done this.

ardaplayer -splash LOGOWorking

Paint this picture (PNG or JPEG) on the Linux framebuffer and exit — the device image's boot logo until the app draws. Waits up to 20 s for the framebuffer.

ardaplayer -correct DIRWorking

Restructure a bare folder of pages into an application directory: its content moves into app/, and data/ and storage/ are created. Then exit.

-id · -version · -v

Print this machine's hardware id and exit; print the version and exit; debug logging.


arda.dev.json

A JSON file in the application directory — beside app/, never inside it — holding the developer's settings for that app, so a working session is ardaplayer -dev myapp/ and not a line of flags. Read in developer mode only. The command line wins over the file; an unknown key is refused with its name rather than ignored. It is never packed, and a device that finds one refuses to start — it decides the player's own window, screens and what the machine claims to have, and a device must not take that from an app folder.

KeyExampleMeaning
window"1280x800"The app's screen size (-window).
scale"75%"Drawn at that fraction; the app keeps its resolution (-scale).
bg"#000000"The colour before the app has painted (-bg).
consoletrueOpen the inspector at start (-console). Off by default.
watchtrueReload the page on every save (-watch). Off by default.
devicetrueDial the control plane and enrol this app's own identity (-device). Off by default — a local run touches no server.
can{"touch": true, "keyboard": false}What the app is told this machine has — screen, keyboard, mouse, touch, audioOut, audioIn, each true or false. A touchscreen layout on a desk with a mouse. false and absent are different answers; the control plane is still told the truth. No input is synthesised — write against pointer events.
screens[{"name": "main", "primary": true}, {"name": "attendance", "size": "800x480", "console": true}]The screens to pretend this machine has. The first (or the one marked primary) is the app's own; the rest open as windows and are what Arda.screen['name'] addresses.
plane, planeCAFor ArdaForm's own testing (-plane, -plane-ca). Leave them out.
partition"till-1"The data partition this run stands in: a dataset whose manifest names a partition field is filtered to records with this value.
settings{"currency": "EUR"}Your own values for the app's settings, over the manifest's defaults — what Arda.config answers on a local run.
devices{"wifi": {"enabled": true, "networks": [{"ssid": "shop", "key": "secret"}]}}Peripherals this machine pretends to have. Arda.wifi lists those networks and checks the key exactly as a real radio would; given, the pretend radio stands in even on a machine that has one.
webhooks[{"slug": "orders", "url": "http://localhost:8080/hook", "method": "post", "key": "dev"}]Stand-ins for the project's webhooks. Arda.webhook.call(slug, data) calls these URLs from this machine with the same body, headers and signature ArdaForm would send, so a receiver can be written with no control plane in reach. Used on a local run only: with the device on, a call goes through ArdaForm like any device's. On a local run a slug not in the list is refused by name.
arda.dev.json example
{
  "window": "1280x800", "console": true, "watch": true,
  "can": { "touch": true, "keyboard": false, "mouse": false },
  "screens": [ { "name": "main", "primary": true },
               { "name": "attendance", "size": "800x480" } ],
  "partition": "site-1",
  "settings": { "kiosk_name": "Front desk" }
}

The folder layout

an application directory
myapp/
  app/              the WHOLE app — index.html at its root and every asset it uses.
    index.html      The player never writes here. This is what gets packed.
    manifest.json   optional: datasets, settings, files the app waits for
  arda.dev.json     your desk's settings (developer mode only, never packed)
  seed/             optional: <dataset>.json loaded into an EMPTY store on a local run
  state/            the device identity — created when the device is turned on; keep out of git
  data/             the player's area: sealed datasets and the outbox; not the app's to touch
  storage/          synced files, served to the app at /storage/<path>; read-only content

Everything the player persists is sealed with a key derived from the device's identity and an identifier that stays with the board. Copy the SD card into another machine and none of it opens — which is why moving a card between devices is not a migration path.

Environment

VariableEffect
NO_COLORPlain output, per the no-color convention. Colour is used only where the stream is a terminal anyway; a log file never sees an escape code.
INVOCATION_IDSet by systemd. A player started by hand refuses the operations that restart the process — a timezone change, applying a player update — because stopping a hand-started player would be a device that simply went away.

The control plane endpoint and its keys are fixed at build time; there is nothing to configure and no token to keep on a workstation. A device holds its own identity and nothing else.

Builds and platforms

All builds come from the portal's Downloads page, each beside its size and version.

DownloadWhat it is
Device player · Linux x86-64 / ARM64The fleet binary: pure Go, draws through cog on the bare display card, no X and no browser. Devices update themselves to it when a release is published.
Linux desktopThe developer's build for a Linux desk: the same player with a WebKit window and the inspector.
Windows · macOS (Apple silicon, Intel)Development platforms. The app opens in a Chrome-family browser when one is found, otherwise the system browser; the window closing is then invisible, so the player runs until Ctrl-C and says so.
Raspberry Pi imageA card image for the Raspberry Pi 3 and 4: Raspberry Pi OS Lite, cog, the player, no desktop. Boots to the activation screen; a Waveshare DSI panel is detected at boot.
PC imageA disk image for x86-64 machines — Debian, cog, the player, UEFI and BIOS boot. First boot grows the root and mints host keys.
USB installerA stick that boots into the player running an install app: pick the disk, name the machine, Wi-Fi, an install code, and about a minute later the machine boots alone as itself.

Published images carry no credentials of any kind. The only way into a fresh device is the portal — the SSH tab through the device's own tunnel — or Bluetooth while it waits to be adopted.