OpenClaw ships with dozens of built-in skills, and the ClawHub marketplace hosts over 13,700 community-built ones. But the real power shows up when you build your own. A custom skill turns a repetitive multi-step workflow into a single command your agent executes consistently every time, without you re-explaining the steps.
This guide covers the full skill development lifecycle: how SKILL.md files work, how to write instructions that produce reliable agent behavior, and three complete skills you can copy, paste, and modify today.
If you have not set up OpenClaw yet, start with our setup guide and come back here once your agent is running.
What OpenClaw Skills Are (and Are Not)
A skill is a folder containing a SKILL.md file. That file has YAML frontmatter describing what the skill does, followed by markdown instructions the agent reads when the skill activates. There is no compiled code, no SDK, no build step. You write plain English instructions, and the agent follows them.
Skills are not MCP servers, though over 65% of active skills now wrap an underlying MCP server. The distinction matters: an MCP server exposes tools (functions the agent can call), while a skill provides the workflow logic that decides when and how to call those tools. Think of MCP servers as the hands, and skills as the playbook telling the hands what to do.
Skills are also not integrations. Integrations connect OpenClaw to messaging channels like Telegram or Slack. Skills operate one layer above that, defining what the agent does once a message arrives.
Anatomy of a SKILL.md File
Every skill starts with a single file. Here is the minimal viable structure:
---
name: my-skill
description: One-line summary of what this skill does and when to use it.
---
# My Skill
## Workflow
1. Parse the user's request for relevant parameters.
2. Execute the required action using available tools.
3. Return results in the specified format.
Two fields in the frontmatter are required: name and description. Everything else is optional but often useful. The markdown body below the frontmatter is where the agent’s instructions live.
Frontmatter Reference
| Field | Required | What It Controls |
|---|---|---|
name | Yes | Unique identifier for the skill |
description | Yes | Triggers skill selection. Be specific about use cases |
user-invocable | No | Whether users can trigger via slash command (default: true) |
disable-model-invocation | No | Exclude from model context entirely (default: false) |
metadata | No | Single-line JSON for gating, emoji, OS, dependencies |
The metadata field deserves extra attention. It must be a single-line JSON string, not a YAML block. This catches people:
# Correct - single-line JSON
metadata: {"openclaw":{"emoji":"📊","requires":{"bins":["node","curl"],"env":["API_KEY"]}}}
# Wrong - will not parse
metadata:
openclaw:
emoji: "📊"
The description field does double duty. It is both human-readable documentation and the trigger mechanism. OpenClaw reads descriptions to decide which skill matches a user’s request. A vague description like “handles data” means your skill rarely activates. A specific one like “Generate weekly ops reports from server log files and GitHub PRs” means it fires exactly when needed.
The Instruction Body
The markdown below frontmatter is the agent’s runbook. This is where most skills succeed or fail.
The pattern is clear across the OpenClaw community: weak skills read like product descriptions. Strong skills read like checklists you would hand to someone covering your on-call shift at 3 AM.
Good instructions are specific, sequential, and explicit about what to do when things go wrong.
Structure your instructions with these sections:
- Purpose: When this skill should activate and what it produces
- Workflow: Numbered steps with exact actions. Not “process the data” but “read all .csv files in the specified directory, extract rows where column B exceeds the threshold, and output a markdown table”
- Output format: What the result looks like. Include a template if the format matters
- Guardrails: What the agent must never do. “Never delete files without confirmation.” “Never fabricate issue IDs.”
- Failure handling: What to do when a step fails. “If the API returns a 401, tell the user their key is expired and stop.”
Skill Directory Structure
A skill only needs its SKILL.md file. But complex skills benefit from additional files:
my-skill/
SKILL.md # Required - instructions and metadata
scripts/ # Optional - helper scripts (Python, Bash, Node)
fetch-data.sh
process.py
references/ # Optional - context docs loaded on demand
api-docs.md
field-mapping.md
The scripts/ folder holds executable code your skill references. If your skill needs to call an API with specific headers, parse a CSV, or run a database query, put the script here and reference it from your SKILL.md instructions.
The references/ folder holds supplementary documentation the agent can read when it needs deeper context. This is useful for large API references or domain-specific knowledge that would bloat the main SKILL.md file. Reference files load on demand rather than injecting into every prompt, which saves tokens.
Where Skills Live
OpenClaw loads skills from multiple locations, checked in this order:
- Workspace skills:
<workspace>/skills/(highest priority) - Project agent skills:
<workspace>/.agents/skills/ - Personal agent skills:
~/.agents/skills/ - Managed skills:
~/.openclaw/skills/(installed via ClawHub) - Bundled skills: Shipped with OpenClaw
- Extra directories: Via
skills.load.extraDirsconfig
When two skills share the same name, the highest-priority location wins. This means you can override any built-in or ClawHub skill by placing a modified version in your workspace.
For skills you want available across all your workspaces, use ~/.openclaw/skills/. For project-specific skills, use <workspace>/skills/. If you are setting up your workspace for the first time, our OpenClaw memory configuration guide covers the workspace folder structure in detail.
Build Your First Skill: Daily Standup Summary
Start with something small that solves a real problem. Here’s how to build a skill that reads your recent Git commits and open issues, then generates a standup summary:
---
name: standup-summary
description: Generate a daily standup summary from Git commits and GitHub issues. Use when the user asks for a standup update, daily summary, or what they worked on.
metadata: {"openclaw":{"emoji":"📋","requires":{"bins":["git","gh"]}}}
---
# Daily Standup Summary
## Purpose
Generate a concise standup update covering yesterday's work, today's plan, and blockers.
## Workflow
1. Run `git log --oneline --since="yesterday" --author="$(git config user.name)"` to get recent commits.
2. Run `gh issue list --assignee=@me --state=open --limit=10` to get open issues assigned to the user.
3. Run `gh pr list --author=@me --state=open` to get open pull requests.
4. Combine results into the output format below.
## Output Format
Return markdown with three sections:
### Yesterday
- List each commit as a bullet point with the commit message
- Group related commits under a single bullet
### Today
- List open issues as planned work items
- List open PRs needing review or merge
### Blockers
- If any issue has a "blocked" label, list it here
- If no blockers exist, write "None"
## Guardrails
- Never fabricate commit messages or issue numbers.
- If git or gh commands fail, report the error and stop.
- Only include commits from the current repository.
## Example
User: "Give me my standup update"
Agent: Runs the three commands, formats the output, and presents the standup summary.
Save this as <workspace>/skills/standup-summary/SKILL.md. Start a new session (type /new in your OpenClaw chat) to load it. Then ask your agent: “Give me my standup update.”
Testing and Debugging Skills
Skill development is iterative. Here is the workflow that saves time:
1. Verify Your Skill Loaded
After creating or modifying a SKILL.md, start a new session and run:
openclaw skills list
Your skill should appear in the output. If it does not, check:
- The file is named exactly
SKILL.md(case-sensitive) - The frontmatter has valid YAML with
nameanddescriptionfields - The metadata JSON (if present) is valid single-line JSON
- Required binaries from
requires.binsexist on your PATH
For more detail, run:
openclaw skills list --verbose
This shows why specific skills were excluded (missing binary, wrong OS, missing env variable).
2. Enable Hot Reload for Development
By default, OpenClaw captures eligible skills when a session starts and reuses that snapshot. Changes to SKILL.md mid-session are ignored until you start a new session.
For faster iteration, enable file watching in your openclaw.json:
{
"skills": {
"load": {
"watch": true,
"watchDebounceMs": 250
}
}
}
With this enabled, saving your SKILL.md immediately updates the skill in your current session.
3. Test Trigger Accuracy
Ask your agent something that should trigger your skill. If the wrong skill activates or no skill activates, your description field needs work. The description is the primary mechanism OpenClaw uses to match user requests to skills.
Test with varied phrasing: “run my standup,” “what did I work on yesterday,” “standup update.” If your skill misses any of these, expand the description to include those trigger phrases.
4. Test Failure Paths
Deliberately break things. Disconnect from the internet, revoke an API key, point to a nonexistent directory. Verify your failure handling instructions produce useful error messages rather than the agent guessing or hallucinating a response.
Three Complete Skill Examples
These are production-ready skills you can copy into your workspace and start using immediately. Each solves a different category of problem.
Example 1: API Caller (Weather Report)
This skill calls an external API, parses the response, and formats it for the user:
---
name: weather-report
description: Fetch current weather and 3-day forecast for any city. Use when the user asks about weather, temperature, forecast, or "should I bring an umbrella."
metadata: {"openclaw":{"emoji":"🌤️","requires":{"bins":["curl"],"env":["WEATHER_API_KEY"]},"primaryEnv":"WEATHER_API_KEY"}}
---
# Weather Report
## Purpose
Fetch and format weather data from WeatherAPI.com for any requested location.
## Setup
The user must have a WEATHER_API_KEY environment variable set. Free tier keys
are available at https://www.weatherapi.com/signup.aspx
## Workflow
1. Extract the city name from the user's message. If no city is specified, ask.
2. Run: `curl -s "https://api.weatherapi.com/v1/forecast.json?key=$WEATHER_API_KEY&q=CITY&days=3&aqi=no"`
3. Parse the JSON response.
4. Format the results using the output template below.
## Output Format
**Current: [City], [Country]**
- Temperature: [temp_c]C / [temp_f]F
- Condition: [condition text]
- Humidity: [humidity]%
- Wind: [wind_kph] km/h [wind_dir]
**3-Day Forecast:**
| Date | High | Low | Condition | Rain Chance |
|------|------|-----|-----------|-------------|
| [date] | [maxtemp_c]C | [mintemp_c]C | [condition] | [daily_chance_of_rain]% |
## Guardrails
- Never guess weather data. Only report what the API returns.
- If the API returns an error, show the error message and suggest checking the API key.
- If the city is ambiguous (multiple matches), ask the user to be more specific.
## Failure Handling
- 401 response: Tell the user their WEATHER_API_KEY is invalid or expired.
- 400 response: City not found. Ask the user to check the spelling.
- Network error: Report that the weather service is unreachable.
Example 2: Web Scraper (Price Monitor)
This skill uses the browser to check a product page and report price changes:
---
name: price-monitor
description: Check the current price of a product from its URL and compare to a stored baseline. Use when the user asks to check a price, monitor a product, or asks "did the price change."
metadata: {"openclaw":{"emoji":"💰","requires":{"bins":["curl"]}}}
---
# Price Monitor
## Purpose
Fetch a product page, extract the current price, compare it to the last
recorded price, and alert the user if it changed.
## Data Storage
Maintain a file at `<workspace>/price-monitor/prices.json` with this structure:
```json
{
"items": [
{
"url": "https://example.com/product",
"name": "Product Name",
"lastPrice": 49.99,
"lastChecked": "2026-04-01T10:00:00Z",
"priceHistory": [
{"price": 54.99, "date": "2026-03-15T10:00:00Z"},
{"price": 49.99, "date": "2026-03-28T10:00:00Z"}
]
}
]
}
Workflow
- If the user provides a URL, fetch the page content using WebFetch.
- Extract the product name and current price from the page content.
- Read
prices.json. If the file does not exist, create it. - Compare the current price to
lastPricefor that URL. - Update the record with the new price and timestamp.
- Report the result to the user.
Output Format
[Product Name]
- Current price: $[price]
- Previous price: $[lastPrice] ([date])
- Change: [+/-amount] ([percentage]%)
- Status: [DROPPED / INCREASED / UNCHANGED]
If checking all monitored items, return a table:
| Product | Current | Previous | Change |
|---|
Guardrails
- Never fabricate prices. Only report what the page content shows.
- If the price cannot be extracted from the page, say so and show the URL for manual checking.
- Do not make purchases or add items to carts.
Failure Handling
- If the page cannot be fetched, report the HTTP status and suggest the user check the URL.
- If the page structure changed and price extraction fails, flag it for manual review.
### Example 3: File Processor (CSV Report Generator)
This skill processes local files and produces structured output:
```markdown
---
name: csv-report
description: Analyze CSV files and generate summary reports with statistics, charts, and key findings. Use when the user asks to analyze a CSV, summarize data, generate a report from a spreadsheet, or find patterns in tabular data.
metadata: {"openclaw":{"emoji":"📊","requires":{"bins":["node"]}}}
---
# CSV Report Generator
## Purpose
Read a CSV file, compute summary statistics, identify patterns, and produce
a formatted markdown report.
## Workflow
1. Ask for the file path if not provided. Verify the file exists and is a valid CSV.
2. Read the first 5 rows to identify column names and data types.
3. For each numeric column, compute: min, max, mean, median, standard deviation.
4. For each text column with fewer than 20 unique values, compute value counts.
5. Identify the top 3 correlations between numeric columns (if more than one numeric column exists).
6. Check for data quality issues: missing values, duplicate rows, outlier values (beyond 3 standard deviations).
7. Format everything into the output template.
## Output Format
# Report: [filename]
**Rows:** [count] | **Columns:** [count] | **Generated:** [timestamp]
## Column Summary
| Column | Type | Non-Null | Unique | Example |
|--------|------|----------|--------|---------|
## Numeric Statistics
| Column | Min | Max | Mean | Median | Std Dev |
|--------|-----|-----|------|--------|---------|
## Category Breakdown
For each categorical column, show the top 10 values by count.
## Data Quality
- Missing values: [count] across [columns]
- Duplicate rows: [count]
- Outliers detected: [details]
## Key Findings
Bullet list of 3-5 notable patterns or insights from the data.
## Guardrails
- Never modify the original CSV file.
- If the file has more than 100,000 rows, analyze a random sample of 10,000 and state this in the report.
- Do not attempt to open .xlsx or .xls files. Only CSV is supported.
- If a column contains what appears to be personally identifiable information (emails, phone numbers, SSNs), flag it but do not include the actual values in the report.
## Failure Handling
- File not found: Report the error and ask the user to check the path.
- Parse error: Show the first 3 lines of the file and ask if the delimiter is correct.
- Empty file: Report that the file contains no data rows.
Writing Instructions That Work
The skills that produce consistent, reliable output share five characteristics:
1. Deterministic steps, not vague goals. “Analyze the data” is a goal. “Read all .csv files in the directory, compute row count and null percentage per column, flag columns with more than 10% nulls” is a step. Agents follow specific instructions far more reliably than they interpret vague ones.
2. Explicit output format. If you care about how the result looks, include a template. Otherwise the agent will improvise, and the format will vary between runs.
3. Guardrails as hard boundaries. The agent treats guardrails as constraints. “Never delete files” works better than “be careful with files.” State what must not happen.
4. Failure paths as first-class citizens. If your skill only describes the happy path, the agent will hallucinate its way through errors. Every external dependency (API call, file read, command execution) needs a “what if this fails” instruction.
5. Trigger-rich descriptions. The description field controls whether your skill activates. Include the exact phrases users might say. If people ask for a “standup,” “daily update,” and “what I worked on,” all three phrases should appear in or near the description.
When to Build vs. When to Compose
Not every problem needs a custom skill. Ask two questions before building:
Can existing skills chain together to solve this? If you need to fetch a webpage, extract data, and save it to a file, check whether the built-in WebFetch and file tools already handle each step. Composing existing skills means less maintenance and automatic improvements when upstream skills update.
Will I use this more than twice? If it is a one-off task, just tell your agent what to do in conversation. Skills are for repeated workflows where consistency matters.
Build a custom skill when:
- You need domain-specific logic that general skills cannot provide
- The workflow has specific guardrails or output formats you need enforced every time
- You are connecting to a proprietary API or internal tool
- Multiple team members need the same workflow to behave identically
Installing and Publishing on ClawHub
Installing Community Skills
Browse and install directly from the command line:
openclaw skills search "calendar"
openclaw skills install calendar-sync
openclaw skills list
Before installing any community skill, review its SKILL.md. The 2026 ClawHavoc incident, where over 1,100 malicious skills were uploaded to the registry, is a reminder that community skills are untrusted code. Check the publisher’s profile, read the instructions, and look for community ratings.
Publishing Your Skills
Share your skills with the community:
npm i -g clawhub
clawhub login
clawhub skill publish ./skills/my-skill --slug my-skill --name "My Skill" --version 1.0.0 --tags "productivity,reports"
Publishing requires a GitHub account at least one week old. Use semantic versioning. Write a clear description, because that is how users find your skill in search results.
Security Best Practices
Skills run with the same permissions as your OpenClaw agent. Treat skill development with the same care you would give any code that runs on your machine.
Store secrets in environment variables. Never hardcode API keys in SKILL.md. Use the requires.env metadata field to declare what your skill needs, and set the actual values in your shell profile or .env file.
Declare minimal dependencies. Only list binaries and environment variables your skill genuinely needs. Every declared dependency is a surface area for misconfiguration.
Write readable instructions. Skills should be reviewable like code. If someone cannot scan your SKILL.md and understand what it does in under two minutes, it is too complex or too opaque.
Test with restricted permissions. Before publishing a skill, verify it works without access to sensitive directories like ~/.ssh or ~/.gnupg.
Frequently Asked Questions
Where do I put custom skill files?
Place them in <workspace>/skills/your-skill-name/SKILL.md for workspace-specific skills. For skills you want across all workspaces, use ~/.openclaw/skills/your-skill-name/SKILL.md. Workspace skills take priority over all other locations.
How do I test a skill without restarting OpenClaw?
Enable hot reload by adding "skills": {"load": {"watch": true}} to your openclaw.json. With this enabled, saving your SKILL.md immediately updates the skill. Without it, type /new to start a fresh session that picks up changes.
Do skills use extra tokens?
Yes. Each skill adds roughly 24 tokens of overhead to your prompt, plus the escaped length of its name and description. The instruction body only loads when the skill activates, so having many installed skills costs minimal tokens during normal conversation.
Can I override a built-in skill?
Yes. Place a skill with the same name in your workspace skills/ folder. Workspace skills have the highest loading priority, so your version replaces the built-in one for that workspace.
What is the difference between a skill and an MCP server?
An MCP server exposes tools, which are functions the agent can call. A skill provides workflow instructions that tell the agent when and how to use those tools. Many skills wrap MCP servers, combining the tool layer with a behavior layer.
How do I share a skill with my team privately?
Put the skill folder in a shared Git repository and add the repo path to skills.load.extraDirs in each team member’s openclaw.json. The skills sync whenever the repo updates.
Can a skill call external APIs?
Yes. Skills can instruct the agent to use curl, fetch, or any CLI tool available on the system. Declare the required binary in metadata.openclaw.requires.bins so the skill only loads on machines where the tool is installed.
What if my skill stops triggering?
Check openclaw skills list --verbose to see if the skill loaded. If it loaded but does not trigger, the description field likely does not match the user’s phrasing. Expand the description with more trigger phrases and synonyms.
Key Takeaways
- A skill is a folder with a
SKILL.mdfile containing YAML frontmatter and markdown instructions. No compilation, no SDK. - Write instructions like an operations runbook: specific steps, explicit output formats, clear failure handling, and hard guardrails.
- Test iteratively using
openclaw skills list --verboseand hot reload. Test failure paths, not just happy paths. - Build custom skills for repeated workflows where consistency and guardrails matter. For one-off tasks, just talk to your agent.
- Treat community skills as untrusted code. Review before installing. Store secrets in environment variables, never in skill files.
For a broader view of what OpenClaw can do beyond custom skills, see our OpenClaw heartbeat scheduling guide and OpenClaw pricing breakdown.
SFAI Labs