OceanCode
Ocean pager — the terminal UI
Ocean pager is oceancode's terminal UI. A plain oceancode execs Ocean pager (ocean-pager); the pager and the Ocean engine run in one process over typed ACP channels — no HTTP between UI and engine. --db, --directory, --listen and --verbose are passed through.
The first-party ratatui TUI was removed on 2026-10-05 (its guide pages are in archive/native-tui/docs/). For compatibility --tui pager and OC_TUI=pager are accepted and change nothing (--tui grok is refused as unknown); --tui ocean and OC_TUI=ocean fail with "the native TUI was removed; oceancode starts Ocean pager". The pager's own slash commands, keys and settings are in Ocean pager reference.
Binary
- Build the pager:
bash scripts/release/build-pager.sh(orcd ocean-pager && cargo build --release -p ocean-pager-bin --locked) →target/release/ocean-pager, the binaryoceancodelaunches. - A plain debug build lands in
target/debug/ocean-pagerand is never launched. To run a pager from elsewhere, setOC_PAGER_BIN.
Discovery order: OC_PAGER_BIN → ocean-pager beside oceancode (and beside the binary a symlinked oceancode resolves to) → ocean-pager on PATH.
oceancode sets $OC_PAGER_HOME to <data>/oceancode/pager ($XDG_DATA_HOME, else ~/.local/share) — the directory a bare ocean-pager uses too — so the pager never shares ~/.grok. Auto-update, remote fetch, feedback and voice are off. Every pager variable: Environment.
Environment
Read by ocean-pager, not by the engine. Every pager variable is OC_PAGER_*; the old GROK_* names are not read.
| Variable | Effect |
|---|---|
OC_PAGER_HOME | The pager's state directory (config.toml, sessions, debug logs, the extracted ripgrep under bin/). oceancode sets it; unset → $XDG_DATA_HOME/oceancode/pager, else ~/.local/share/oceancode/pager. GROK_HOME is ignored. |
OC_PAGER_LOG_FILE | Write the pager's debug log to exactly this path (honors RUST_LOG). |
OC_PAGER_DEBUG_LOG | A path, or 1/true for <pager home>/debug/tui-<pid>.txt: turns the debug log on. |
OC_PAGER_CONFIG | Inline JSON config overlay, merged above config.toml. |
OC_PAGER_CONFIG_PATH | An extra JSON or TOML config-overlay file (read by extension), merged above config.toml. |
OC_PAGER_MANAGED_CONFIG_FAIL_CLOSED | Overrides the requirements fail-closed setting (applies to requirements.toml only). |
OC_PAGER_SHELL | Shell the pager spawns: an executable path (bash, zsh, …); on Windows pwsh, powershell or cmd. |
OC_PAGER_THEME | Force a theme name, or auto, without editing the config. |
LC_OC_PAGER_THEME | Same as OC_PAGER_THEME; the LC_ form survives SSH SendEnv LC_*. |
OC_PAGER_APPEARANCE | dark or light: the terminal background auto themes assume. |
LC_OC_PAGER_APPEARANCE | Same as OC_PAGER_APPEARANCE, SSH-forwardable. |
OC_PAGER_TERMINAL_THEME | Follow the terminal's own palette (on/off; a requirement pin wins). |
OC_PAGER_NERD_FONTS | Nerd Font glyphs in the git status (on/off). |
OC_PAGER_FORCE_LEGACY_CONSOLE | Windows: ASCII-safe glyphs for the legacy console. |
OC_PAGER_SCREEN_MODE | Internal: the screen mode a /fullscreen / /minimal relaunch hands to the new process (read and removed at startup). |
OC_PAGER_SCREEN_MODE_SWITCH | exec forces the legacy re-exec switch between screen modes. |
OC_PAGER_SCROLL_SPEED | Mouse-wheel scroll speed; applied on first load only (the settings modal persists it). |
OC_PAGER_SCROLL_MODE | Mouse-wheel scroll mode; first load only. |
OC_PAGER_SCROLL_LINES | Lines per wheel notch; first load only. |
OC_PAGER_INVERT_SCROLL | Invert the wheel direction; first load only. |
OC_PAGER_SCROLL_CADENCE_MS | Redraw cadence while scrolling (ms). |
OC_PAGER_MIN_DRAW_MS | Minimum interval between frames (ms). |
OC_PAGER_DISPLAY_REFRESH_PROBE_ENABLED | Probe the display refresh rate at startup (on/off). |
OC_PAGER_DISPLAY_REFRESH_AUTO_CADENCE | Derive the draw cadence from the probed refresh rate (on/off). |
OC_PAGER_SCROLL_DEBUG | Show the scroll debug HUD. |
OC_PAGER_SCROLL_LOG | Log scroll input events (unset or 0 = off). |
OC_PAGER_FPS | Show the frames-per-second HUD. |
OC_PAGER_MEMTRACE | Periodic memory trace in the debug log; 0/false/off disables. |
OC_PAGER_MEMTRACE_INTERVAL_SECS | Memory-trace interval (seconds). |
OC_PAGER_MEMTRACE_THRESHOLD_MB | Memory trace logs only above this resident size (MB). |
OC_PAGER_MOUSE_REPORTING_TOGGLE | Enable the mouse-reporting toggle (on/off). |
OC_PAGER_SHOW_THINKING_BLOCKS | Show model thinking blocks (on/off; overrides the setting). |
OC_PAGER_GROUP_TOOL_VERBS | Group consecutive tool calls by verb (on/off; overrides the setting). |
OC_PAGER_SHOW_EDIT_DETAILS | Show each edit's diff inline (on/off; overrides [ui] show_edit_details). |
OC_PAGER_SHOW_RUN_DETAILS | Finished agent Runs show the command and first output lines (on/off; overrides [ui] show_run_details). |
OC_PAGER_COLLAPSED_EDIT_BLOCKS | Legacy: start edit blocks collapsed (on/off); read only when show_edit_details is unset everywhere, as its inverse. |
OC_PAGER_CONTEXTUAL_HINTS | Contextual hints on/off (overrides [ui.contextual_hints]). |
OC_PAGER_TIPS_OVERRIDE | Debug builds only: ` |
OC_PAGER_SLASH_COMMAND_TAGS | JSON map of tags shown beside slash commands in the / menu. |
OC_PAGER_DEFAULT_SELECTED_PERMISSION | Which permission-card option the cursor starts on. |
OC_PAGER_ESC_DOUBLE_PRESS_MS | Window for the double-Esc gesture (ms). |
OC_PAGER_DOCK | The dock above the prompt on/off; on by default (0 brings back the Tasks pane at the top; a requirement pin wins, [features] dock in the pager config comes after). |
OC_PAGER_DOCK_V2 | Same switch as OC_PAGER_DOCK, read after it. |
OC_PAGER_AGENT_DASHBOARD | 0 turns /dashboard off. |
OC_PAGER_WORKSPACE_DASHBOARD | Use the workspace (v2) dashboard layout instead of the persisted v1 layout. |
OC_PAGER_SESSION_PICKER_GROUPED | 1/0: group the session picker (overrides [cli] session_picker_grouped, default on). |
OC_PAGER_HUNK_TRACKER | Hunk-tracker mode (overrides [ui] hunk_tracker_mode). |
OC_PAGER_SUGGESTIONS | Shell-command ghost suggestions (off by default). They request ocean/suggest, which the Ocean engine does not serve, so nothing shows. |
OC_PAGER_SUGGESTIONS_AI | AI variant of OC_PAGER_SUGGESTIONS (same limitation). |
OC_PAGER_SUGGESTIONS_AI_MODEL | Model id for OC_PAGER_SUGGESTIONS_AI. |
OC_PAGER_MCP_PUSH_SERVER_STATUS | Push MCP server status updates into the UI (default on). |
OC_PAGER_ENVRC_TIMEOUT_SECS | Timeout for evaluating a directory's .envrc (seconds; 0 disables). |
OC_PAGER_CONNECT_UI_TIMEOUT_SECS | Seconds before startup shows the connect-failure report (6 s floor). |
OC_PAGER_PROMPT_ACK_TIMEOUT_SECS | Prompt acknowledgement timeout (seconds). |
OC_PAGER_EXIT_TIMEOUT_SECS | Force-exit this many seconds after a quit if teardown hangs (default 20; 0 disables). |
OC_PAGER_COPY_FILE | Backup file every copy is also written to (default <pager home>/last-copy.txt). |
OC_PAGER_OSC52_SINK | Emit clipboard writes as OSC 52 for a wrapping terminal. |
LC_OC_PAGER_OSC52_SINK | Same as OC_PAGER_OSC52_SINK, SSH-forwardable. |
OC_PAGER_CLIPBOARD_NO_OSC52 | Never emit OSC 52 (for hosts that paint it as garbage). |
OC_PAGER_CLIPBOARD_NO_NATIVE_READ | macOS: don't read the native pasteboard. |
OC_PAGER_CLIPBOARD_NO_DATA_CONTROL | Linux: skip the Wayland data-control clipboard protocol. |
OC_PAGER_SQLITE_JOURNAL_MODE | SQLite journal mode for the pager's local databases (the WAL kill switch). |
OC_PAGER_RESET_CHILD_OOM | Linux, internal: set on child processes so they reset the inherited OOM score. |
OC_PAGER_EVENT | Set for notification hook commands: the event name. |
OC_PAGER_MESSAGE | Set for notification hook commands: the message text. |
OC_PAGER_SESSION_ID | Set for notification hook commands: the session id. |
OC_PAGER_BUNDLE_RG_PATH | Build time: embed this ripgrep binary instead of downloading the release tarball. |
OC_PAGER_RG_VER | Build-internal: embedded ripgrep version, set by ocean-pager-ripgrep/build.rs. |
OC_PAGER_RG_TARGET | Build-internal: embedded ripgrep target triple. |
OC_PAGER_RG_SHA256 | Build-internal: SHA-256 the extracted ripgrep is verified against. |
OC_PAGER_CHANGELOG_OFFLINE | Tests: never fetch the changelog. |
OC_PAGER_MDM_NO_EXPAND_TEST | Tests: macOS managed-preferences layer. |
OC_PAGER_TEST_OPEN_URL_FILE | Tests: write opened URLs to this file instead of launching a browser. |
OC_PAGER_TEST_FRAME_WRITE_DELAY_MS | Tests: delay each frame write (ms). |
OC_PAGER_TEST_HOLD_TEARDOWN_SECS | Tests: hold teardown to exercise the exit timeout. |
What is wired to the Ocean engine
/, /mcps, /skills, /plugins, /hooks, /workflows, /model, and /effort use the pager chrome and Ocean Services. MCP add/toggle, plugin enable/disable, hook reload, and tool permission cards go through the same ACP methods Grok Build uses. The /workflows picker lists built-in and discovered project/user workflows over ocean/workflows/list (empty when the workflows section is disabled); launching, pausing, resuming and stopping a run go through the workflow tool, not an ext request.
Skills complete in the composer. Typing / and a prefix lists your enabled, user-invocable skills alongside the pager's own commands — a plugin skill under Claude Code's plugin-qualified name (/superpowers:writing-plans, so /super finds every superpowers skill), a project or user skill under its bare name (/formatcode); the prefix narrows the list, Tab/Enter inserts /<skill> into the message box so you can keep typing, and sending dispatches it — the engine expands the skill body into the turn (a typed bare /writing-plans still runs the plugin skill too). The candidates come from ocean/skills/list (fetched at session start; the Ocean engine does not advertise skills as ACP commands), so a disabled skill is never offered. A Space toggle on the Skills tab of the capabilities picker updates the popup live, and the <available_skills> block and skill_* tools shrink on the next step (09 · Capabilities).
The capabilities picker. Each tab (/skills, /plugins, /hooks, /mcps, /workflows, Marketplace) lists only its own kind. On the Skills tab, Space toggles the skill under the cursor and the change sticks (it writes ~/.oceancode/skill-state.json); / opens a search that filters the rows by the skill's name, its slash id, its description and its author, case-insensitively, and a query that matches nothing reads No matches. a / d enable / disable every skill behind a confirm prompt. Each row shows its source — project, user or plugin: <name> — grouped by source.
Group and master toggles. On the Skills, Plugins, Hooks and MCP tabs Space also works above the single row; every change applies on the next step and costs one cache rewrite (09 · Capabilities):
| Row / key | Action |
|---|---|
Everything (first row) + Space | Master switch: off removes skills, MCP tools, hooks and plugin rules from the agent's context, built-in tools stay; asks first |
All skills / All plugins / All MCP / All hooks (second row) + Space | The whole kind on or off; asks first |
a / d (Skills tab) | Same as All skills on / off |
A Plugin: <name> header (Skills, MCP) or a hook source header + Space | Every row in the group; asks first above 10 rows; an all-off group reads [off] |
A row + Space | That one skill, plugin, hook or MCP server |
The picker's last row shows the live counts (skills 22/259 · plugins 2/21 · mcp 1/10 · hooks 8/8 · applies on the next step (one cache rewrite)), prefixed EVERYTHING OFF while the master switch is off. The Plugins tab also lists Claude Code's cached plugins under User (Claude). The Marketplace tab reads ~/.oceancode/marketplaces/** only when you open it (opening /skills or /plugins no longer touches the marketplace), and marketplace content never reaches the prompt or the tool list.
Pasted images
Paste an image from the clipboard (Ctrl+V / Cmd+V) or drag an image file onto the composer; it shows as [Image #1] in your text and goes to the model with the prompt ("what's wrong with this layout? [Image #1]"). Every route carries it — Anthropic, OpenAI chat and Responses (xAI, Groq, OpenRouter, …), Gemini. With several images, each is labelled [Image #N] in the request, so the model matches the name in your text to the right picture.
Limits: at most 20 images per prompt, 3.75 MiB per image once stored (about 5 MB once base64-encoded, the strictest limit of the routes), and 8000 px on either side (Anthropic refuses a larger image before the model runs; sips -Z 2576 <file> brings it under). The engine sends PNG, JPEG, GIF and WebP — the types every route accepts, decided by the image's bytes, not its declared type. The pager re-encodes a TIFF (what a macOS screenshot usually is on the clipboard), BMP, ICO or GIF as PNG before it sends, so those paste and drag in like any other; PNG, JPEG and WebP go as they are. An image over the limits after that, a type the pager cannot decode, or an http(s) source refuses the whole prompt with a message naming the image; nothing is dropped silently.
Dragging from another app. In Ocean AI Terminal a file dragged in from Photos or Finder becomes a chip the same way, and since desktop build 0.8.11 the drop also brings the terminal window to the front: macOS does not activate the window a drag lands on, so with an older build the keys you type next, Enter included, still go to the app the image came from until you click the terminal once.
Resizing. Images are resized so they never make a session fail (the same rules apply to images the read tool returns):
- An image over 2576 px on its long edge (the most a current Claude model reads; larger is downscaled by the provider anyway) is shrunk to 2576 px when it is pasted or read. The resize is Lanczos3 with the aspect ratio kept; PNG stays PNG and JPEG stays JPEG, GIF and WebP become PNG.
- When one request carries more than 20 images, Anthropic applies a stricter size limit to every image in it, so any image over 2000 px is sent as a 2000 px copy. The stored session is not changed.
- If the provider still refuses an image for its size, the engine retries once with every image at or under the limit the provider named, and keeps that limit for the rest of the session.
- Past 100 images or 24 MiB of image data in one request, the oldest images are replaced by a one-line note (
[<name>, <W>x<H> omitted from this request: …; read the file again to see it]).
Text-only models. When the catalog says the current model reads no images (its models.dev entry lists input modalities without image), the text still goes and the image does not; a session note says so: Image #1 not sent: <model> doesn't accept images. A model the catalog cannot describe — an offline seed entry or one you declared under providers.*.models — gets the image. Switching to a text-only model after pasting drops the media from the request on the next turn — and an image a tool returns (read on a PNG) is replaced by a one-line note on such a model — so the provider does not answer 400.
The image is stored inline on the user row of oceancode.db ("files":[{"uri":"data:image/png;base64,…); a reopened session replays that row as text only, and the headless and server prompt bodies (07 · Headless and server) carry text only for now.
The dock: sub-agents above the prompt
Running sub-agents, background commands, monitors, loops and queued prompts live in one dock directly above the
prompt, one section each (Agents, Tasks, Watchers, Queued). While a turn runs, its status rides the dock's
first header instead of taking a row of its own:
▾ Agents 2 ⸬ Working 2m31s 1m20s ⇣12k [stop]
⸬ Find every caller of resolveWorkflowAccess — Running: rg -n … 1m15s silent · 4 tools · 38k tok · 2m13s
✓ Map the picker code paths 9 tools · 52k tok · 48sA sub-agent row is the task's description, led by a badge only when the mission gave the sub-agent a persona or role
(Researcher), then its live activity; the right column shows its tool calls, tokens and elapsed time, plus
Ns silent once it has sent nothing for 10 s — amber from a minute, the one to open. The dock counts the agents, so
the Ocean bar does not. Ctrl+G hides and shows the dock; a section folds on Enter or a click on its header, show N more opens a long one, ↗ opens a row and [stop] stops it. One blank row separates the transcript from what
sits under it; nothing else is spaced.
The transcript keeps a record: Subagent running: "…" when a sub-agent starts and Subagent completed in 48s: "…" · 52k tok · 9 tools when it ends; the running line does not repeat the dock's live figures. OC_PAGER_DOCK=0 (or
[features] dock = false) brings back the Tasks pane at the top, the live figures on the transcript row and the
agents N count in the bar.
Under a work mode with an at-once limit (23), a sub-agent that must wait for a free slot
gets a dock row of its own with a hollow glyph, waiting (4/4 running), which turns into its running row when a slot
frees (or closes if the turn is stopped first). Model, the default, has no such limit, so this row never appears
there.
The work-mode picker (F4)
F4 or /mode opens the work-mode picker: who decides how agents work together — the model (Model, the default),
Jev (Auto), or you (seven diagrams). The list sits on the left and the highlighted mode's picture on the right; moving
the cursor redraws it at once. Enter uses the mode for this session, d makes it the current agent's default, e
copies a built-in into .oceancode/modes/ to edit, Esc closes. /mode <id> and /mode default do the same
without the picker. Every mode but Model shows its badge on the prompt's top border, after the ultracode badge when
that is on (delegate ≤4, race ×3, auto → goal · Jev 0.82); Model shows none, so the border is unchanged. F2 ›
Agent defaults holds a mode row per ring agent, and F2 › Sub-agents the three sub-agent limits
(22). The modes, limits and requirements are on
23 · Work modes.
Watching a sub-agent
Open a sub-agent with a double-click or Enter on its dock row (↗), its transcript row or its Agent Dashboard row:
the view fills with what the sub-agent does as it does it — its bash commands and their output, reads, greps, edits
with their diff, and its text and thinking — with its own context bar. q or Esc closes it.
The engine streams a running sub-agent's activity live under the sub-agent's own session id, while the parent's turn
runs and afterwards for a background sub-agent. A finished sub-agent whose view holds nothing yet — or whose view was
freed after you closed it — is rebuilt from oceancode.db when you open it (ocean/session/replay). Sub-agents of a
session you resumed, or of an earlier pager run, do not open yet.
Goal mode (orchestrate: always)
Set orchestrate: "always" in the workflows section of oceancode.json and a plain prompt is
no longer a single turn — it launches the built-in goal workflow, which plans the objective
into verifiable deliverables, works in rounds with one resumed worker, and converges only when a
panel of adversarial skeptics fails to refute completion (identical gaps two rounds running, or a
spent budget, pause instead of looping). The pager's Workflows dock shows the run advancing
through its Plan → Work → Verify phases, with the sub-agents of each round beneath it. The
Claude-settings ultracode flag does not turn this on — only the explicit orchestrate
opt-in does. Headless, the same goal run is oceancode goal "<objective>" (see
07-headless-and-server.md). Since work modes, orchestrate: "always" with no mode set is read as the Goal work
mode (23).
What the pager does not do
Login, billing, worktrees, /imagine and Grok memory flush are unsupported (-32601).
Connecting a provider is in the pager: pick a gray /model row, or /connect <provider>. OpenCode-style auth methods:
- API key — most providers (Google, Groq, Perplexity, …).
- ChatGPT Plus/Pro — OpenAI, via OpenCode’s JSON deviceauth (
auth.openai.com/codex/device), or paste an API key. - Claude Pro/Max — Anthropic PKCE (paste the browser code), or paste an API key.
- GitHub Copilot — GitHub device flow (
github.com/login/device). - claude-code —
oceancode claude(Claude CLI login). - Bedrock / Vertex — environment/config, not a prompt.
Already-connected providers open a manage overlay: switch API key ↔ subscription, or d to disconnect (removes auth.json; env-backed providers stay connected until the env var is unset). Credentials go to the same auth.json as oceancode key / oceancode login.
Expired subscription
Ocean runs on the Claude subscription by consuming the active slot Claude Code keeps in
~/.claude/.credentials.json (claudeAiOauth); it never rotates that slot's refresh token. On
macOS, once that file's token is within five minutes of expiry, Ocean also reads the Keychain item
Claude Code refreshes itself into (Claude Code-credentials, read only) and uses whichever carries
the later expiry, so a self-refresh by Claude Code no longer strands Ocean an hour later; no file
still means no login. When the slot's access token has expired and carries no refresh token, a
prompt cannot be sent, and the
turn fails in the transcript with a terminal, actionable message —
Claude subscription token has expired: Run oceancode login to reconnect your Claude account. —
and no retry countdown or network banner (the failure is not a transport error and is never
retried). Run oceancode login, complete the Claude Pro/Max browser flow, and send the prompt
again. (Headless, oceancode run prints the same message to stderr and exits non-zero.)
The same holds when the slot expires mid-session: it was valid when the turn started, so the
request reached Anthropic and the server rejected the now-dead token with an HTTP 401. On the
subscription route that 401 (and a 403) is the same terminal run oceancode login failure — it is
never retried — whereas a 401 on an API-key provider stays a generic error (its fix is a new key,
not a re-login).
Coming from the native TUI (removed 2026-10-05)
The pager renames some surfaces of the removed native TUI and has no ctrl+x leader — it uses
direct chords. The pager equivalents:
| Native TUI | Ocean pager | Notes |
|---|---|---|
/copy | /toggle-mouse-reporting | Toggle terminal mouse capture so text selection/copy works. |
/mcp | /mcps | The MCP-servers picker. |
/models | /model | The model picker (also gates provider /connect). |
/cockpit | status bar + /context | No unified cockpit panel; the status bar plus /context show the same figures. |
ctrl+x leader chords | direct chords | The pager has no ctrl+x prefix. Use ctrl+p (command palette), ctrl+\ (Agent Dashboard), ctrl+t (todos pane), ctrl+m (multiline / model picker off the prompt). |
Shift+Tab ring and permission modes
Shift+Tab cycles Build → Auto → Plan → Ask → Debug → Build. Build, Plan, Ask and
Debug are the engine's agents (the curated ring in crates/ocean-acp/src/modes.rs);
Auto is the one permission stop, Claude Code's "accept edits": the agent stays Build,
the prompt border shows auto in yellow, and the engine's permission mode is
acceptEdits — edits run without a card, bash and outside-directory asks still
prompt (or go to Jev, see 13), and the question tool always
asks. Cycling on from Auto drops back to ask before the switch to Plan. The stop is
absent while always-approve is on, and when the auto feature is gated off
([auto_mode] enabled = false in the pager config).
The same mode is reachable from /auto, /always-approve (ctrl+o; the engine's
bypassPermissions, every card auto-answered by the pager) and the permission_mode
row of the settings modal. Each change is persisted to the pager config and sent to
the engine as ocean/yolo_mode_changed, so the engine's mode and the border flag
agree (see 12 · Permissions and sandbox).
A subagent's ask surfaces as its own card, labelled with the subagent.
The agent is the bold flag on the prompt's bottom border (Build blue, Plan violet,
Ask green, Debug orange); the permission mode follows it (auto yellow,
always-approve red). The Plan agent is plan mode, so it shows once, as Plan;
plan approval and commenting L3 appear beside it while a plan is under review.
Each agent can carry a default model and effort (agents.<id>.{model,effort} in
oceancode.json, edited under F2 › Agent defaults): Shift+Tab to that agent puts the
session on them, the effort clamped to the levels the model offers, and status-bar row 1
follows. Option+Tab (or F3, for terminals that don't send Option as Meta) steps the
session's effort up through the current model's levels, wrapping to the lowest, and
prints the same "Switched to …" line as /effort. That change lasts for the session:
the next Shift+Tab loads the agent's own default again. An agent with no defaults keeps
the session's model and effort.
A settings push reaches an open session live — a fleet-router Apply, an F2 edit, or a
hand edit of oceancode.json or ~/.claude/settings.json. The pager shows one toast naming what
moved, for example Settings applied: sub-agents effort medium · build effort max, and
status-bar row 1 shows the new values. The values it names are the main model and effort, ultracode,
the sub-agent model and effort, FORCE, and each agent's model and effort. When the push changes
the row of the session's current agent and the session still runs that row's old value, the session
moves to the new one. A Mesh › Main change moves a session on the previous Main model unless its
agent has a row of its own: the row wins (today that leaves Debug, which has no row). A model or effort
you changed by hand in this session (/model, Option+Tab) is kept.
Question cards
When the agent asks with the question tool, a card replaces the composer: ↑/↓ walk
the answers, Enter picks one (or starts typing on the last row, where you answer in
your own words — that text reaches the model as written), ←/→ move between questions.
Ctrl+Bback to chat leaves the question to give the agent more first — notes, pasted images, links. The turn stops, the answers you had picked land in the composer asMy answers so far:, and the agent is told you stopped to add context; send your message and it thinks again and asks only what is still open.Escsteps back (out of the text row, then clears a pick);Xdismisses the card without answering;Ctrl+Ccancels the turn and the open question with it. A secondCtrl+Cwhile the turn is still cancelling arms quit, and a third quits.
Resuming: the session tree
/resume (and the home screen's list) shows your main sessions only, most recently active
first. A session that spawned sub-agents carries a fold glyph and says how many in the right
column — › Pager fixes 3 sub · 5m ago — and the sub-sessions stay out of the way until you
open it:
→(ore) on a parent row opens it: its sub-sessions are fetched the first time and drawn indented underneath; a sub-session that spawned its own folds the same way, as deep as the work went. On a row with nothing to open,→shows the detail card as before.←closes the detail card if it is open, then folds the sub-sessions away, then moves the selection up to the row's parent.- Typing searches titles on the engine, across main sessions and sub-sessions alike. A hit is drawn under its main session, with the rows between them dimmed when they did not match, so you can tell which run it belongs to. Clearing the search brings the folded list back.
- A row badged
openis already running in another pager window on this machine; open it there instead of resuming it twice. Enterresumes whichever row is selected, a sub-session included.
The engine names a session after the first prompt that says something — Hi, Yeah, Do it,
Continue, [Image #1] and the like name it only until a real request arrives, so a list of
greetings does not happen. /rename still wins over any automatic title.
Search counter and tideline tiers
The top-right status row shows a search N · 0.3s chip once the session has run a
grep or glob tool call: N is the number of calls, the time is the last call's
latency (green ≤ 1 s, yellow ≤ 5 s, orange above). Click it for the breakdown —
calls by tool, last / average / total latency, bytes and files scanned, and how
many recursive grep -r / find the model ran through bash (and how many of
those were rewritten to rg). The figures are folded from each tool result's
metadata (elapsed_ms, files, bytes, search_redirect) in oceancode.db,
so they survive a restart; nothing is counted in memory.
The Ocean context row (ctx … N% full · tideline …) is tiered against the
tideline limit: green under 80 % of it, yellow from 80 %, orange at or over it
(the gauge, the percentage and the tideline clause share the tone). With the
ledger off the same tiers apply against the context window. tideline ×12 @30% …
carries the number of turns past the tideline (/tideline prints the same
figure); no ×N while it is zero.
The bash tool rewrites a plain recursive grep -r … to the bundled ripgrep
(POSIX shells; every flag must have an rg equivalent, patterns are literal-safe)
and prepends [oceancode] ran as: rg … to the result; any other recursive
grep or a find … -name runs as typed under a one-line hint naming the grep /
glob tools. A leading cd <dir> &&/; prefix, a trailing 2>/dev/null,
| grep -v … / | head followers, and BRE \| alternation are carried or
translated verbatim, so the common slow pipelines still rewrite. The ripgrep directory leads the child PATH, so rg is available
in bash on every OS where a binary resolves (OC_RG_BIN overrides; see 02).
Ocean session commands
These act on the Ocean engine over _ocean/* / ocean/* ext methods (Ocean backend only):
| Command | What it does |
|---|---|
/tideline | Bare shows the ledger state; /tideline now cuts the ledger; <n>%, <tokens>, or default set the tideline (the floor and the presets were removed — a second number or a preset word is refused with the usage line). The old /shelve still works as a hidden alias. |
/retention | Bare shows how long idle sessions are kept and what the next sweep would delete (retention 7 days · 12 sessions pending · first sweep after <date> (grace), or … · last sweep 5m ago, 340 swept); <days> sets retention.days in the global config and re-arms the sweep at once; off is 0 (keep everything). An out-of-range number is refused with the engine's message. While sessions wait out the 24-hour grace window the context row shows retention N pending and one notice is toasted. See 18 · Operations. |
/budget | Bare shows the spend cap; $5 (or 5) caps USD, off clears it, subscription switches to list-price mode. |
/limits | Bare shows the per-turn bounds; steps <n> caps steps, time <90m|1h30m> bounds wall-clock. |
/subagent | Bare reports the effective sub-agent model + source; <provider/model> pins one, default / off / clear removes the override. |
/mode | Bare opens the work-mode picker (as F4); <id> sets this session's work mode; default clears it, so the agent's or the config's mode applies again. Answered with a toast, Mode: <label>. See 23. |
/plan add|done|cancel|edit|remove | Edit the live todo table (1-based rows); bare /plan still enters plan mode. |
/redo | Re-apply the turn a /undo (/rewind) reverted, and the files it put back. |
/share | Share this session via a public URL (Ocean backend). |
/unshare | Revoke the current session's share link. |
/notify | Toggle desktop notifications; /notify on|off sets it explicitly. |