Skip to content

Client / TUI

// Official Clientv1.1.1

flowlayer-client-tui is the official terminal client for FlowLayer runtime sessions. It attaches to a running flowlayer-server over WebSocket, then provides one keyboard-first workspace for:

  • service state observation
  • log inspection
  • control actions (start, stop, restart)
  • connection diagnostics and reconnect behavior

Typical quickstart:

Terminal window
flowlayer-server -s 127.0.0.1:6999 -c flowlayer.jsonc
flowlayer-client-tui -addr 127.0.0.1:6999 -token <token>
FlowLayer TUI  Connected
S Start All  X Stop
tab switch panel · ↑↓ navigate/scroll · / filter · esc close filter · i conn info · q quit
Services
Filter: —
— all logs
  billingready
  pingfailed
  usersready
Logs
Filter: —
16:23:51 billing > billing@0.0.1 start:dev
16:23:52 billing [4:23:52 PM] Starting compilation in watch mode…
16:23:52 billing [4:23:52 PM] Found 0 errors. Watching for file changes.
16:23:52 billing [Nest] LOG [NestFactory] Starting Nest application…
16:23:52 billing ready http: http://localhost:3002/healthz
16:23:56 ping failed_start: process exited before ready
16:23:56 users > users@0.0.1 start:dev
16:23:58 users ready http: http://localhost:3003/healthz
16:23:58 [flowlayer] boot: startup ok: 2 running, 1 failed_start

The client is an operator UI process, not part of server orchestration.

CapabilityWhat it does
Session attachmentConnects to ws://<addr>/ws with bearer auth
State renderingDisplays snapshot baseline and live updates
Log workspaceMerges replay + live events in one stream
Control surfaceSends protocol commands for service/session actions
Recovery loopReconnects with bounded exponential backoff

What it is not covered in detail in Known Limits.

The thin-client model separates authority and presentation.

ConcernClient roleServer role
Dependency graphObserve onlyOwn and enforce
Lifecycle transitionsRequest actionsValidate and execute
Runtime stateRender current truthPublish canonical state
Log retention semanticsKeep working bufferDecide replay/retention behavior

Consequences:

  • command results are feedback, not an independent state engine
  • UI never invents hidden transitions
  • multiple clients can coexist without state divergence

The client supports two connection modes.

Direct mode passes connection values explicitly.

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

Use when you read token and bind from fresh server boot output.

Config-based mode loads connection values from JSONC.

Terminal window
flowlayer-client-tui -config flowlayer.jsonc

Expected config values:

{
"session": {
"addr": "127.0.0.1:6999",
"token": "change-me"
}
}

The client reads only session connection values from config.

Step 1

Start the server

Run flowlayer-server first. The TUI only connects after the Session API is already up.

Step 2

Copy the token

Read the session token from the server startup log line. Format: fl_<uuid>.

Step 3

Connect the TUI

Pass -addr / -token directly, or use -config to read connection values from the server config file.

Authentication is bearer-token based and enforced by server endpoints.

Flow:

  1. Start server and capture token from server boot logs.
  2. Pass token via -token or via session.token in -config mode.
  3. Client sends WebSocket upgrade request with bearer header.
  4. Server accepts or rejects based on token validity.
Authorization: Bearer <token>

Token mismatch or missing header prevents session establishment.

After successful connection to /ws, session initialization is ordered.

  1. hello arrives first (protocol metadata, capabilities)
  2. snapshot arrives second (full runtime baseline)
  3. client starts consuming incremental events and sending commands
1.Connect to ws://<addr>/ws with bearer token
2.Server sends hello — protocol version and capabilities
3.Server sends snapshot — full service state baseline
4.Client consumes live events: service_status, log
5.Client sends commands via the same WebSocket connection

The client model combines baseline + increments.

Message typePurpose
snapshotFull baseline for services and session data
service status eventsIncremental lifecycle/state transitions
log eventsLive log stream entries
command ack / resultAcceptance and completion feedback

This is the core rule: baseline from snapshot, then converge with server events.

The UI consumes specific protocol outputs.

SourceWhy the UI needs it
helloconfirm protocol/session metadata
snapshotinitialize service table and statuses
status eventskeep service list in sync
live log eventsupdate logs view in real time
get_logs responsesfill history and replay missing ranges
ack / resultdisplay action acceptance and outcome

The UI also tracks local-only state: selected service, filters, focus panel, modal visibility, footer messages.

Control is protocol-driven, not process-driven.

UI intentCommand
Start selected servicestart_service
Stop selected servicestop_service
Restart selected servicerestart_service
Start whole session setstart_all
Stop whole session setstop_all
Reload log window or replayget_logs

Advanced clients may also use additional protocol calls; see Reference and Protocol.

KeyScopeBehavior
Up / DownFocused panelNavigate services list or scroll logs
TabGlobalSwitch focus between services and logs panels
PageUp / PageDownLogs panelScroll logs by page
/Focused panelStart filter input for active panel
EscGlobalClose filter editor or modal
iGlobalOpen connection info (address, token, connection status)
sServices panelStart selected service when applicable
SServices panelStart all when selection context is global (all logs)
xServices panelStop selected service
XServices panelStop all when selection context is global (all logs)
qGlobalQuit client
Ctrl+CGlobalQuit client

Key intent depends on focus and current selection context.

Two primary panels:

  • services panel
  • logs panel

Navigation pattern:

  1. select panel with Tab
  2. move within panel (Up/Down, paging in logs)
  3. filter focused panel with /
  4. close filter/modal with Esc
  5. inspect connection metadata with i

This model keeps service selection and log confirmation in one loop.

The logs view is stream-oriented.

  • It displays replayed and live entries in one ordered timeline.
  • It deduplicates entries when replay overlaps live delivery.
  • It keeps a bounded working window for operator usability.

The client treats logs as operational context for decisions, not as durable archival storage.

Action semantics depend on selection scope.

ContextKeyCommand
Specific service selectedsstart_service (or restart when state allows)
Specific service selectedxstop_service
Global context (all logs)Sstart_all
Global context (all logs)Xstop_all

This split avoids accidental session-wide actions from per-service context.

Action semantics are request/response based.

ActionRequested by clientDecided by server
StartAsk to transition service/session into running stateValidate dependencies and current state
StopAsk for controlled termination pathApply stop policy (stopCmd or signal path)
RestartAsk for stop/start lifecycle transitionEnforce runtime constraints and command ordering

The client must treat ack and result as authoritative feedback channels.

Reconnect creates a new WebSocket session, not a resumed transport.

Backoff schedule:

500ms -> 1s -> 2s -> 5s (max)

Reconnect sequence:

  1. wait backoff interval
  2. reconnect with auth
  3. wait for hello
  4. wait for snapshot
  5. replay logs using after_seq when available
  6. continue live event processing

All pending commands from previous disconnected socket are invalidated and not auto-replayed.

Log continuity uses a high-water sequence strategy.

ConceptMeaning
seqMonotonically increasing log sequence identifier
lastSeqHighest sequence observed by client
after_seqReplay request cursor used after reconnect
effective_limitServer-provided working-window bound

Replay pattern:

  1. track lastSeq across both replay and live events
  2. on reconnect, request get_logs with after_seq=lastSeq
  3. merge replay with new live events
  4. deduplicate by seq
  5. trim local window using effective_limit

This is how the client recovers missed logs without duplicating rows.

Selection-change behavior for log views:

  • On service change, the visible log pane is cleared immediately.
  • Late historical/replay responses that no longer match the active selection are ignored.
  • This prevents stale or mixed service logs; responses are filtered client-side, not network-cancelled.

Representative failure handling:

ScenarioClient behavior
Invalid flags or positional argsPrint error + help, exit 2
Auth failureConnection fails until token/bind are corrected
Disconnect during pending commandMark pending command as invalidated
Replay overlapDeduplicate by seq
Unknown or unsupported protocol behaviorSurface error context and keep UI stable

Color behavior note: NO_COLOR disables red error coloring in terminal output.

Recommended operator loop:

  1. start server and capture session token
  2. connect client (direct or config-based)
  3. wait for hello + snapshot
  4. inspect blocked/failed services first
  5. inspect related logs before action
  6. send targeted start/stop/restart request
  7. verify server result and resulting state/log output
  8. repeat for next dependency edge

Useful command snippets:

Terminal window
# Server first
flowlayer-server -s 127.0.0.1:6999 -c flowlayer.jsonc
# Direct client attach
flowlayer-client-tui -addr 127.0.0.1:6999 -token <token>
# Config-based attach
flowlayer-client-tui -config flowlayer.jsonc

Two supported operation paths from the source client documentation:

  1. Download the binary artifact for your platform.
  2. Make it executable.
  3. Run with direct or config-based connection mode.
Terminal window
./flowlayer-client-tui -addr 127.0.0.1:6999 -token <token>

Requires Go toolchain and repository checkout.

Terminal window
go run . -addr 127.0.0.1:6999 -token <token>

In both paths, the server must already be running and reachable.

Migration of the original client page contribution guidance:

  • The terminal client implementation is open source and inspectable.
  • UI improvements (layout, keybindings, display behavior) are contribution candidates.
  • The protocol is public, so custom clients (web, IDE plugin, specialized operator UI) can be built without changing server runtime policy.

Useful external references:

Not

An orchestrator

The TUI does not start or manage services itself. All orchestration logic stays in the FlowLayer server.

Not

A log archive

Maintains an in-memory working window bounded by effective_limit. Scrolling past the top of the buffer transparently loads older history via get_logs with before_seq; for durable retention beyond the server’s ring buffer, use logs.dir.

Not

A source of truth

Service state is server-owned. The TUI never invents state from command results — it only renders what the server reports.

Not

A config authority

Only reads session.addr and session.token from config. Does not interpret service definitions or server settings.

Also out of scope:

  • Not a multi-runtime coordinator in one client instance.
  • No automatic replay of orphaned pending commands after disconnect.