AgentSkills.site

OpenClaw Skills: The Practical Guide

Most guides to OpenClaw skills name directories that aren't in the official load order at all. Here's the real precedence chain, the dependency gating that hides skills you can't run, and the per-skill prompt cost — quoted from the docs and checked against the bundled skills themselves.

Published

AgentSkills.site editorial

What OpenClaw skills are

OpenClaw is an open-source personal AI assistant that runs locally and connects to the messaging platforms and tools you already use. A skill is a directory containing a SKILL.md file — YAML frontmatter plus markdown instructions. OpenClaw's own documentation puts the purpose crisply: skills "teach the agent how and when to use tools."

OpenClaw follows the Agent Skills open standard, which its docs state directly. The same SKILL.md works in Claude Code, Codex, Cursor, and Hermes Agent — what differs is everything around it, and OpenClaw has more of that machinery than any other agent covered on this site.

The minimum skill is two fields:

---
name: image-lab
description: Generate or edit images via a provider-backed image workflow
---

When the user asks to generate an image, use the `image_generate` tool...

Where OpenClaw loads skills from

Six sources, in a documented precedence order. "When the same skill name appears in multiple places, the highest source wins."

Priority Source Path
1 — highest Workspace skills <workspace>/skills
2 Project agent skills <workspace>/.agents/skills
3 Personal agent skills ~/.agents/skills (default state only)
4 Managed / local skills <state-dir>/skills
5 Bundled skills shipped with the install
6 — lowest Extra directories skills.load.extraDirs + plugin skills

<state-dir> defaults to ~/.openclaw, so priority 4 is normally ~/.openclaw/skills — that's the directory --global installs write to.

A correction worth making explicitly, because it affects whether your skill loads at all: several widely-linked guides teach .openclaw/skills/ as the project skills directory. That path is not in the load order. Project-level skills go in <workspace>/skills or <workspace>/.agents/skills.

Discovery is recursive — OpenClaw finds a skill "whenever SKILL.md appears anywhere under a configured root (up to 6 levels deep)". The folder path is organisational only:

<workspace>/skills/research/SKILL.md          → skill "research"
<workspace>/skills/personal/research/SKILL.md → also skill "research"

The name comes from the frontmatter name field, falling back to the directory name. Agent allowlists match on that name too.

Codex directories are deliberately not roots

Worth knowing if you run both, because OpenClaw and Cursor made opposite decisions here. From the docs:

Codex CLI's native $CODEX_HOME/skills directory is not an OpenClaw skill root. Use openclaw migrate plan codex to inventory those skills, then openclaw migrate codex to copy them into your OpenClaw workspace.

Cursor reads ~/.codex/skills for compatibility. OpenClaw refuses to and gives you a migration command instead. Note that ~/.agents/skills is an OpenClaw root, so a skill kept in the cross-agent location is shared without any migration at all.

Coming from Claude Code

openclaw migrate claude copies Claude skills with a SKILL.md into the OpenClaw workspace skills directory, structurally unchanged. Two details from the migration docs are more interesting than the copy itself:

  • Claude command files under .claude/commands/ "are converted into OpenClaw skills with disable-model-invocation: true" — the same conversion Cursor's /migrate-to-skills performs on its own commands.
  • CLAUDE.md content is copied or appended into the OpenClaw workspace AGENTS.md.

Hooks, permission allowlists, CLAUDE.local.md, .claude/rules/, and Claude subagents do not transfer; the docs describe them as archive-only for manual review.

openclaw migrate claude --dry-run
openclaw migrate apply claude --yes

The frontmatter

Required: name and description. The optional fields are where OpenClaw diverges most from the portable spec:

Field Default What it does
homepage URL shown as "Website" in the macOS Skills UI
user-invocable true Expose the skill as a user slash command
disable-model-invocation false "keeps the skill's instructions out of the agent's normal prompt". Still reachable as a slash command when user-invocable is true
command-dispatch Set to tool and the slash command bypasses the model entirely
command-tool Which tool to invoke under tool dispatch
command-arg-mode raw Forwards the raw args string; the tool receives { command, commandName, skillName }

command-dispatch: tool is unusual enough to call out: it produces a skill the model never sees or reasons about. You type the command, OpenClaw hands the raw arguments straight to a registered tool. No other ecosystem covered here has an equivalent — it's closer to an alias than to a skill in the usual sense.

One parsing quirk to be aware of when writing frontmatter: it's "parsed as YAML first; if that fails, it falls back to a single-line-only parser," and nested metadata blocks are flattened to JSON and re-parsed as JSON5. That's why the gating examples below use JSON-style braces inside YAML frontmatter and still work.

In the body, {baseDir} resolves to the skill's own directory — use it for referencing bundled scripts rather than hardcoding a path.

Gating: skills that hide when you can't run them

This is OpenClaw's most distinctive mechanism and it's almost entirely absent from third-party coverage. Skills are filtered at load time using a metadata.openclaw block. A skill with no such block "is always eligible unless explicitly disabled."

Key Behavior
requires.bins Every listed binary must exist on PATH
requires.anyBins At least one listed binary must exist on PATH
requires.env Each env var must exist in the process or be provided via config
requires.config Each openclaw.json path must be truthy
os Hard platform filter: ["darwin"], ["linux"], ["win32"]
always Include whenever os is compatible, bypassing all requires.* checks
primaryEnv Env var wired to skills.entries.<name>.apiKey
install Installer specs used by the macOS Skills UI

The bundled skills use this in practice. Reading them directly from the repository:

# skills/peekaboo/SKILL.md
metadata:
  {
    "openclaw":
      {
        "emoji": "👀",
        "os": ["darwin"],
        "requires": { "bins": ["peekaboo"] },
        ...
      },
  }

So the macOS UI-automation skill simply doesn't exist as far as a Linux agent is concerned. 1password gates on the op binary, mcporter on mcporter, gemini on gemini. The effect is that a large bundled library doesn't clutter the prompt with capabilities the machine can't actually perform.

Note the os filter is described as hard: always does not override it.

Skills that know how to install their own dependency

The install key is a real mechanism, not documentation. A skill can declare how to obtain the binary it's gated on:

# skills/1password/SKILL.md
metadata:
  {
    "openclaw":
      {
        "requires": { "bins": ["op"] },
        "install":
          [
            {
              "id": "brew",
              "kind": "brew",
              "formula": "1password-cli",
              "bins": ["op"],
              "label": "Install 1Password CLI (brew)",
            },
          ],
      },
  }

Documented selection behavior: with multiple installers listed the gateway picks one — brew when available, otherwise node — and the overall preference order is Homebrew → uv → configured node manager → go → download. Node installs honour skills.install.nodeManager (npm by default; pnpm, yarn, and bun are options).

One gotcha the docs are explicit about: "requires.bins is checked on the host at skill load time. If an agent runs in a sandbox, the binary must also exist inside the container."

Invoking a skill

Three forms, and the first is easy to miss because it isn't a slash:

  • $name in the composer. Type $ in the Control UI to search available skills; selecting one inserts a stable reference without replacing the rest of your message. You can reference several in one prompt:

    Use $github and $release_notes to summarize this change for the release.
    

    A single message may reference up to eight distinct skills — beyond that OpenClaw "returns a visible error instead of ignoring extra references."

  • /name ... is the standalone command form, and it's the one that can use direct tool dispatch.

  • /skill <name> invokes explicitly by name.

A neat detail: uppercase shell-style variables like $HOME, $PATH, and $EDITOR stay literal text, while lowercase $home, $path, $editor reference skills with those names. Escape a reference as \$name when you want it left alone.

Skills with disable-model-invocation: true stay out of the $ picker and out of the model's prompt — but an authorized explicit $skill-name reference still invokes them. The flag hides a skill from model-initiated selection; it doesn't disable it.

What skills actually cost

OpenClaw publishes more precise numbers here than any other agent covered on this site, and they're worth knowing because they explain the authoring advice.

Eligible skills are compiled into a compact XML block injected into the system prompt. Per the docs:

  • Per skill: "~97 characters + your name, description, and location field lengths."
  • "At ~4 chars/token, 97 chars ≈ 24 tokens per skill before field lengths."
  • XML escaping expands & < > " ' into entities, adding a few characters each.
  • Base overhead applies only when at least one skill is eligible.

When the rendered block would exceed skills.limits.maxSkillsPromptChars, OpenClaw degrades in a documented order rather than truncating arbitrarily: preserve as many skill identities as the compact format allows, spend any remaining budget on shortened descriptions, omit descriptions entirely if nothing is left — and note openclaw skills check in the prompt so you know it happened.

That's why OpenClaw's own authoring guide asks for a description that's "one line and under 160 characters," far tighter than the 1,024-character ceiling the portable spec permits. The description is a recurring cost in every session, not a one-off.

For comparison, all documented rather than measured by us: Codex caps its index at 2% of context or 8,000 characters; Claude Code's equivalent default is around 1%; Cursor publishes no figure at all.

Snapshots: why your new skill didn't appear

OpenClaw "snapshots eligible skills when a session starts and reuses that list for all subsequent turns in the session." So a skill added mid-conversation generally isn't visible until the next session.

Two exceptions refresh it mid-session, picked up on the next agent turn: the skills watcher detecting a SKILL.md change (on by default, 250 ms debounce, configurable at skills.load.watch), and a newly connected eligible remote node.

If in doubt, start a new session with /new or restart the gateway.

Allowlists: separating where a skill lives from who can use it

Precedence decides which copy of a skill wins. Allowlists decide which agent can see it at all — a separate control, configured under agents:

{
  agents: {
    defaults: { skills: ["github", "weather"] },
    entries: {
      writer: { default: true },        // inherits the defaults
      docs: { skills: ["docs-search"] }, // replaces them entirely
      "locked-down": { skills: [] },     // no skills
    },
  },
}

A non-empty entry list "is the final set — it does not merge with defaults." The allowlist applies "across prompt building, slash-command discovery, sandbox sync, and skill snapshots."

The docs attach a caveat that deserves repeating rather than paraphrasing:

This is not a host shell authorization boundary. If the same agent can use exec, constrain that shell separately with sandboxing, OS-user isolation, exec deny/allowlists, and per-resource credentials.

In other words, restricting an agent's skills is context management, not a security control. What that means in practice is on the security page.

Turning a skill on or off

Bundled and managed skills are configured under skills.entries in ~/.openclaw/openclaw.json:

{
  skills: {
    entries: {
      peekaboo: { enabled: true },
      sag: { enabled: false },
      "image-lab": {
        enabled: true,
        apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" },
      },
    },
  },
}

Keys match the skill name unless the skill sets metadata.openclaw.skillKey. allowBundled is a bundled-only allowlist that leaves managed and workspace skills untouched. The bundled coding-agent skill is opt-in — it needs enabled: true plus one of claude, codex, opencode, or another supported CLI installed and authenticated.

Environment variables and API keys from skills.entries are injected into process.env for the duration of the run and restored afterwards — and, importantly, "scoped to the host agent run, not the sandbox."

Skill Workshop: agent-drafted skills, reviewed first

OpenClaw's agent can propose skills rather than write them. Skill Workshop is "a proposal queue between the agent and your active skill files. When the agent spots reusable work, it drafts a proposal instead of writing directly to SKILL.md. You review and approve before anything changes."

openclaw skills workshop list
openclaw skills workshop inspect <proposal-id>
openclaw skills workshop evaluate <proposal-id>
openclaw skills workshop apply <proposal-id>

The closest analogue elsewhere is Hermes Agent's staged-write approval queue, which gates its self-editing behind /skills pending|diff|approve|reject. Both are review gates on agent-authored skills, and no other ecosystem covered here has one. Authoring detail is on how to create an OpenClaw skill.

An implementation detail worth knowing if you also run Claude Code

From the docs, describing what happens with the bundled claude-cli backend:

OpenClaw also materializes the same eligible skill snapshot as a temporary Claude Code plugin and passes it via --plugin-dir. Other CLI backends use the prompt catalog only.

So when OpenClaw drives Claude Code, your OpenClaw skills reach it through Claude Code's plugin system rather than through its skills directories. A concrete instance of the two ecosystems interoperating at a level neither one advertises.

Skills vs plugins vs MCP, in OpenClaw

Concept What it is How it reaches the agent
Skill SKILL.md plus optional bundled files, teaching how and when to use tools Compiled into the system prompt as an XML block; invoked via $, /, or model selection
Plugin A packaged extension that can add tools and ship its own skills Skills contributed at the lowest precedence tier
MCP server An external protocol connection exposing tools Configured separately. The bundled mcporter skill exists precisely to teach the agent to drive them

That last row is the clearest illustration of the layer distinction anywhere in this ecosystem: mcporter is a skill whose entire job is listing, configuring, authenticating against, and calling MCP servers. The skill is the knowledge; MCP is the access. See Agent Skills vs MCP.

Limitations and caveats

  • We have not installed or run OpenClaw. Everything here is documented behavior or read directly from the openclaw/openclaw repository, and this page says which.
  • skills.limits.maxSkillsPromptChars has a configurable default that the skills documentation doesn't state. The degradation behavior is documented; the number isn't, so none is given here.
  • The per-skill token figure (~97 characters, ≈24 tokens) is OpenClaw's own published estimate, not our measurement.
  • OpenClaw is under very active development — the repository was pushed to the same day this page was researched, 16 August 2026. Check the official docs if you're reading this much later.

Sources