For AI agents: a documentation index is available at https://www.plungeai.com/docs/llms.txt. Append .md to any page URL, or send Accept: text/markdown, to get markdown. Setup instructions for agents are at https://www.plungeai.com/docs/agents.md. One ozk_ key opens every plane, models included.

Documentation Index: fetch the complete documentation index at /llms.txt. Use this file to discover all available pages before exploring further.

Skills, sub-agents, personas, commands and MCP servers are all capabilities, and oceancode finds them the same way: one discovery walk over five tiers, across four ecosystems, with a single rule for names that collide and a separate rule for what a capability is allowed to do.

The five tiers

A capability is discovered from one of five tiers. The walk runs from the narrowest scope out to the widest, so a name defined closer to the code wins.

TierWhere it comes fromExample root
LocalThe project's own .oceancode/ — your machine's private copy, git-ignored.oceancode/skills, .oceancode/agents
RepoThe project you are in, checked into the repo.claude/, .opencode/, .grok/
UserYour home directory, read across every ecosystem~/.oceancode/…, ~/.claude/…, ~/.grok/…
BundledShipped inside the binary(built in)
PluginAn installed plugin's own tree<plugin>/skills/, <plugin>/agents/

Plugin-tier roots are enumerated from disk — one root per installed plugin directory — so a plugin contributes its skills, agents and hooks only while it is installed. For plugins Claude Code installed, the roots are exact: only the version directories its ~/.claude/plugins/installed_plugins.json records for the user scope, or for this project, are walked (one root per plugin even when the file lists the same install twice), and a plugin you have disabled in ~/.claude/settings.json (enabledPlugins) stays disabled here. A project's own .claude/settings.json can never re-enable a plugin you disabled.

The .oceancode/ directory in a project is the local tier — your machine's private copy, trusted precisely because it is not shared repo content — and is git-ignored in this monorepo.

Four ecosystems

Each tier is read for four ecosystems at once, so a capability written for another tool is picked up without conversion:

  • OceanCode — the native .oceancode/ layout.
  • Claude Code — .claude/ (skills, agents, rules, settings.json).
  • OpenCode — .opencode/ (opencode.json, agents).
  • Grok Build — .grok/ (agents, personas, rules, memory).

Frontmatter and directory conventions from each ecosystem are translated into the one internal shape as they are read; you do not have to rewrite a Claude Code skill or a Grok persona to use it here.

Rule files may pull in other files with @path imports (up to four hops); an import is bounded to the project directory and your home directory, so a rule can never inline a file from elsewhere on disk.

A rule may scope itself to a file glob in its frontmatter — paths: "**/*.py" (Claude Code / OpenCode) or globs: "**/*.ts" (a Cursor .mdc). A scoped rule is loaded only when the working tree actually contains at least one file matching its glob; in a checkout with no match it is left out entirely, so a TypeScript project does not carry Python or Ruby rule bodies. The check honours your ignore rules (.gitignore, .git pruned) and runs once per session. Scope today is resolved for the whole checkout, not per individual file the current turn touches. A rule with no paths/globs is always loaded — with one Cursor exception: a .mdc under .cursor/rules that says alwaysApply: false and has no globs is Cursor's agent-requested or manual rule, which Cursor attaches only when asked, and the engine leaves it out too (a globs: rule keeps its scope whatever the flag says; the key means nothing outside .cursor/rules).

Workflow scripts

Workflow scripts are discovered the same way, from two OceanCode roots in the usual precedence (built-in > project > user). Every *.rhai file under a root is one workflow, identified by the meta.name its script declares — not by its file name:

ScopeRootFiles
Project.oceancode/workflows*.rhai
User~/.config/oceancode/workflows*.rhai

Two workflows ship built in to the binary — the highest tier — so they run by name with no *.rhai file on disk. Built-ins cannot be shadowed: a project or user script with the same meta.name as a built-in is ignored (dropped from the picker catalog with a warning), and the built-in still runs — that is what "built-in > project > user, first wins" means. A duplicate meta.name across two discovered files likewise keeps the first (project before user).

NameArgsWhat it does
deep-researchquery (or objective); breadth 2–6, default 4Researches the query with bounded parallelism across four phases — Plan, Research, Verify, Report — independently cross-checks every candidate claim, and writes a cited report.
goalobjective; skeptics 1–5, default 3; max_rounds, default 10; optional worker_model, verifier_modelProves an objective is done, not just claimed done: plans it into verifiable deliverables, works in rounds with one resumed worker, then has a panel of adversarial skeptics try to refute completion. Converges only when a strict majority of the cold panel fails to refute; pauses on identical gaps two rounds running or a spent agent budget.
pipelinesteps: [{ prompt, label?, model?, agent_type?, output_schema? }]; stop_on_failure, default trueRuns an ordered list of agent steps one after another; each step is given the previous step's output. Stops at the first failed step unless stop_on_failure is false.

Names that collide are qualified; unique names stay bare

A capability keeps its bare name when that name is unique across everything discovered. Only when the same name appears more than once is it qualified, and only the colliding members are rewritten:

SituationQualified name
Same name at two different tierstier:name (e.g. repo:review)
Same tier, different ecosystemstier.<ecosystem>:name (e.g. repo.claude_code:review, repo.open_code:review)
A plugin tier<plugin>:name
A residual same-tier, same-ecosystem tietier.<ecosystem>.<root-dir>:name

The pass reads only each item's bare name and source, so it is idempotent — running discovery again yields the same qualified names in the same order.

The slash name of a plugin skill is always <plugin>:name, even when the name is unique — Claude Code's convention, so /superpowers:writing-plans lists and runs in the Ocean pager's / popup exactly as it does there. Typed as a prompt, /<plugin>:name and the bare /name both run an enabled plugin skill; a <plugin>: prefix that names no installed plugin does not resolve (a warning toast; the text is then sent as a normal message).

Enable is not trust

Two independent gates decide what a capability does:

  • Enabled — whether the capability is discovered and offered at all. Disabling a plugin removes its capabilities from the walk — including its rule bodies, which no longer inject into the system prompt (its skills, agents, commands, hooks and MCP servers drop too).
  • Trusted — whether a capability that can execute code on your behalf is allowed to run without a prompt. Only hooks and MCP servers gate on trust; a skill or a persona is inert data and needs no trust decision.

By default, Local, User and Bundled tiers are trusted; the Repo tier is untrusted (code that arrived with a checkout has not been vetted by you); a Plugin is trusted only if you installed it with trust. So enabling a repo-supplied hook is not the same as trusting it — it is discovered, but it will not run its command until you trust it.

Trust decisions for a project persist in ~/.oceancode/trust.json, keyed by the project's absolute path: repo (may the repo tier's hooks and .mcp.json servers execute?), mcp (per-server overrides that beat repo) and disabled_mcp (servers held disabled at any tier). Plugin trust lives beside the plugin in ~/.oceancode/plugins/installed.json. Set them with oceancode trust repo on|off, oceancode trust mcp <name> on|off|clear, oceancode plugin trust <name> [--off], or from the /hooks, /mcp and /plugins pickers; read them with oceancode trust show.

Enabling and disabling skills

Loading every skill from every tier costs prompt tokens — one <available_skills> line and one skill_* tool per skill, plus a disabled plugin's rule bodies. Skills, plugins and MCP servers share one enable interface so you can turn off what you are not using; a disabled skill costs nothing (it is not in <available_skills>, registers no skill_* tool, and its rules do not inject).

A skill's effective state is the fold of four tiers, resolved in this order — the first that turns it off wins, so a project can disable a skill but can never re-enable one you disabled:

#TierTurned off byskill list reason
1PluginThe skill's plugin is disabled (oceancode plugin disable)disabled (plugin)
2UserYou disabled the skill (~/.oceancode/skill-state.json)disabled (user)
3Projectskills.disabled in .oceancode/oceancode.jsondisabled (project)
4Allowlistskills.mode = "allowlist" and the skill is not in skills.enablednot in allowlist

The per-skill user toggle is written by the CLI (or the /skills picker) into ~/.oceancode/skill-state.json — OceanCode's own store, never Claude's ~/.claude/settings.json. The project policy (mode, disabled, enabled) lives in .oceancode/oceancode.json under skills (see 02 · Configuration); default mode all keeps every skill a candidate. The project policy is a default: an explicit enable of one skill (Space on its row, a plugin-group header's Space, or oceancode skill enable <id>) is also recorded for this project as enabled_skills in ~/.oceancode/trust.json and beats the project's skills.disabled and allowlist (tiers 3–4), so a skill the allowlist leaves out can be switched on without editing the config; it never beats the master switch or a disabled plugin, a disable drops it again, and enable-all stays user-tier only. MCP keeps its own disabled_mcp / enabled_mcp model (oceancode mcp enable|disable, see 11 · MCP servers); the verbs are the same shape.

oceancode skill enable <id>            # clear the user-tier disable; beats the project policy
oceancode skill disable <id>           # disable this skill at the user tier
oceancode skill enable-all             # clear every user-tier skill disable
oceancode skill disable-all            # disable every currently-discovered skill

<id> is a skill's stable id <tier>.<eco>:<name> — e.g. user.claude_code:agents-sdk, local.ocean_code:tdd, repo.open_code:deep — shown in the id column of skill list. It is computed the same way whether or not the name collides with another tier, so the store never loses a disable when a session sees only one tier. You may also pass a bare name when exactly one discovered skill has it (oceancode skill disable wrangler); a name shared by more than one skill is refused with the candidate ids, so pass the full id to pick one. A bare name is still accepted in skills.disabled/skills.enabled and as a legacy store entry (it matches every copy of that name). If you disabled skills before this change, re-run oceancode skill disable-all once to rewrite the store with stable ids.

A toggle takes effect on the next step of the running session. The /skills and capabilities pickers, the /skill invocation gate and the Ocean pager's composer / completion update at once (an enabled skill is offered as /<skill>, a disabled one is not); the <available_skills> block, the skill_* tools, the MCP tool list and the hook dispatcher are rebuilt before the agent's next model call, so the very next request no longer carries what you turned off. A step already running finishes with what it started with. Each change made mid-session costs one system-prompt cache rewrite (the cached prefix changes once), so flip several things together rather than one per turn. A change made from a shell (oceancode skill disable-all) lands on the next step too.

Whole groups and everything at once. In the Ocean pager's capabilities picker (/skills, /plugins, /hooks, /mcps) Space works at four levels:

Row under the cursorSpace togglesAsks first
A skill, plugin, hook or MCP serverthat one itemno
A Plugin: <name> header (Skills, MCP tabs) or a hook source header (Hooks tab)every row in the groupabove 10 rows
All skills / All plugins / All MCP / All hooks (second row of the tab)the whole kindyes
Everything (first row of every tab)the master switchyes

Everything off removes skills, MCP tools, hooks and plugin rules from the agent's context; the built-in tools (bash, read, edit, …) stay. Turning it back on restores exactly the per-item state you had. A group whose rows are all off shows [off] on its header, and the picker's last row shows the live counts — skills 22/259 · plugins 2/21 · mcp 1/10 · hooks 8/8 — with EVERYTHING OFF in front while the master switch is off. Group and master state is per project, stored next to disabled_mcp in ~/.oceancode/trust.json; per-skill disables stay in skill-state.json. The Plugins tab lists Claude Code's cached plugins (under User (Claude)) beside the OceanCode-store ones, and Space turns a whole plugin — its skills, hooks, MCP servers and rules — off or on.

Start from nothing. To strip the prompt down and add capabilities back deliberately, disable everything and re-enable one by one: oceancode plugin disable-all (then re-enable from /plugins), and oceancode skill disable-all with skills.mode = "allowlist" + a short skills.enabled list for the handful of skills you actually want. With every plugin disabled and an empty allowlist, the first turn carries no <available_skills> block and no skill_* tools at all.

oceancode inspect — where did this come from?

To see the winning source of every capability, config key, MCP server and instruction file for the current directory:

oceancode inspect          # a human-readable provenance table
oceancode inspect --json   # a stable JSON array (for scripts)

Each row names the kind, the id, the layer that won, and the file it came from — the fastest way to answer "why is this skill loaded and not that one?". It boots nothing and is read-only.

instruction rows list what the directory contributes to the system prompt: one primary file — CLAUDE.md, else AGENTS.md, never both, so a generated AGENTS.md mirror is not loaded twice — then CLAUDE.local.md and CONTEXT.md when present. The same rule applies at every level from the worktree root down to the working directory, and to the reminder that fires when a tool first touches a directory this session. The system prompt is fixed for the rest of a prompt, so an edit to these files (or a URL instruction expiring, or midnight passing) made while a prompt runs applies from the next prompt, not the next step; switching a capability or the model still applies on the very next step.

Plugins and marketplaces

A plugin bundles skills, agents and hooks under one installable tree. Manage them from the CLI:

oceancode plugin marketplace add <spec>      # register a marketplace
oceancode plugin marketplace list
oceancode plugin marketplace update <name>
oceancode plugin marketplace remove <name>

oceancode plugin install <name-or-path> [--trust] [--marketplace <m>]
oceancode plugin list
oceancode plugin enable <name>               # / disable <name>
oceancode plugin enable-all                  # / disable-all — flip every installed plugin
oceancode plugin trust <name> [--off]        # grant / revoke trust
oceancode plugin validate <name>             # check the manifest
oceancode plugin update <name>               # / uninstall <name>

install without --trust enables the plugin but leaves it untrusted, so its hooks and MCP servers stay dormant until you run plugin trust. Pass --root <dir> to any plugin subcommand to point at a project other than the current directory.

In Ocean pager, /plugins opens the Plugins tab of the capabilities picker; see 19 · Ocean pager.

Importing from Claude Code

If you already use Claude Code, one command brings its setup here:

oceancode plugin import --from claude-code --dry-run   # show what would happen, write nothing
oceancode plugin import --from claude-code --trust     # do it, trusting the imported plugins

What it does, and what it deliberately does not:

  • Plugins are copied from Claude Code's cache (~/.claude/plugins/cache/<marketplace>/<name>/<version>/) into ~/.oceancode/plugins — only the versions installed for the user scope or for this project — and each is enabled or disabled as your ~/.claude/settings.json says. Without --trust they are enabled but untrusted, so their hooks and MCP servers stay dormant.
  • Marketplaces Claude Code knows (known_marketplaces.json) are registered.
  • Trust is seeded from Claude Code's own record in ~/.claude.json: the project's hasTrustDialogAccepted becomes repo=true (pass --no-repo-trust to opt out), servers in disabledMcpServers / disabledMcpjsonServers are held disabled, enabledMcpjsonServers are trusted.
  • Skills, commands, agents, rules, hooks and MCP configs at the user and repo tiers are not copied. ~/.claude/skills, ~/.claude/commands, ~/.claude/settings.json, .claude/** and .mcp.json are read where they are, so they stay in sync with Claude Code.

Every line the command prints names one action (IMPORT, SKIP, MISSING, MARKETPLACE, TRUST); the last line is IMPORT_OK plugins=<n> marketplaces=<m> repo_trust=<bool> (with --dry-run, IMPORT_DRY_RUN_OK …). A cache tree that is not a plugin — Claude Code's rust-analyzer-lsp / typescript-lsp entries carry neither a manifest nor a SKILL.md — is reported SKIP <name> not a plugin and one entry that fails to install is reported SKIP <name> install failed: <why>; neither stops the run, so the trust seeding at the end always happens. Nothing under ~/.claude is ever modified.

/skills — browse and run

Every discovered skill — yours, the project's, a plugin's, from any of the four ecosystems — is a slash command: /<name> <arguments> runs it as a command turn whose prompt is the skill body prefaced by a one-line instruction, with $ARGUMENTS and the positional rules applied. A name that collides across tiers is invoked by its qualified form (/repo:review). The completion popup lists skills with the other commands.

In Ocean pager, /skills opens the Skills tab of the capabilities picker and the composer's / completion lists your enabled skills; see 19 · Ocean pager. Without a session:

oceancode skill list            # id  tier  trusted|untrusted  <state>  description
oceancode skill list --json     # each row carries "id", "enabled" and a "reason" tag when disabled

The id column is the stable <tier>.<eco>:<name> id (--json also keeps the collision-resolved qualified name); copy it straight into oceancode skill enable|disable <id>.

The state column reads enabled, or why the skill is off — disabled (plugin), disabled (user), disabled (project) or not in allowlist (see Enabling and disabling skills).

See also

  • 10 · Hooks — the one capability that gates on trust and can change a run.
  • 11 · MCP servers — the other trust-gated capability, and its own translation table.
  • 19 · Ocean pager — /plugins, /skills, /mcps, /hooks in the terminal UI; the pager's other commands are in ocean-pager/crates/ocean-pager-ui/docs/user-guide/.
  • 07 · Headless and server — every management subcommand in one table.

Planned: TI-34

The docs assistant is not available yet. You can hand these docs to your own assistant instead.