OpenClaw comes with plenty of built-in capabilities, but skills are where it gets interesting. A skill is a modular package that teaches OpenClaw how to work with a specific tool, API, or workflow. Instead of vague “I can try to help” responses, you get answers that actually use the right tools for the job.
This guide covers the built-in skills, how to pull in community skills from ClawHub, and how to build your own.
What Are OpenClaw Skills?
A skill is a self-contained directory with a SKILL.md file at its root. That file has:
- YAML frontmatter with metadata (name, description, allowed tools)
- Markdown instructions that guide how OpenClaw uses the skill
- Optional resources: scripts, reference docs, templates
When you ask OpenClaw to do something, it reads skill descriptions to find relevant ones. The instructions inside then shape how it handles your request.
Skills work like specialized training. The weather skill teaches OpenClaw to fetch forecasts. The GitHub skill shows it how to work with repos. Without skills, OpenClaw has general capabilities but no specific domain knowledge.
Built-in Skills Overview
OpenClaw ships with about 50 built-in skills. Here’s what you’ll probably use most:
Communication & Productivity
himalaya – Email via CLI. IMAP/SMTP support, multiple accounts, folders, composition. Good for automated email workflows.
discord – Discord operations through the message tool. Send messages, reactions, threads, polls. Uses Discord’s component system for rich UIs.
slack – Same pattern as Discord but for Slack workspaces.
notion – Full Notion API. Create pages, query databases, update properties. Uses the 2025-09-03 API version.
obsidian – Work directly with Obsidian vaults.
Development & DevOps
github – GitHub CLI wrapper. Check PR status, review workflow runs, query the API. Uses gh underneath.
coding-agent – Orchestrate Codex CLI, Claude Code, OpenCode. Includes patterns for parallel execution, background tasks, PR reviews.
tmux – Control tmux sessions remotely. Handy for interactive TTY operations, running agents in parallel, persistent background work.
Data & Content
weather – Weather forecasts without API keys. Uses wttr.in and Open-Meteo.
summarize – Extract and summarize URLs, PDFs, YouTube videos via summarize.sh.
web-search – Brave Search integration.
gog – Google Workspace CLI. Gmail, Calendar, Drive, Sheets, Docs, Contacts via OAuth.
Media & Files
openai-whisper – Local transcription with OpenAI’s Whisper models.
video-frames – Pull frames from video files for analysis.
canvas – Control node canvases for UI presentation and screenshots.
Utilities
1password – 1Password CLI integration for credentials.
model-usage – Track LLM API usage and costs.
healthcheck – System health monitoring.
The full list sits in your OpenClaw installation at skills/. Each skill’s SKILL.md has specifics.
Installing Community Skills from ClawHub
ClawHub is the community repository for OpenClaw skills. Think npm, but for skills.
Install the ClawHub CLI
npm i -g clawhub
Search for Skills
clawhub search "postgres backups"
clawhub search "stripe api"
Install a Skill
# Latest version
clawhub install my-skill
# Specific version
clawhub install my-skill --version 1.2.3
Skills install to ./skills by default. Override with --dir or set CLAWHUB_WORKDIR.
Update Skills
# Update one skill
clawhub update my-skill
# To a specific version
clawhub update my-skill --version 1.2.3
# Update everything
clawhub update --all
The update command hashes local files and handles version resolution. Use --force to override conflicts.
List Installed Skills
clawhub list
Publishing Your Own Skills
Built something useful? Share it:
clawhub login
clawhub publish ./my-skill --slug my-skill --name "My Skill" --version 1.2.0 --changelog "Fixes + docs"
How Skills Work: SKILL.md Structure
To use or build skills well, you need to understand SKILL.md.
YAML Frontmatter
Every SKILL.md starts with metadata:
---
name: weather
description: Get current weather and forecasts (no API key required).
homepage: https://wttr.in/:help
allowed-tools: ["bash", "exec"]
metadata:
openclaw:
emoji: "🌤️"
requires:
bins: ["curl"]
install:
- id: brew
kind: brew
formula: wttr
bins: ["wttr"]
label: "Install wttr (brew)"
---
Required fields:
name– Skill identifier (lowercase, hyphens)description– What it does and when to use it. This matters – OpenClaw uses this to decide whether to trigger the skill.
Optional fields:
homepage– Reference URL for the underlying tool/APIallowed-tools– Which tools this skill can usemetadata.openclaw– OpenClaw-specific config
The Description Field Is Critical
The description isn’t just docs – it’s how OpenClaw decides to use your skill. A good description says:
- What the skill does
- When to trigger it
- What files or operations it handles
Example from the docx skill:
description: "Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. Use when Codex needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks"
Body Content
After the frontmatter comes instructions, examples, workflows:
# Weather
Two free services, no API keys needed.
## wttr.in (primary)
Quick one-liner:
\`\`\`bash
curl -s "wttr.in/London?format=3"
# Output: London: ⛅️ +8°C
\`\`\`
## Open-Meteo (fallback, JSON)
Free, no key, good for programmatic use...
The body only loads when the skill triggers. Keep it focused on actionable guidance.
Allowed Tools
Skills can declare which tools they use:
allowed-tools: ["bash", "read", "write", "github"]
This sets guardrails. A weather skill doesn’t need browser or discord. If OpenClaw tries to use a non-allowed tool, it should reconsider.
Creating Your First Custom Skill
Let’s build a simple skill that checks website uptime with curl.
Step 1: Initialize the Skill Structure
OpenClaw has a skill creation helper. Find the skill-creator scripts:
cd /path/to/openclaw/skills/skill-creator/scripts
python3 init_skill.py uptime-checker --path ~/.openclaw/workspace/skills --resources scripts
This creates:
uptime-checker/
├── SKILL.md
└── scripts/
Step 2: Edit SKILL.md
Replace the template:
---
name: uptime-checker
description: Check website uptime and HTTP status. Use when the user asks about website availability, wants to verify a site is up, or needs to check HTTP response codes. Works with any URL.
metadata:
openclaw:
requires:
bins: ["curl"]
---
# Uptime Checker
Quick HTTP status checks.
## Single URL Check
```bash
curl -s -o /dev/null -w "%{http_code}" https://example.com
Check with Timing
curl -s -o /dev/null -w "HTTP %{http_code} | Time: %{time_total}s | Size: %{size_download}b" https://example.com
Follow Redirects
curl -s -L -o /dev/null -w "Final URL: %{url_effective} | Code: %{http_code}" https://bit.ly/xxx
Check Multiple Sites
for site in google.com github.com example.com; do
code=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 "https://$site")
echo "$site: $code"
done
Common Status Codes
- 200: OK
- 301/302: Redirect
- 403: Forbidden
- 404: Not Found
- 500: Server Error
- 503: Service Unavailable
- 0: Connection failed (DNS, timeout, refused)
### Step 3: Test the Skill
Put the skill directory in your workspace's `skills/` folder and ask OpenClaw:
> "Check if my website is up"
OpenClaw should recognize the task, load your skill, and use the curl patterns you defined.
## Skills Directory Structure and Conventions
### Standard Layout
skill-name/
├── SKILL.md # Required – main instructions
├── scripts/ # Optional – executable code
│ ├── helper.py
│ └── utils.sh
├── references/ # Optional – documentation
│ ├── api-reference.md
│ └── examples.md
└── assets/ # Optional – templates, files
├── template.docx
└── logo.png
### Naming Conventions
- **Skill names**: lowercase, hyphens, max 64 characters (`website-monitor`, `pdf-utils`)
- **Directory**: Must match the skill name exactly
- **Files**: Use lowercase with hyphens or underscores
### Resource Types
**scripts/** - Executable utilities
- Python, bash, or any executable
- Run directly without loading into context
- Good for deterministic operations
**references/** - Documentation
- Loaded into context when needed
- API docs, schemas, detailed guides
- Keep SKILL.md lean, put details here
**assets/** - Output resources
- Templates, images, fonts
- Not loaded into context
- Used in final output
### Progressive Disclosure
Skills load in three levels:
1. **Metadata** (name + description) - Always in context (~100 words)
2. **SKILL.md body** - Loaded when skill triggers (<5k words ideal)
3. **References** - Loaded on demand (unlimited)
This keeps context usage efficient. Don't dump everything into SKILL.md - link to references for detailed content.
## Skill Best Practices
### Keep SKILL.md Under 500 Lines
Context windows are shared. The tighter your skill, the better it performs. Move detailed content to references.
### Write Clear Descriptions
The description field determines when your skill activates. Be specific about:
- What problems it solves
- What file types it handles
- What user requests should trigger it
Bad: "A skill for working with APIs"
Good: "Stripe API operations for payment processing, subscription management, and invoice generation. Use when the user mentions Stripe payments, subscriptions, checkout sessions, or billing operations."
### Use Concrete Examples
Show actual commands, not abstract descriptions:
```markdown
# Good
curl -s "wttr.in/London?format=3"
# Less good
Use the wttr.in service to fetch weather data for a location
Handle Variations with References
If your skill supports multiple providers or patterns, keep the main skill focused:
# SKILL.md
## AWS Deployment
See [references/aws.md](references/aws.md) for EC2, Lambda, and S3 patterns.
## GCP Deployment
See [references/gcp.md](references/gcp.md) for Cloud Run and GKE patterns.
Don’t Include Extraneous Files
Skills should only contain what the AI needs to do the job. Skip:
– README.md
– CHANGELOG.md
– INSTALLATION_GUIDE.md
– Test files
Test Your Scripts
If you include scripts, run them. A broken script in a skill is worse than no script at all.
Example: Building a Complete Custom Skill
Let’s build something more complex: a Hacker News reader that fetches stories and comments.
Create the Structure
python3 init_skill.py hackernews-reader --path ~/.openclaw/workspace/skills --resources scripts,references
Write SKILL.md
---
name: hackernews-reader
description: Fetch and read Hacker News stories, comments, and user profiles. Use when the user asks about HN stories, wants to summarize comment threads, or needs to find top posts on specific topics. Includes top/new/best story listings and full comment tree retrieval.
metadata:
openclaw:
requires:
bins: ["curl", "jq"]
---
# Hacker News Reader
Use the official Hacker News API (firebaseio.com).
## API Basics
Base URL: `https://hacker-news.firebaseio.com/v0/`
All endpoints return JSON. No auth required.
## Story Listings
### Top Stories
```bash
curl -s "https://hacker-news.firebaseio.com/v0/topstories.json" | jq '.[0:10]'
Returns an array of story IDs. Get the first 10 with .[0:10].
New Stories
curl -s "https://hacker-news.firebaseio.com/v0/newstories.json" | jq '.[0:10]'
Best Stories
curl -s "https://hacker-news.firebaseio.com/v0/beststories.json" | jq '.[0:10]'
Ask HN
curl -s "https://hacker-news.firebaseio.com/v0/askstories.json" | jq '.[0:10]'
Show HN
curl -s "https://hacker-news.firebaseio.com/v0/showstories.json" | jq '.[0:10]'
Job Stories
curl -s "https://hacker-news.firebaseio.com/v0/jobstories.json" | jq '.[0:10]'
Get Story Details
STORY_ID=12345
curl -s "https://hacker-news.firebaseio.com/v0/item/${STORY_ID}.json"
Response fields:
– title – Story title
– url – Link URL (null for text posts)
– text – Self-post text (HTML)
– by – Username
– score – Upvote count
– time – Unix timestamp
– descendants – Comment count
– kids – Array of comment IDs
Get Comments
Comments use the same item endpoint:
COMMENT_ID=67890
curl -s "https://hacker-news.firebaseio.com/v0/item/${COMMENT_ID}.json"
Response fields:
– by – Username
– text – Comment text (HTML)
– time – Unix timestamp
– kids – Child comment IDs (for threads)
– parent – Parent item ID
Get User Profiles
USERNAME=patio11
curl -s "https://hacker-news.firebaseio.com/v0/user/${USERNAME}.json"
Response fields:
– id – Username
– created – Account creation (Unix timestamp)
– karma – Karma score
– about – Profile text (HTML)
– submitted – Array of submission IDs (last 100 or so)
Batch Fetch Example
Get top 5 stories with titles and URLs:
curl -s "https://hacker-news.firebaseio.com/v0/topstories.json" | \
jq -r '.[0:5][]' | \
while read id; do
curl -s "https://hacker-news.firebaseio.com/v0/item/${id}.json" | \
jq -r '[.title, .url, .score] | @tsv'
done
Comment Thread Depth
HN comments nest. A comment’s kids field contains child comment IDs. To get a full thread, recursively fetch children.
See references/comment-fetching.md for a complete recursive fetch script.
### Add Reference Documentation
Create `references/comment-fetching.md`:
```markdown
# Fetching Comment Threads
Hacker News comments are trees. Each comment has a `kids` array of child IDs.
## Recursive Fetch Script
Use this Python script for deep comment threads:
\`\`\`python
#!/usr/bin/env python3
import requests
import sys
def fetch_item(item_id):
url = f"https://hacker-news.firebaseio.com/v0/item/{item_id}.json"
return requests.get(url).json()
def fetch_comments(item_id, depth=0, max_depth=3):
item = fetch_item(item_id)
if not item:
return
indent = " " * depth
text = item.get('text', '')[:200].replace('\n', ' ')
print(f"{indent}{item.get('by', 'unknown')}: {text}...")
if depth < max_depth and 'kids' in item:
for kid_id in item['kids'][:5]: # Limit to 5 children per level
fetch_comments(kid_id, depth + 1, max_depth)
if __name__ == "__main__":
story_id = sys.argv[1] if len(sys.argv) > 1 else "1"
fetch_comments(story_id)
\`\`\`
## Rate Limiting
The Firebase API has no explicit rate limits, but be reasonable:
- Batch related requests
- Cache results when possible
- Don't recursively fetch thousands of comments
## HTML in Text Fields
Both story `text` and comment `text` fields contain HTML:
- `<p>` for paragraphs
- `<a href="...">` for links
- `'` for escaped quotes
Strip or render as needed for your output format.
Create a Helper Script
Create scripts/fetch_top.py:
#!/usr/bin/env python3
"""Fetch top HN stories with formatted output."""
import requests
import json
def main():
# Get top story IDs
response = requests.get("https://hacker-news.firebaseio.com/v0/topstories.json")
story_ids = response.json()[:10]
stories = []
for story_id in story_ids:
story = requests.get(f"https://hacker-news.firebaseio.com/v0/item/{story_id}.json").json()
stories.append({
"title": story.get("title", "No title"),
"url": story.get("url", f"https://news.ycombinator.com/item?id={story_id}"),
"score": story.get("score", 0),
"comments": story.get("descendants", 0),
"by": story.get("by", "unknown")
})
print(json.dumps(stories, indent=2))
if __name__ == "__main__":
main()
Make it executable:
chmod +x scripts/fetch_top.py
Test It
Put it in your skills directory and try:
“What’s on the front page of Hacker News?”
“Get the top 5 stories from HN”
“Fetch the comments for story 12345”
Package for Sharing
Ready to share?
# From the skill-creator scripts directory
python3 package_skill.py ~/.openclaw/workspace/skills/hackernews-reader
# Produces: hackernews-reader.skill
Then publish to ClawHub:
clawhub publish ./hackernews-reader.skill --slug hackernews-reader --name "Hacker News Reader" --version 1.0.0
Troubleshooting Skills
Skill Not Triggering
Check your description. Is it specific enough? Does it mention the right trigger words?
Tools Not Working
Verify allowed-tools in the frontmatter. If a skill needs browser but only declares bash, it won’t work.
Missing Dependencies
Use metadata.openclaw.requires to declare binary dependencies:
metadata:
openclaw:
requires:
bins: ["curl", "jq", "python3"]
env: ["API_KEY"]
Context Too Long
If your skill is slow or hitting limits:
– Move content to references/
– Split long examples
– Remove redundant explanations
Conclusion
Skills are how OpenClaw extends itself. Built-in skills cover common needs, ClawHub has community solutions, and custom skills let you encode your specific workflows.
Start small. Build a skill for one repetitive task. Iterate based on real usage. Share what works.
The skill ecosystem grows when users publish solutions. Your weekend project might save someone else hours.