Reference

Commands

Every command the shoal binary answers to, with its options and the help it prints.

This page is generated from the binary. Each command below, every flag, every default, and every line of help is read out of the program at version 0.32.0 rather than written beside it, so a reference that disagrees with what runs on your machine is a build failure rather than a page nobody noticed.

The extension runs these for you. It spawns shoal proto and talks to it, so the commands here are what you reach for when you set the machine up, check what it found, or manage a server outside the editor.

The app window is shoal desktop. The rest of these commands are what you reach for when you set the machine up, check what it found, or manage a server that outlives a single window.

shoal

Shoal - a local-first coding agent

Shoal is a coding agent that runs on your own hardware. It manages the inference server itself, keeps history stable for the server's prefix cache, asks before writes and shell commands, and delegates subtasks to fresh-context sub-agents. Cloud APIs are optional, never required. Install once: shoal setup. Save a default model: shoal config set model <name>. After that, a bare shoal in any terminal is enough. Server lifecycle: shoal up, shoal down, shoal doctor, shoal models. Docks (where models tie up): - mlx: Apple Silicon via mlx_lm.server (macOS only) - llamacpp: NVIDIA CUDA / Metal via llama-server (all platforms) - remote: an OpenAI-compatible server you run, here or on another box - anthropic: Anthropic's API, reached by a mooring record with your key - openai: OpenAI's API, reached by a mooring record with your key
Flag Type Default What it does
--auto-approve bool - Approve write/exec tool calls without prompting (required for -p mode to use them)
--dock string - Inference dock: mlx, llamacpp, remote (auto-detected if omitted)
--endpoint string - Skip server management, use this OpenAI-compatible endpoint
--hitl bool true Ask before a decomposition plan is accepted (default: on)
--index bool - Rebuild the project chart and exit
--model string - Model identifier
--prompt , -p string - Non-interactive: run single prompt and exit
--resume string - Resume a previous session by ID or unique prefix
--version , -v bool - version for shoal

Those options except --version are persistent: --auto-approve, --dock, --endpoint, --hitl, --index, --model, --prompt, --resume can be given to any command below as well, not only to a bare shoal.

shoal audit

What a session touched, read and produced

audit reads the row log: one append-only record per tool call, per agent loop and per model call, written under the data directory and outliving the session that wrote it. shoal audit index every session in the log shoal audit --session <id> one session shoal audit --day 2026-09-01 one day shoal audit --json the same index as one JSON object shoal audit --store where the log lives and what it costs It is an index, not a transcript. It says which files were read, written and failed, which calls were refused, what the model calls cost, and how much of the window was in use. It does not carry tool arguments or results: a row is a fact about a call, not a copy of it. The log is on by default and shoal config set rowlog off stops it.
Flag Type Default What it does
--day stringSlice [] one or more days, as 2026-09-01
--json bool - print the index as JSON
--main-only bool - leave out what delegated children did
--session string - one session id
--store bool - print where the log lives and what it costs

shoal berth

Run the agent loop here for a surface on another machine

berth runs the engine on this machine and listens for one surface to drive it. The loop, the tools, and the workspace are here; a person sitting at another machine runs "shoal connect" or "shoal desktop --berth" and works in this tree. The default listen address is 127.0.0.1, which reaches nothing but this box. Reaching further is an address you type: --listen 0.0.0.0:7823 offers the berth to your network. Every connection is authenticated and every connection is TLS. The token lives in the secrets store under "berth_token"; --mint-token generates and saves one on the way up. The certificate is self-signed and kept in `~/.shoal/berth/`, and the client pins its fingerprint, which this command prints. Nothing dials out and there is no relay: a berth behind NAT is reached through your own network. A dropped connection does not stop the engine. Nobody attached for the linger period does: --linger 0 keeps it up until you stop it.
Flag Type Default What it does
--cert-host stringSlice [] Extra hostnames or addresses the self-signed certificate should answer to
--linger duration 15m0s Shut down after this long with nobody attached; 0 never does
--listen string 127.0.0.1 Address to listen on; a bare host takes the default port
--mint-token bool - Generate a token, save it under the secret name, and print it once
--tls-cert string - Use this certificate instead of the self-signed one
--tls-key string - Private key for --tls-cert
--token-secret string berth_token Name of the secrets-store entry holding the berth token

shoal board

The metrics board: did the window hold, and what did it cost

board renders one session's telemetry from the row log: whether the window held, what the tools did, what landed, and what it cost. shoal board the last real session (eval runs skipped) shoal board --session <id> a named session shoal board --json the same board as one view-model JSON object shoal board --with-eval fold in rows a benchmark run tagged eval The spine is window-first: size, peak in use, drops, then activity, and spend leads only where a mooring carries real prices. Rows the eval runner tagged source=eval are excluded by default and the board says how many it left out. It reads the same log shoal audit reads. The audit is the trail and never filters; the board is the view and says what it excluded.
Flag Type Default What it does
--json bool - print the view model as JSON
--session string - one session id (default: the last session with a non-eval row)
--with-eval bool - include rows tagged source=eval

shoal config

Show or set user-wide defaults (model, dock, endpoint, breakwater, trust, rowlog, memory, voyage)

config manages the user-wide defaults so shoal runs without flags. shoal config show the current defaults shoal config set model <name> set the default model shoal config unset model clear a default Keys: model, dock (mlx, llamacpp, remote), endpoint, breakwater, trust, rowlog, memory, voyage. breakwater is open or closed, and closed is the default even when the key is unset. Closed means Shoal's own code reaches loopback and the destinations a mooring names, and refuses every other one. Open takes that wall down. shoal doctor prints which it is and what is named. trust is the label a mooring gets when its own record carries none. Unset is the default and means unlabelled, which is the full toolset, exactly as before this key existed. Set it to unvetted to say you have not vetted the models on this machine: every unlabelled mooring then runs on the read-only toolset and says so when it starts. A record labelled trusted still gets everything. rowlog is on or off, and on is the default even when the key is unset. On writes one JSON row per tool call, per agent loop and per model call to an append-only log under the data directory, which is what answers what a session touched, read and produced after the session itself is gone. Off writes nothing at all. shoal audit reads it. voyage is on or quiet, and on is the default even when the key is unset. On, the status line above the composer narrates the turn as a sea passage, phase by phase, each phase entered because its event happened. Quiet gives the plain status words back. memory is the directory the user-scope memory store lives in. Unset is the default and means the memory folder under ~/.shoal, so a machine that never sets it changes nothing. Set it to move the memory store and only the memory store, for example to a folder another tool also reads. SHOAL_HOME is the wrong tool for that: it moves the whole Shoal home, secrets included, and while it is set it wins over this key. An absolute path, or one starting with ~. shoal memory shows which rule is deciding the path. Precedence at launch: CLI flag, then the project's .shoal/config.json, then these defaults. unset clears one key. To clear the launch defaults together, so the next launch is a first run: shoal reset-defaults. To walk the first-run flow without clearing anything: shoal first-run.

shoal config set <key> <value>

Set a default

shoal config unset <key>

Clear a default

shoal connect <host[:port]>

Drive a Shoal engine running on another machine

connect speaks the protocol seam to a berth: an engine running somewhere else, with its own workspace and its own filesystem. Events come out on stdout as JSON lines and ops go in on stdin, exactly as "shoal proto" does, so a client written for one drives the other. The berth prints a certificate fingerprint when it starts. Pass it with --fingerprint. A berth on this same machine needs none: its certificate is on this disk and connect reads it. The token comes from the environment (SHOAL_BERTH_TOKEN) or from the secrets store, never from a flag, because a flag value is visible in the process list. Closing stdin leaves the remote loop running. To stop it, send a shutdown op.
Flag Type Default What it does
--ca string - Verify the berth against this CA instead of pinning a fingerprint
--fingerprint string - The berth's certificate fingerprint, as it printed it
--token-secret string berth_token Name of the secrets-store entry holding the berth token

shoal desktop

Open Shoal as a desktop app window

desktop runs the engine and opens the Shoal web client in an app-mode window on a loopback port. Closing the window exits Shoal; the inference server follows the usual ownership rules (a server started by shoal up persists, a session-owned one stops).
Flag Type Default What it does
--berth string - Drive an engine running at this berth instead of one in this process
--ca string - Verify the berth against this CA instead of pinning a fingerprint
--fingerprint string - The berth's certificate fingerprint, as it printed it
--no-open bool - Serve only: print the URL instead of opening a window
--token-secret string berth_token Name of the secrets-store entry holding the berth token

shoal doctor

Check platform, dependencies, and running services

Detect the host platform, verify the dependencies shoal needs (including the llama-server security floor), and report which inference servers are answering locally. An inference server whose owning session is gone is stopped and reported, so the memory it holds goes back to the machine. A server started by shoal up records no owner and is never touched.

shoal down

Stop persistent inference servers

Stop every shoal-managed inference server and clear stale pid records. A server shoal did not start is reported but left running.

shoal exec [prompt]

Run one prompt without a terminal and exit with a code

exec runs one prompt on this machine and exits. There is no terminal, nothing listens on a socket, and no ops are read after launch: stdin is at most the prompt. The prompt comes from the argument, from --file, or from stdin, and exactly one of the three. With --workflow the same text becomes the workflow's argument instead. Output modes: text the final assistant text on stdout, notices on stderr json one result document: final text, stop reason, spend, files touched, and every action the ladder refused stream every seam event as JSON lines on stdout, as it happens. This is the mode to script against: the vocabulary is the engine's own protocol, not a second schema Exit codes: 0 the turn completed and nothing was refused 1 the flags or the prompt could not be read 2 the engine did not start 3 the turn ended in an error 4 the turn spent its whole tool call budget 5 the turn finished and the ladder refused at least one call 6 the run was interrupted 7 the input gate answered the prompt without starting a turn Approvals cannot ask anybody here, so they resolve from a rung of the autonomy ladder. The rungs are named after Shoal's own tool classes: read runs from the read rung reads a file or searches the tree delegate runs from the read rung hands work to a sub-agent, whose own calls come back through this same table plan runs from the write rung accepts a decomposition plan write runs from the write rung writes to a file exec runs from the exec rung runs a shell command hook runs from --unsafe-approve-all calls an outside process a hook started tool runs from --unsafe-approve-all carries no classification, so nothing here knows what it does The floor is read, which is the default. A write-classified call at the floor is refused and reported, never dropped in silence. Whether a call needs approving at all is the engine's own decision (internal/ permissions), the same one every other client asks, so a shell command Shoal already treats as read-only runs at the floor too.
Flag Type Default What it does
--autonomy string read Autonomy rung: read, write, exec
--file , -f string - Read the prompt from a file
--output , -o string text Output mode: text, json, stream
--session string - Continue a stored session by ID or unique prefix
--unsafe-approve-all bool - Approve every call, including shell commands and hook tools
--workflow string - Run a named workflow instead of a prompt; the prompt becomes its argument

shoal first-run

Replay the first-run flow without clearing anything

first-run walks the flow a new machine gets, on a machine that is already set up. Nothing is cleared. The model list opens on the default this machine already has, so pressing Enter through it leaves everything as it was; picking a different model saves that one, exactly as the first launch would have. This is the flow to reach when you want to SEE the first run. To make the next launch a first run for real, which does clear what is saved: shoal reset-defaults On the windowed surfaces the same two acts are /first-run and /reset-defaults, and the first is also the "Set up this machine again" row at the bottom of the model picker.

shoal memory

Show where memory lives and what it holds

memory shows the two stores a session in this directory would read: the project scope at .shoal/memory in the repository, and the user scope, which is the memory folder under ~/.shoal unless the memory key moves it (shoal config set memory <dir>) or SHOAL_HOME moves the whole Shoal home. It says which rule decided the user path, how many records each scope holds, which slugs the project scope overrides, and which records carry a format newer than this build reads. Read-only. Records are files, one fact each, in a published format, so either folder can be opened in any editor. shoal memory this directory's stores shoal memory discover other harnesses' stores on this machine

shoal memory discover

Find other harnesses' memory stores on this machine, read-only

discover looks where other agent harnesses keep memory and reports what is there and where: Claude Code's per-project stores, Gemini CLI's memory file, the Goose and Windsurf memory folders, the folders OpenCode, Factory and Codex keep, and the neutral .agents location, under the home directory and the current directory. Every location it looked at is printed, found or not. It reads names, counts, and the names of frontmatter keys. It never reads a record's text, never shows one to a model, and never copies one into Shoal's own store. Import is not built: it needs opt-in per source and a review of every record before recall can see it, because a folder of files written by another tool is untrusted text, and recall is the path that carries text into a prompt without a person reading it first. --json prints the same sweep as one document.
Flag Type Default What it does
--json bool - machine-readable output

shoal models

List known models and recommend one for this hardware

Show what is on disk, the model registry with per-dock identifiers, a hardware-aware recommendation, and what each model on disk says about itself. A model already on disk that fits the memory budget is recommended over a registry download. The sizing is a heuristic (weights against a memory budget with KV headroom); any GGUF path or MLX id outside the registry still works with --model. Provenance is reported in three states and never two. What a GGUF header says about its own name, publisher and licence is claimed: the header travels with the file, so nothing here checked it. The path, the size and the sha256 are verified, because this machine read them. Anything absent is not stated, which is silence and not a finding. --hash reads every model on disk and records its digest, so a later listing can report it as verified. Nothing is fetched and nothing is compared: the number is printed for you to compare against whatever the publisher published.
Flag Type Default What it does
--hash bool - read every model on disk and record its sha256 (slow: it reads every byte)
--json bool - machine-readable output

shoal proto

Speak the protocol seam over stdio (JSON lines)

proto runs the engine as a child process for GUI clients: protocol events stream out on stdout, one JSON object per line, and ops arrive on stdin the same way. stdout is pure protocol; startup prints and diagnostics go to stderr. Closing stdin shuts the engine down cleanly. Approvals assume an interactive approver on the other end: tool calls that need approval emit approval_requested events and wait for a resolve_approval op. Pass --auto-approve to skip approvals entirely.

shoal reset-defaults

Clear the saved launch defaults, so the next launch is a first run

reset-defaults clears the user-wide launch defaults in one act: model, dock and endpoint. The next launch then resolves no model and meets the first-run condition, which is the terminal wizard on a terminal and the launch portal on the windowed surfaces. What it does not touch, and why: breakwater, trust policy, not convenience. Unset already means the wall is up, and clearing trust would widen what an unlabelled mooring may do. mooring records a record is something you wrote down. Forget removes one, by name, from the mooring form or /moor on a windowed surface. A record carrying the main purpose supplies the launch on its own, so this command names it when one still does rather than deleting it for you. the project config .shoal/config.json belongs to the repository, not to this machine. It is reported, never edited. To clear one key instead of all of them, shoal config unset <key>. To walk the first-run flow without clearing anything, shoal first-run.

shoal secret

Manage the secrets hooks authenticate with

secret manages the values a hook needs to authenticate, kept outside every project and readable only by you. shoal secret set <name> store a value, read from a prompt or stdin shoal secret list list names and fingerprints, never values shoal secret rm <name> remove one Reference a secret from a hook's env in hooks.json as ${secret:NAME}. It resolves when the hook process is spawned, into that process's environment, and never into a prompt, a tool result, or a stored session. A value that comes back out in a hook's output is replaced with [redacted:NAME] before it reaches the model.

shoal secret list

List secret names and fingerprints

shoal secret rm <name>

Remove a secret

shoal secret set <name>

Store a secret, reading the value from a prompt or stdin

set reads the value from a prompt, or from stdin when it is piped. The value is never taken as an argument: arguments are visible in shell history and in the process list. shoal secret set LINEAR_TOKEN echo $TOKEN | shoal secret set LINEAR_TOKEN

shoal sessions

List and manage sessions

shoal setup

Install shoal as a program (uninstall with --uninstall)

setup installs the running binary as a per-user program: - copies it to the user programs directory - puts shoal on PATH, so any new terminal runs it by name - registers it with the OS (Start Menu, Apps & features on Windows) Re-running setup from a newer binary upgrades the install in place. --uninstall reverses everything; session data and config are kept. When no default model is saved yet, setup asks for one as part of installing, so a bare shoal starts on every surface afterwards. The same default can always be set or changed by hand: shoal config set model <name>
Flag Type Default What it does
--uninstall bool - Remove the installed program (session data and config are kept)

shoal up

Start a persistent inference server

Start the inference server detached, so it outlives this command. The model loads once; later shoal runs find the server healthy on the port and use it instead of spawning their own. Stop it with shoal down. The server binds to 127.0.0.1 only, never exposed to the network.
Flag Type Default What it does
--sleep-idle int 0 unload weights after N idle seconds, keep listening (llama.cpp dock only, 0 = off)

This reference matches Shoal 0.32.0.