flowlayer
// Server Runtime v1.0.0

FlowLayer Server

The FlowLayer server runtime: single binary that loads your config, orchestrates services, exposes the Session API, and streams logs and state in real time.

Quickstart

flowlayer-server -c flowlayer.jsonc -s 127.0.0.1:6999

flowlayer-client-tui -addr 127.0.0.1:6999 -token <token>

flowlayer-client-tui -config flowlayer.jsonc

The Orchestration Engine

The FlowLayer server is a single binary that reads a JSONC config, builds a dependency graph, launches services in the correct order, and exposes a live Session API.

check Source of truth for process state, orchestration, and logs
check Exposes Session API (/ws, /health) for clients
check Engine source is closed; protocol and config reference are public
close Does not restart crashed services automatically
close Not a production supervisor — designed for development sessions
dns

Two-binary architecture

dns Server flowlayer-server

Orchestration engine. Owns service state, lifecycle, logs, and Session API.

terminal TUI flowlayer-client-tui

Official client. Connects over WebSocket. Observer and control surface. Separate binary.

Protocol: WebSocket V1 — public spec, open to custom clients

Config: JSONC — see Configuration for full reference

CLI Usage

FlowLayer is invoked as a single command. All flags are optional — the binary auto-discovers a config file in the current directory when no path is specified.

synopsis
flowlayer-server [-c <path>] [--config <path>] [<path>] [-s <bind>] [-token <value>] [--no-color] [-h|--help] [--version]

router Session API bind — -s <bind>

Enables the Session API. Accepts host:port, :port, or a bare port number. CLI overrides session.bind from config.

-s 6999→ 127.0.0.1:6999 (localhost)
-s :6999→ :6999 (all interfaces)
-s 192.168.1.10:6999→ specific interface

vpn_key Token — -token <value>

Bearer token override. Overrides session.token from config. When the Session API is enabled but no token is set via CLI or config, the server auto-generates one.

Token priority: -token flagsession.token configauto-generated fl_<uuid>

palette Color output — --no-color

--no-color Disables ANSI color output.
NO_COLOR Environment variable. Any non-empty value disables color.

If neither is set, color is enabled only when stdout is a TTY.

info Version — --version

--version Prints flowlayer-server 1.0.0 and exits immediately. No config file is required.

help Help — -h / --help

-h --help flowlayer-server with no arguments and flowlayer-server -h / --help print the same onboarding help and exit with code 0.

error Error behavior

Error: <message> Invalid CLI/config input prints Error: <message>, then the full help, and exits with code 2.

Config Path Resolution

folder_open Priority order

Resolved in descending priority. Using both -c and --config simultaneously is an error. More than one positional argument is an error.

1. -c <path>
2. --config <path>
3. Positional argument
4. Auto-discovery (see right)

search Auto-discovery order

Scans the current directory in this order when no explicit path is given:

1.flowlayer.jsonc
2.flowlayer.json
3.flowlayer.config.jsonc
4.flowlayer.config.json

If no config is found, FlowLayer exits with code 2.

Configuration

The Session API is configured in your JSONC file via session.bind and session.token.

{

  "session": {

    "bind": "127.0.0.1:6999",

    "token": "change-me"

  }

}

Open configuration reference open_in_new

Session API

When enabled through -s or session.bind, the server exposes two authenticated endpoints. The HTTP server starts during boot, before services are launched.

favorite GET /health

Liveness endpoint. Returns {'\"ok\": true'} when the server is running.

Requires: Authorization: Bearer <token>

cable GET /ws

Upgrades to a WebSocket session using the FlowLayer V1 protocol. On connection the server sends hello then snapshot.

See Protocol for the full message spec

settings Session API lifecycle

Activation

CLI -s takes precedence over session.bind. If neither is set, no Session API is started.

Startup

HTTP server starts before service wave execution. If the bind address is unavailable, FlowLayer exits immediately with an error.

Shutdown

On SIGINT/SIGTERM, the HTTP server stops first (2-second grace for in-flight requests), then services are torn down in reverse dependency order.

Bearer Token Auth

Every Session API request requires a bearer token. There are no public endpoints — authentication is enforced on all routes including /health and /ws.

Token priority

1. -token CLI flag

2. session.token config value

3. Auto-generated: fl_<uuid>

The token is ephemeral and printed in boot logs. It is a session-level gate for a development tool, not a production credential.

Request header

Authorization: Bearer <token>
auth responses
Condition HTTP Status
No Authorization header401 Unauthorized
Header present, token does not match403 Forbidden
Valid tokenRequest proceeds
$ flowlayer-server -c flowlayer.jsonc
[flowlayer] boot: session token: fl_d4e5f6a7-b8c9-4d0e-a1b2-c3d4e5f6a7b8
[flowlayer] boot: session API: 127.0.0.1:6999 (/ws, /health)

DAG + Wave Execution

At boot, FlowLayer validates the config, builds a dependency graph, and prints the execution plan before starting any service. Same config always produces the same order.

boot.output

$ flowlayer-server -c flowlayer.jsonc

[flowlayer] boot: validating config and graph...

[flowlayer] boot: session API: 127.0.0.1:6999 (/ws, /health)

[flowlayer] boot: DAG computed — 3 nodes, 2 waves

[flowlayer] boot: wave 0 │ billing → starting

[flowlayer] boot: wave 0 │ ping → starting

[flowlayer] boot: wave 0 │ billing → ready (http :3002/healthz)

[flowlayer] boot: wave 0 │ ping → ready (tcp :8088)

[flowlayer] boot: wave 1 │ users → starting

[flowlayer] boot: wave 1 │ users → ready (http :3003/healthz)

STARTUP COMPLETE — runtime active

account_tree DAG

Built from dependsOn declarations. Cycles cause immediate failure. Validated once at boot — never recomputed at runtime.

waves Waves

Services in the same wave start concurrently. The next wave begins only after all services in the current wave reach their terminal startup state (running or ready).

bolt Runtime commands

After boot, clients can send start_service, stop_service, and restart_service via the WebSocket API. See Protocol for the full command reference.

Shutdown Behavior

mop

Graceful shutdown sequence

01.

Session HTTP server stops. 2-second grace period for in-flight requests.

02.

Services torn down in reverse dependency order.

03.

Per-service: if stopCmd is defined, it runs instead of SIGTERM.

04.

If no stopCmd: SIGTERM sent to the process group. 8-second wait for I/O flushing.

05.

Any remaining processes receive SIGKILL.

stop_circle stopCmd

Accepts string | string[]. When present, FlowLayer runs this command instead of sending SIGTERM to the process group. Runs with the same effective environment as cmd, including service env overrides. Useful for Docker Compose and similar runtimes that need an explicit stop command.

warning Trigger

Graceful shutdown is triggered by SIGINT or SIGTERM received by the FlowLayer process.

Track-Only Guarantee

FlowLayer maintains a registry of every process it spawns and will only ever signal processes in that registry. External processes are never touched. This guarantee prevents accidental interference with other running processes on the machine.

TRACKED

Signals and lifecycle management apply only to registered PIDs.

EXTERNAL

Unregistered processes remain untouched and unaware.

monitor_heart Runtime principles

  • check_circle

    Deterministic

    Same config, same order, every time. The execution plan is computed once and printed at boot.

  • check_circle

    Explicit

    Commands are executed directly — no shell is invoked. Shell operators (&&, |, redirections) are not interpreted. To use shell features, invoke a shell explicitly: ["sh", "-c", "..."]. See Configuration → cmd for details.

  • check_circle

    No automatic restart

    FlowLayer does not restart crashed services. An unexpected daemon exit transitions the service to failed.

Participation

Bug reports, feature requests, and roadmap discussion happen on GitHub Issues. The engine source is not public, but the protocol and config reference are, and alternative clients are welcome.