Start

First run in the app

What the window shows when it opens, how the composer and approvals work, and what closing it stops.

The window opens before the engine is ready

shoal desktop draws the window first and builds the engine behind it. The boot animation plays while that happens: a shoal of particles gathers into the wordmark, the lamp comes on, and the returning beam ignites the letters. A click or any key skips it, and it plays again on every new session.

Startup narration streams into the page one line at a time, so a window waiting on a model to load says what it is waiting for. Until the engine exists the page serves and narrates, and anything the client sends is refused with a plain “engine still starting” rather than dropped in silence.

An unconfigured launch opens the mooring form

When no model resolves from a flag, the project config, or the user-wide config, the engine starts unmoored. It comes up on a provider that refuses every call by name, and the window says the same thing in words: no model is moored, pick one from the mooring form.

The form opens itself once, after the boot animation finishes rather than over it. It carries a first-run frame around the ordinary form: the same fields, the same validation, and the same dock catalogue the engine sends with the fleet, under a heading that says what is being asked. Pick a dock and a model, save, and the session moors without a restart. The record goes to config, so later launches on a local or remote dock run on it quietly. An anthropic record is not applied at launch, because launching straight onto an offshore mooring is not built, so that session comes up unmoored again and /moor ties it up.

Setup asks the same question at install time, so an ordinary double-click never meets this form at all.

The transcript and the composer are the whole surface

Finished output stacks in the transcript above the composer. Long tool output and long diffs fold to a short preview with a count on the expander, so one large result does not bury the conversation around it.

The composer sits at the bottom. Enter sends, Shift with Enter makes a newline, and the send button becomes a stop button while a turn is running. Escape closes an open menu first and cancels the turn second.

Typing a single slash into an empty composer opens the command menu above it, and every keystroke after that narrows the list. Anything that is not a lone slashed word closes it again. The menu lists each command with its description and its keyboard shortcut, and the same menu opens from the button beside the composer.

Approvals arrive as cards carrying a diff

When a tool needs permission, a card appears with the tool name, a plain description of the call, and the diff the engine computed for the edit-class tools. Three buttons answer it: approve, always, and deny. Always allows that tool for the rest of the session.

The default mode is manual, which asks about everything. The other modes answer some classes of call for you, and every automatic answer is written into the transcript as a notice rather than applied in silence. Alt with G is the safety catch: one press drops to manual from wherever you were, the next press restores what you had.

Sessions are shared with the terminal

The window reads and writes the same SQLite session store the terminal uses, under your user data directory. The recents picker in the header lists stored sessions with the most recently touched first, marks the one you are in, and opens any other. Each row carries a count of what that session delegated, and that count opens the sub-agent roster scoped to it.

A session started in a terminal is therefore waiting in the window, and one started in the window is waiting in the terminal.

Closing the window shuts Shoal down

Closing the window ends the process, but not the instant it disappears. The bridge waits five seconds after the last window disconnects, which is what makes a refresh safe: a page that comes back inside that grace replays the recent event ring and keeps its transcript.

The inference server follows the usual ownership rules on the way out. A server started by shoal up was never this session’s to stop, so it keeps running with the model loaded. A server this session spawned stops with it.