FlowLayer Client
Terminal UI for FlowLayer. The official terminal client connects to a running server over WebSocket and provides a deterministic local view of service state, live logs, and runtime controls.
Terminal Observability Client
The TUI connects over WebSocket to a running FlowLayer server and provides a local view of service state, live logs, and runtime controls. It is a thin client — all business truth stays in the server.
Two ways to connect
Pass -addr and -token directly, or use -config to read session.addr and session.token.
16:23:50 ping [stderr] Commands:
16:23:50 ping [stderr] attach Attach local standard input, output, and error streams to a running container
16:23:50 ping [stderr] build Build an image from a Dockerfile
16:23:50 ping [stderr] exec Run a command in a running container
16:23:50 ping [stderr] images List images
16:23:50 ping [stderr] run Run a command in a new container
16:23:51 billing > billing@0.0.1 start:dev
16:23:51 billing > nest start --watch --preserveWatchOutput
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 [Nest] LOG [InstanceLoader] AppModule dependencies initialized +6ms
16:23:52 billing [Nest] LOG [RoutesResolver] AppController {/}: +2ms
16:23:52 billing [Nest] LOG [RouterExplorer] Mapped {/health, GET} route +2ms
16:23:52 billing [Nest] LOG [RouterExplorer] Mapped {/healthz, GET} route +0ms
16:23:52 billing [Nest] LOG [RouterExplorer] Mapped {/, GET} route +1ms
16:23:52 billing [Nest] LOG [NestApplication] Nest application successfully started +1ms
16:23:52 billing ready http: http://localhost:3002/healthz
16:23:56 ping failed_start: ready tcp: process exited before ready
16:23:56 users > users@0.0.1 start:dev
16:23:56 users > nest start --watch --preserveWatchOutput
16:23:56 users [4:23:56 PM] Starting compilation in watch mode...
16:23:58 users [4:23:58 PM] Found 0 errors. Watching for file changes.
16:23:58 users [Nest] LOG [NestFactory] Starting Nest application...
16:23:58 users [Nest] LOG [InstanceLoader] AppModule dependencies initialized +7ms
16:23:58 users [Nest] LOG [NestApplication] Nest application successfully started +1ms
16:23:58 users ready http: http://localhost:3003/healthz
16:23:58 [flowlayer] boot: startup ok: 2 running, 0 oneshot succeeded, 1 failed_start, 0 blocked
Installation
download Download binary
Download the prebuilt binary for your platform from GitHub Releases. Binaries are available for Linux, macOS, and Windows on amd64 and arm64.
# Download and run directly
./flowlayer-client-tui -addr 127.0.0.1:6999 -token <token>
code Run from source
For development or contributions. Requires Go.
# Run from source (server already running)
go run . -addr 127.0.0.1:6999 -token <token>
Connecting to the Server
The TUI supports two connection modes: Direct with -addr and -token, or Config with -config (reads session.addr and session.token).
1
Start the server
Run the server first. The TUI only connects after the Session API is already up.
2
Copy the token from the server logs
Read the token from the server startup log line and keep that exact value.
3
Connect with -addr / -token or -config
Pass flags directly, or use -config to read connection values from the server config.
Standard usage
The flow is always the same: start the server, copy the token from the server logs, then connect the TUI with -addr and -token.
# 1. Start the server
flowlayer-server -s 127.0.0.1:6999 -c flowlayer.jsonc
# 2. Copy the token from the server logs
[flowlayer] boot: session token: fl_abc123
# 3. Connect the TUI with -addr and -token
flowlayer-client-tui -addr 127.0.0.1:6999 -token <token>
Flags reference
-addr <host:port> Address of the running server. Required.
-token <token> Session token printed by the server at startup. Copy it from the server logs and pass it here.
-config <path> Path to a FlowLayer config file. The TUI reads session.addr and session.token.
-h, --help Print help and exit.
--version Print flowlayer-client-tui 1.0.0 and exit.
Bare invocation launches the TUI. Unknown flags or positional arguments print an error and the help, exit 2. NO_COLOR disables red error coloring.
Configuration file
Use -config to load connection values from JSONC.
{
"session": {
"addr": "127.0.0.1:6999",
"token": "change-me"
}
}
Use session.addr for TUI connections.
# Launch with config
flowlayer-client-tui -config flowlayer.jsonc
Keybindings
| ↑ ↓ | Navigate services / scroll logs |
| Tab | Switch focus between panels |
| Page ↑ ↓ | Scroll log panel by page |
| / | Start filter on focused panel |
| Esc | Close filter or modal |
| i | Connection info (address, token, status) |
| s | Start / restart selected service |
| x | Stop selected service |
| q | Quit the TUI |
Connection & Message Flow
The TUI keeps local UI state only (selection, filters, busy hints, footer messages). Service truth comes entirely from server messages.
ws://<addr>/ws with bearer tokenhello (protocol version, capabilities)snapshot (full service state)service_status, loghub State model
The TUI uses snapshot for the full initial state, then applies service_status events as incremental updates. The server is the single authority. Command results provide user feedback only — they do not invent state.
bolt Available commands
start_service / stop_service / restart_service
start_all / stop_all
get_logs — used for initial load and replay after reconnect
Additional protocol capabilities such as get_snapshot exist for custom clients. See Protocol reference.
info No HTTP/SSE path
All communication uses the single WebSocket connection at /ws. There is no HTTP polling or SSE path in the current TUI.
Log Model
Logs are an ordered stream, not a static dataset. The TUI merges live events with historical replay into a continuous operator view.
sort
Sequence cursor (seq)
Every log entry has a globally unique, monotonically increasing seq. The TUI tracks lastSeq as the highest sequence seen across both live events and replay responses. This is the high-water mark for log continuity.
merge Deduplication
The same log entry can arrive via live log event and via get_logs replay. The TUI deduplicates by seq, maintaining a seen-set to prevent duplicate rows when replay overlaps with live delivery.
memory
Buffer size (effective_limit)
The TUI never computes log limits locally. It sends get_logs without a limit field, receives effective_limit from the server, and uses that value to trim its local buffer. All retention decisions are server-driven.
warning Best-effort delivery
Live log events are best-effort. If the TUI is slow, the server may drop log events silently. The TUI uses get_logs with after_seq to recover gaps after reconnection.
Reconnect Behavior
The server does not persist sessions. A reconnection is a completely new session — the TUI performs a full handshake and replays logs from lastSeq.
Backoff schedule
500ms → 1s → 2s → 5s (max)
All pending commands are invalidated on disconnect. The server has no mechanism to deliver responses across sessions.
Exponential backoff
Wait, then attempt reconnect. 500ms → 1s → 2s → 5s max.
Full handshake
Wait for hello, then snapshot.
Log replay
If lastSeq > 0: send get_logs with after_seq=lastSeq.
Merge & deduplicate
Merge replayed entries with any live events received in the meantime. Deduplicate by seq.
Pending commands are dropped
Commands awaiting ack or result are orphaned at disconnect. The TUI marks them as failed and does not auto-retry.
What the TUI Is Not
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. For durable log retention, use logs.dir on the server.
Not a source of truth
Service state is server-owned. The TUI never invents state from command results — it only displays what the server reports.
Not a source of config truth
The TUI only reads connection values from config via -config: session.addr and session.token. It does not read or apply service definitions or server settings.
Contributing
Source exploration
The TUI is open source. Read the code to understand how log deduplication, reconnect backoff, and state merging work in practice.
github.com/FlowLayer/tui open_in_newUI contributions
Improvements to layout, keybindings, log display, or status presentation are welcome. Open an issue to discuss first.
Open an issue open_in_newAlternative clients
The FlowLayer protocol is public. You can build your own client — a web UI, a plugin, an IDE integration — using the same WebSocket protocol. The only requirements are a WebSocket library and a JSON parser.
Protocol reference arrow_forward