OceanCode
CLI reference
oceancode is one binary: oceancode [subcommand] [flags] [args]. With no subcommand it starts Ocean
pager. acp runs it as an editor agent, and serve, run, goal and workflow run it headless.
01 · Getting started explains the three boot shapes. This page lists every
subcommand, its flags and its exit codes.
Flag syntax
Most engine commands parse flags with a port of Go's flag package: the default shape, serve, acp,
migrate, run, workflow, goal, ledger, export, login, logout, key and auth. Go's rules
apply:
-nameand--nameare the same flag. A value is written--name valueor--name=value. Single-letter flags cannot be bundled:-vcis one flag namedvc.- Parsing stops at the first argument that is not a flag, or at a bare
--, which is dropped. Everything after that point is positional, even if it looks like a flag. - A boolean flag never takes the next argument; turn one off with
--name=false. Integer flags accept Go's base prefixes (0x1000,0o10000,0b…) and_separators. -h/--helpprintsUsage of <name>:and the flag list to stderr, then exits 0. An unknown flag, a missing value or a bad value prints the error and the usage to stderr, then exits 2.
The capability and maintenance commands (plugin, mcp, skill, trust, hooks, jev, inspect,
doctor, update, verify-release, uninstall, claude) parse their arguments by hand. Write their
flags with two dashes, exactly as shown. Most of them reject --help with a usage error (exit 1).
update ignores --help and runs a real update, so never try oceancode update --help.
Global flags
--version must be the first argument. --data-dir and --fake-llm-sse are removed from the whole
command line before the subcommand is chosen, so a run prompt that contains the words --data-dir x
loses them.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--version | — | — | Print oceancode <version> (<build stamp>) and exit 0. Needs no database, config or terminal. -v is not an alias: it means --verbose. |
--data-dir <dir> | string | the app data dir | Where auth.json and the other per-install state live, for commands that boot the engine. Also --data-dir=<dir>. |
--fake-llm-sse <file> | string, repeatable | none | Test hook: replay a recorded provider SSE body for each turn, in order, repeating the last one. Also --fake-llm-sse=<file>. |
OC_DETERMINISTIC=1 is read at the same point: it pins the clock and seed that ids are minted from, so
two runs produce identical id sequences. Every invocation except --version checks for orphaned sessions
left by a crashed run. When it finds any, it prints one line to stderr: note: <n> orphaned session(s) from a previous run — run `oceancode doctor` for details.
Common engine flags
--db, --directory and --verbose are not global; each command declares them. They mean the same
thing everywhere, so the per-command tables below omit them.
| Flag | Type | Default | Meaning | Taken by |
|---|---|---|---|---|
--db | string | oceancode.db | Path to the session database. | the default shape, run, serve, acp, workflow run/pause/resume/stop, goal, ledger, export, migrate |
--directory | string | current directory | Working directory. For workflow runs it is the project to filter by. | the same, minus migrate, plus workflow runs |
--verbose, -v | bool | off | Trace every outbound LLM provider request/response to stderr, with credentials masked. | the default shape, run, serve, acp, workflow run and its control verbs, goal |
Exit codes
| Code | Meaning | Where |
|---|---|---|
| 0 | Success, or -h/--help on a Go-flag command. | all |
| 1 | The command failed. The message is printed to stderr as error: <message>. | all |
| 2 | Flag parse error (unknown flag, missing or bad value). | Go-flag commands |
oceancode run exits with a typed code once its turn has started. A failure before that (boot, flag
validation, an empty message) is exit 1. A turn that ends while background sub-agents it started still work
does not end the run: run waits for them and for the turns their results start, and exits on the last.
| Code | Meaning | Stop reason(s) |
|---|---|---|
| 0 | finished | finished, waiting |
| 2 | permission rejected | permission_rejected |
| 3 | budget | budget |
| 4 | time | time |
| 5 | no progress | no_progress, max_steps, doom_loop |
| 6 | error | error, hook_blocked; also a --json-schema that cannot be satisfied |
| 130 | interrupt | user_interrupt |
oceancode workflow run and oceancode goal exit by the run's final status:
| Code | Status |
|---|---|
| 0 | complete (and a --validate-only check) |
| 2 | failed, cancelled, interrupted, budget_limited, or any unrecognised status |
| 3 | a pause: user_paused, back_off_paused, no_progress_paused, infra_paused, blocked |
Exit 2 from run can be a permission rejection or a flag error; the stderr text tells them apart.
oceancode (no subcommand)
oceancode [--db <path>] [--directory <dir>] [--listen <host:port>] [--tui pager] [-v]Execs Ocean pager, which runs the engine inside its own process. stdout must be a terminal; otherwise it
fails with stdout is not a terminal — use `oceancode serve` for headless serving. The pager binary is
looked up in this order: OC_PAGER_BIN, then next to oceancode (also next to its target if oceancode
is a symlink), then PATH. Here --verbose becomes the pager's --debug.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--listen | string | 127.0.0.1:4096 | HTTP bind address handed to the pager. A non-loopback address needs OC_SERVER_PASSWORD. |
--tui | string | empty | Kept for old scripts: empty or pager is accepted, ocean is refused (the native TUI was removed), and any other value is an error. Falls back to OC_TUI. |
See 19 · Ocean pager.
oceancode run
oceancode run [flags] <message…>Runs one non-interactive turn and exits with the typed code above. Flags must come before the
message, because a flag after it is sent to the model as text; a bound flag placed after the message
also prints a warning that the run is not bounded by it. When stdin is not a terminal, run reads it to
EOF and appends it to the message, so close stdin (</dev/null) when the prompt is only an argument. An
empty message fails with you must provide a message.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--agent | string | empty | Agent to use. |
--model, -m | string | empty | Model to use, provider/model. |
--variant | string | empty | Model variant (provider-specific reasoning effort, e.g. high, max). |
--title | string | truncated prompt | Session title. |
--continue, -c | bool | off | Continue the last session. |
--session, -s | string | empty | Session id to continue. |
--resume-title, -r | string | empty | Resume the most recent session whose title matches this text. |
--fork | bool | off | Fork the session before continuing. An error unless --continue or --session is also given. |
--auto | bool | off | Auto-approve permissions that are not explicitly denied (dangerous!). |
--output-format | string | text | stream-json (NDJSON per event), json (one buffered result object), or text. Takes precedence over --format. |
--format | string | default | Deprecated. default = text; json = the stream-json framing. |
--tools | string | all | Restrict the advertised tools to these comma-separated ids. An unknown id is an error. |
--disallowed-tools | string | empty | Remove these comma-separated tool ids from the advertised set. |
--allow | string | empty | Append allow permission rules, e.g. "Bash(git *),Edit(src/**)". |
--deny | string | empty | Append deny permission rules (last match wins, so a --deny beats an overlapping --allow). |
--append-system-prompt | string | empty | Append this text to the run's system context. |
--json-schema | string | empty | Validate the model's final JSON against this JSON Schema (a file path or inline JSON). On a mismatch the model is re-prompted with the validation errors, up to a retry limit. Prints the validated object; exits 6 if the schema cannot be satisfied. |
--max-usd | string | unset | USD bound for this session: a number, off, or subscription (no bound; spend shows the list-price estimate). |
--max-minutes | string | unset | Wall-clock bound: minutes, 90m, 8h, 2d, or off. |
--max-steps | string | unset | Step bound per turn, 1..=1000, or default to clear a stored override. |
--tideline, --shelve | string | unset | The Session Ledger tideline: <pct>% (a share of the model's context), <limit>, or default. --shelve is the older spelling. |
--window | string | — | Removed. Any value fails with --window was renamed: use --tideline. |
--subagent | string | unset | The model this session's sub-agents run, provider/model. |
--atif | string | empty | When the turn ends, write the session's ATIF-v1.8 trajectory (JSON) to this path. |
See 07 · Headless and server and 08 · Bounding a long run.
oceancode serve
oceancode serve [--port <n>] [--host <ip>] [--db <path>] [--directory <dir>] [-v]Starts the engine with its HTTP surface only and no UI. The banner goes to stdout and diagnostics to
stderr. A non-loopback --host without OC_SERVER_PASSWORD is refused before anything boots.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--port | int | 4096 | TCP port to listen on. |
--host | string | 127.0.0.1 | Interface to bind. A non-loopback host requires OC_SERVER_PASSWORD. |
oceancode acp
oceancode acp [--db <path>] [--directory <dir>] [-v]Serves the engine as an Agent Client Protocol agent over stdin/stdout, which is how Xcode and other ACP editors launch it. stdout carries only newline-delimited JSON-RPC; the banner, diagnostics and tracing go to stderr. There is no HTTP surface, and the command returns when the editor closes stdin. It takes only the common engine flags. See 20 · Xcode and other ACP editors.
oceancode workflow
oceancode workflow run <name|path> [--args <json>] [--budget <n>] [--validate-only] [-m <provider/model>]
oceancode workflow runs [--all] [--directory <dir>]
oceancode workflow pause|resume|stop <run_id> [--budget <n>]run starts a host-run Rhai workflow and prints each workflow_updated body to stdout as one JSON line.
The last line is the terminating body, and the command exits with the workflow/goal code above. Put the
name or path first, then the flags. runs lists the persisted runs for the current project, newest
first; it takes no --db or --verbose. pause, resume and stop (run id first) only act on a run
that is live in the engine that same command boots.
| Flag | Sub-subcommands | Type | Default | Meaning |
|---|---|---|---|---|
--args | run | string | {} | JSON object bound to the workflow's args global. |
--budget | run, control verbs | string | from config | run: absolute bound on cumulative child-agent calls, 1..=1024. resume: a higher call bound that lifts a budget-limited run. |
--validate-only | run | bool | off | Metadata and compile check only; launches no agent. |
--model, -m | run | string | empty | provider/model for steps that name no model. There is no default provider. |
--all | runs | bool | off | List runs from every project. |
oceancode goal
oceancode goal "<objective>" [--budget <n>] [-m <provider/model>] [--db <path>] [--directory <dir>] [-v]Launches the built-in goal workflow (Plan → Work → Verify) and prints each goal_updated body to stdout
as one JSON line. It exits with the workflow/goal code above. The objective must be the first
argument, with the flags after it. A missing objective, or a flag in first place, fails with
missing objective: usage: oceancode goal "<objective>" [--budget <n>] [--model <provider/model>].
| Flag | Type | Default | Meaning |
|---|---|---|---|
--budget | string | from config | Absolute bound on cumulative child-agent calls for the goal, 1..=1024. |
--model, -m | string | empty | Default model for every goal agent that names none. There is no default provider. |
oceancode ledger
oceancode ledger path [--db <path>] [--directory <dir>] <session-id>
oceancode ledger rebuild [--merge] [--yes] [--db <path>] [--directory <dir>] <session-id>path prints the absolute ledger directory of the session. rebuild rebuilds the ledger mechanically and
prints rebuilt <n> turn(s) in <dir>. --merge then prints the number of merge chunks and asks
fold forward with model calls? [y/N] on stderr before folding them forward, which costs model calls.
The session id is read after the flags, so write the flags first; a flag placed after the id is not
applied. With the ledger disabled (ledger.enabled = false), rebuild fails.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--merge | bool | off | rebuild only: fold the merge backlog forward after the rebuild (model calls). |
--yes | bool | off | rebuild only: skip the y/N confirmation for --merge. |
See 06 · Session ledger and export.
oceancode export
oceancode export (--md | --atif) [--out <path>|-] [--db <path>] [--directory <dir>] <session-id>Writes a whole session as one Markdown document or as an ATIF-v1.8 trajectory (JSON). Pass exactly one of
--md or --atif. As with ledger, the session id is read after the flags, so write the flags first.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--md | bool | off | Write the session as one Markdown document. |
--atif | bool | off | Write the session as an ATIF-v1.8 trajectory (JSON). |
--out | string | - | Output path; - writes to stdout. |
See 06 · Session ledger and export.
oceancode login
oceancode login [--provider claude|copilot|codex] [--no-browser]Logs in to a provider and stores the credential in the data dir's auth.json. claude (the default;
also anthropic, claude-pro, claude-max) runs the Claude Pro/Max OAuth flow: it prints the authorize
URL and reads the pasted code from stdin. copilot (github-copilot) and codex (openai) run the
OAuth 2.0 device-code flow and store the credential under github-copilot or openai.
| Flag | Type | Default | Meaning |
|---|---|---|---|
--provider | string | claude | Provider to log in to: claude, copilot or codex. |
--no-browser | bool | off | Print the authorize URL only; do not try to open a browser. |
A --features platform build adds --provider ocean (dashboard sign-in that stores the Ocean account
key) and --sso-token <token> (stores a gateway SSO session token). See
15 · Platform mode.
oceancode logout
oceancode logout [anthropic|zai-coding-plan|ocean]Removes one provider's stored credential from auth.json; the default is anthropic. Accepted names:
anthropic/claude, zai-coding-plan/zai/glm/zai-coding/glmcoding, and ocean/plungeai. If
nothing is stored, it prints No stored <provider> credential. and exits 0. Takes no flags.
oceancode key
oceancode key [<provider>] [<api-key>]Stores an API key in auth.json (type api). The provider defaults to anthropic and takes the same
names as logout. With no key on the command line, the key is read from stdin when stdin or stdout is
not a terminal; in a terminal, a non-Anthropic provider prompts for it. With no key at all, the command
prints the credential status for anthropic and zai-coding-plan. A key without the expected sk-ant-
prefix triggers a warning but is still stored. Takes no flags.
oceancode auth
oceancode authAn interactive picker: 1 Anthropic API key, 2 Claude subscription (runs login), 3 GLM coding plan
(runs key zai-coding-plan). Needs both stdin and stdout to be a terminal and fails otherwise. Takes no
flags.
oceancode claude
oceancode claudeChecks the claude-code provider before you use it. It reports the claude binary's path (or claude.bin
from config), its --version, and whether a Claude Code login is present. Advisory only: it exits 0
whatever it finds. Any argument fails with usage: oceancode claude.
oceancode inspect
oceancode inspect [--json]Prints where every config key, skill, agent, command, MCP server and instruction file comes from, for the
current directory (there are no --dir/--home flags). Each human row is
kind id winning-layer source, and the last line is INSPECT_OK sources=<n>. With --json the JSON
array goes to stdout and the sentinel to stderr. Boots nothing. See
09 · Capabilities and plugins.
oceancode plugin
oceancode plugin [--root <home>] <subcommand>--root (also --root=<home>) overrides the home that the stores live under
(<home>/.oceancode/plugins and <home>/.oceancode/marketplaces).
| Sub-subcommand | Prints |
|---|---|
marketplace add <spec> / update <n> / remove <n> | PLUGIN marketplace-added|marketplace-updated|marketplace-removed <name> |
marketplace list | <name> plugins=<n> per marketplace |
install <name-or-path> [--trust] [--marketplace <m>] | PLUGIN installed <name> <version>, plus PLUGIN trusted <name> with --trust |
list | <name> <version> enabled=<bool> trusted=<bool> per plugin |
uninstall <n> / update <n> | PLUGIN uninstalled <n> / PLUGIN updated <n> <version> |
enable <n> / disable <n> | PLUGIN enabled|disabled <n> |
enable-all / disable-all | PLUGIN enabled-all|disabled-all count=<n> |
trust <n> [--off] | PLUGIN trusted|untrusted <n> |
validate <n> | PLUGIN validated <n> ok=<bool>, then one - <problem> line per problem |
import --from claude-code [--trust] [--no-repo-trust] [--dry-run] [--home <h>] [--dir <d>] | Ends with IMPORT_OK plugins=<n> marketplaces=<m> repo_trust=<bool> (IMPORT_DRY_RUN_OK … under --dry-run). import takes --home/--dir, not --root. |
See 09 · Capabilities and plugins.
oceancode mcp
oceancode mcp [--root <dir> | --dir <dir>] [--home <h>] <subcommand>--root (or its alias --dir) selects the project directory where .mcp.json lives; the default is the
current directory. --home selects the home tier.
| Sub-subcommand | Behaviour |
|---|---|
add <name> --command <cmd> [--arg <a>]… [--env K=V]… | Writes a stdio server to <dir>/.mcp.json under mcpServers.<name>. Prints MCP added <name> stdio. |
add <name> --url <url> [--header K=V]… | Writes a remote (type: http) server. Prints MCP added <name> remote. Pass exactly one of --command or --url. |
remove <name> | Deletes the entry from .mcp.json. Prints MCP removed <name>. |
enable <name> / disable <name> | Clears or sets the server's held-disabled bit in the trust store. Prints MCP_ENABLED/MCP_DISABLED <name>. |
list | One row per discovered server: name stdio|remote tier trusted|untrusted enabled|disabled|shadowed source. |
login <name> / logout <name> | login prints the OAuth callback URL and contacts no network. logout clears the stored OAuth entry. |
doctor | Connects to each server with a 2-second budget and prints one status row per server (connected, needs-auth, failed, disabled, untrusted). |
See 11 · MCP servers.
oceancode skill
oceancode skill [--root <dir>] [--dir <d>] [--home <h>] <subcommand>| Sub-subcommand | Behaviour |
|---|---|
create <name> [--description <text>] | Writes <root>/.oceancode/skills/<name>/SKILL.md (--root defaults to the current directory) and prints SKILL created <path>. Refuses to overwrite an existing skill. |
list [--json] | One row per discovered skill: id tier trusted|untrusted state description. state is enabled or the reason the skill is disabled. |
enable <id> / disable <id> | Flips one skill's user-tier enable bit. <id> is a stable id, or a bare name that matches exactly one skill. Prints SKILL enabled|disabled <id>. |
enable-all / disable-all | Prints SKILL enabled-all / SKILL disabled-all count=<n>. |
See 09 · Capabilities and plugins.
oceancode trust
oceancode trust show | repo on|off | mcp <name> on|off|clear [--dir <d>] [--home <h>]Reads and sets the per-project trust record in <home>/.oceancode/trust.json. show prints
repo=<bool>, then one mcp <name>=<bool> line per override and one disabled <name> line per held
server. Every subcommand ends with TRUST_OK. repo grants or revokes repo-tier execution (repo hooks
and .mcp.json servers). mcp sets a per-server override that takes precedence over repo, or clears
it. See 11 · MCP servers.
oceancode hooks
oceancode hooks [--dir <d>] [--home <h>] list [--json]
oceancode hooks add <Event> --command <cmd> [--matcher <re>] [--timeout <s>] [--scope user|project|local]
oceancode hooks remove <Event> --command <cmd> [--matcher <re>] [--scope user|project|local]list prints every hook source file the boot loader reads: one line per source with its tier, its trust,
whether it is loaded (or held, and why) and its path, followed by its handlers. The output ends with
HOOKS_OK sources=<n> handlers=<m> loaded=<k>. --json prints {"repo_trusted", "sources"} and no
sentinel. add and remove edit Claude Code's settings.json for the chosen scope (default project)
and print HOOK_ADDED <path> or HOOK_REMOVED <path>. Removing a handler that does not exist fails with
hooks remove: no such handler. See 10 · Hooks.
oceancode jev
oceancode jev status [--json]
oceancode jev probe [--record --point <p> --case <id> --request <req.json> --out <fixture.json> [--expect <json>]]
oceancode jev labels [--implicit | --unlabelled [--point <p>]] [--root <ledger dir>] [--out <file>]
oceancode jev questions --json
oceancode jev verdicts --in <cases.jsonl>Inspects the Jev decision layer, read from the current directory and the environment (no --dir/--home
flags). status prints one point mode endpoint-host line for each of the nine decision points —
permission, output_view, supervisor, triage, visibility, check, guidance, snippets,
effort — then JEV_STATUS_OK points=9; --json prints {points, endpoint, thresholds} instead, with
JEV_STATUS_EMITTED points=9 on stderr. On a project with no jev section every point is off:
permission off -
output_view off -
…
effort off -
JEV_STATUS_OK points=9probe makes one live call to Jev and prints JEV_PROBE_OK
or JEV_PROBE_FAIL <why>; probe --record records a fixture. labels exports labelled decisions
(JEV_LABELS_OK added=<n> total=<m>), each row's source telling a person's answer (shadow-user) from
the labels the effort and snippets points write themselves (implicit-effort, implicit-snippets);
--unlabelled requires --out. The tool_tiers and relevance points were retired on 2026-10-21
and no verb lists them. questions --json and
verdicts --in print the decision points' question sets and policy verdicts for the bench. Only probe
calls Jev. See 13 · Jev decisions.
oceancode doctor
oceancode doctor [--storage]Reports orphaned sessions (registry entries whose process died without a clean exit) and captured panic
reports found under the data dir. --storage adds the storage report: the sizes of oceancode.db and its
WAL, the session count, and the ledger directory's size and oldest session age. Read-only; any other
argument is ignored. See 18 · Operations.
oceancode migrate
oceancode migrate [--db <path>]Opens the database named by --db (default oceancode.db), migrates it to the current schema, prints
opened and migrated <path>, and exits.
oceancode update
oceancode update [--self-test]Updates itself to the newest release on the configured channel; OC_UPDATE_CHANNEL (stable/beta)
overrides update.channel. Both oceancode and ocean-pager are verified first, swapped atomically, and
rolled back together if a health check fails. Prints UPDATE_APPLIED from=<old> to=<new>, or
oceancode <v> is already the newest <channel> release. --self-test exercises the swap and rollback
offline on stub binaries and prints UPDATE_OK from=<old> to=<new> rollback_tested=1, then
UPDATE_SELF_TEST_OK binaries=2. No other argument is recognised. See
17 · Distribution and updates.
oceancode verify-release
oceancode verify-release <artifact> [--pubkey <base64>] [--sha256sums <path>]Verifies the artifact's minisign <artifact>.minisig signature without any external tool. --pubkey
replaces the embedded release key; --sha256sums also checks the artifact's entry in that SHA256SUMS
file. Prints VERIFY_RELEASE_OK file=<name>. See 17 · Distribution and updates.
oceancode uninstall
oceancode uninstall [--purge] [--yes] [--dry-run]Removes the installed oceancode binary from OC_INSTALL_DIR (default ~/.local/bin). --purge also
removes the app's config and data dirs, but never a project's .oceancode/oceancode.db. Unless --yes is
given, it lists every path and asks you to type oceancode to confirm. --dry-run prints
would remove: <path> lines and removes nothing. The last line is UNINSTALL_OK removed=<n>. See
17 · Distribution and updates.
See also
- 01 · Getting started — the three boot shapes.
- 02 · Configuration — every
OC_*variable these commands read. - 07 · Headless and server —
run,serve,workflow,goalin depth. - 09 · Capabilities and plugins, 10 · Hooks, 11 · MCP servers — the capability commands.
- 17 · Distribution and updates —
update,verify-release,uninstall.