Files
adolf/docs/tools/creating-skills.md
alvis bedb527145
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Vendor OpenClaw source as Adolf fork baseline
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11),
free to diverge. Tree copied sans upstream .git; upstream remote added for
future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19.
Preserves docs/ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
2026-07-05 09:36:54 +00:00

8.6 KiB

title, sidebarTitle, summary, read_when
title sidebarTitle summary read_when
Creating skills Creating skills Build, test, and publish custom SKILL.md workspace skills for your OpenClaw agents.
You are creating a new custom skill
You need a quick starter workflow for SKILL.md-based skills
You want to use Skill Workshop to propose a skill for agent review

Skills teach the agent how and when to use tools. Each skill is a directory containing a SKILL.md file with YAML frontmatter and markdown instructions. OpenClaw loads skills from several roots in a defined precedence order.

Create your first skill

Skills live in your workspace `skills/` folder:
```bash
mkdir -p ~/.openclaw/workspace/skills/hello-world
```

You can group skills in subfolders for organization — the skill is still
named by the `SKILL.md` frontmatter, not the folder path:

```bash
mkdir -p ~/.openclaw/workspace/skills/personal/hello-world
# skill name is still "hello-world", invoked as /hello-world
```
The frontmatter defines metadata; the body gives the agent instructions.
```markdown
---
name: hello-world
description: A simple skill that prints a greeting.
---

# Hello World

When the user asks for a greeting, use the `exec` tool to run:

```bash
echo "Hello from your custom skill!"
```
```

Naming rules:
- Use lowercase letters, digits, and hyphens for `name`.
- Keep the directory name and frontmatter `name` aligned.
- `description` is shown to the agent and in slash-command discovery —
  keep it one line and under 160 characters.
```bash openclaw skills list ```
OpenClaw watches `SKILL.md` files under skills roots by default. If the
watcher is disabled or you are continuing an existing session, start a new
one so the agent receives the refreshed list:

```bash
# From chat — archive current session and start fresh
/new

# Or restart the gateway
openclaw gateway restart
```
```bash openclaw agent --message "give me a greeting" ```
Or open a chat and ask the agent directly. Use `/skill hello-world` to
invoke it explicitly by name.

SKILL.md reference

Required fields

Field Description
name Unique slug using lowercase letters, digits, and hyphens
description One-line description shown to the agent and in discovery output

Optional frontmatter keys

Field Default Description
user-invocable true Expose the skill as a user slash command
disable-model-invocation false Keep the skill out of the agent's system prompt (still runs via /skill)
command-dispatch Set to tool to route the slash command directly to a tool, bypassing the model
command-tool Tool name to invoke when command-dispatch: tool is set
command-arg-mode raw For tool dispatch, forwards the raw args string to the tool
homepage URL shown as "Website" in the macOS Skills UI

For gating fields (requires.bins, requires.env, etc.) see Skills — Gating.

Using {baseDir}

Reference files inside the skill directory without hardcoding paths — the agent resolves {baseDir} against the skill's own directory:

Run the helper script at `{baseDir}/scripts/run.sh`.

Adding conditional activation

Gate your skill so it only loads when its dependencies are available:

---
name: gemini-search
description: Search using Gemini CLI.
metadata: { "openclaw": { "requires": { "bins": ["gemini"] }, "primaryEnv": "GEMINI_API_KEY" } }
---
| Key | Description | | --- | --- | | `requires.bins` | All binaries must exist on `PATH` | | `requires.anyBins` | At least one binary must exist on `PATH` | | `requires.env` | Each env var must exist in the process or config | | `requires.config` | Each `openclaw.json` path must be truthy | | `os` | Platform filter: `["darwin"]`, `["linux"]`, `["win32"]` | | `always` | Set `true` to skip all gates and always include the skill |
Full reference: [Skills — Gating](/tools/skills#gating).
Wire an API key to a skill entry in `openclaw.json`:
```json5
{
  skills: {
    entries: {
      "gemini-search": {
        enabled: true,
        apiKey: { source: "env", provider: "default", id: "GEMINI_API_KEY" },
      },
    },
  },
}
```

The key is injected into the host process for that agent turn only.
It does not reach the sandbox — see
[sandboxed env vars](/tools/skills-config#sandboxed-skills-and-env-vars).

Propose via Skill Workshop

For agent-drafted skills or when you want operator review before a skill goes live, use Skill Workshop proposals instead of writing SKILL.md directly.

# Propose a brand-new skill
openclaw skills workshop propose-create \
  --name "hello-world" \
  --description "A simple skill that prints a greeting." \
  --proposal ./PROPOSAL.md

# Propose an update to an existing skill
openclaw skills workshop propose-update hello-world \
  --proposal ./PROPOSAL.md \
  --description "Updated greeting skill"

Use --proposal-dir when the proposal includes support files:

openclaw skills workshop propose-create \
  --name "hello-world" \
  --description "A simple skill that prints a greeting." \
  --proposal-dir ./hello-world-proposal/

The directory must contain PROPOSAL.md at its root. Support files go under assets/, examples/, references/, scripts/, or templates/.

After review:

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

See Skill Workshop for the full proposal lifecycle.

Publishing to ClawHub

Make sure `name`, `description`, and any `metadata.openclaw` gating fields are set. Add a `homepage` URL if you have a project page. ```bash npm i -g clawhub clawhub login ``` ```bash clawhub skill publish ./path/to/hello-world ```
Add `--version <version>` or `--owner <owner>` to override the inferred
version or publish under a specific owner. See
[ClawHub — Publishing](/clawhub/publishing) and
[ClawHub CLI](/clawhub/cli) for the full flow, owner scoping, and other
maintenance commands (`clawhub sync`, `clawhub skill rename`, ...).

Best practices

- **Be concise** — instruct the model on *what* to do, not how to be an AI. - **Safety first** — if your skill uses `exec`, ensure prompts do not allow arbitrary command injection from untrusted input. - **Test locally** — use `openclaw agent --message "..."` before sharing. - **Use ClawHub** — browse community skills at [clawhub.ai](https://clawhub.ai) before building from scratch. Loading order, gating, allowlists, and SKILL.md format. Proposal queue for agent-drafted skills. Full `skills.*` config schema. Browse and publish skills on the public registry. Plugins can ship skills alongside the tools they document.