Building Custom Skills for OpenClaw
Skills are OpenClaw’s extension system. They’re the difference between an agent that “can use tools” and an agent that “knows how to book a meeting room” or “knows how to send an iMessage.” Skills package up context, scripts, and templates into reusable, shareable units.
If you find yourself pasting the same instructions to an agent repeatedly, that’s a skill waiting to be written.
What Is a Skill?
Section titled “What Is a Skill?”A skill is a directory containing:
SKILL.md— The instruction manual the agent reads before executing the skill- Scripts — Helper programs the agent can run
- Templates — Output formats, config stubs, and reusable content
- Tests — Verification that the skill still works
When an agent encounters a task that matches a skill’s description, it reads SKILL.md and follows its instructions — using the scripts and templates packaged inside.
Directoryskills/
Directorytanner-rooms/
- SKILL.md ← Agent reads this first
Directoryscripts/
- reserve.py ← Booking automation
- list-available.py ← Check availability
Directorytemplates/
- confirmation.md ← Response format
Directorytests/
- test-reserve.sh ← Verify it still works
- README.md ← Human documentation
Why Skills Beat Prompts
Section titled “Why Skills Beat Prompts”You could paste instructions directly into your agent prompt every time. Skills are better because:
They’re reusable. Write once, use in any agent. Your coding agent, your research agent, your CEO agent — all can use the same Slack skill without duplicating config.
They’re testable. A skill with a tests/ directory can be regression-tested. If an API changes, your test catches it before your agent silently fails.
They’re shareable. Push a skill to ClaWHub and other users can openclaw skill install slack-curator. No copy-pasting prompt engineering.
They’re maintainable. When Slack changes their API, you update one SKILL.md and one script — not every agent prompt that uses Slack.
Anatomy of SKILL.md
Section titled “Anatomy of SKILL.md”SKILL.md is the heart of the skill. It’s what the agent actually reads and follows. Write it like you’re briefing a smart intern who’s never used this tool before.
A good SKILL.md has five sections:
# skill-name — Short description
## What This Skill DoesOne paragraph. What problem does it solve? When should the agentuse it vs. something else?
## Prerequisites- What needs to be installed- What credentials need to be set- What config files need to exist
## How to Use It
### Common Task 1Step-by-step instructions. Include actual commands.Reference scripts with relative paths: `./scripts/reserve.py`Include expected output so the agent knows success.
### Common Task 2...
## Script Reference
| Script | Purpose | Usage ||--------|---------|-------|| `scripts/reserve.py` | Book a room | `python3 scripts/reserve.py --room 210 --time 14:00 --duration 60` || `scripts/list-available.py` | Check availability | `python3 scripts/list-available.py --date 2026-03-27` |
## Error Handling
| Error | Cause | Fix ||-------|-------|-----|| `401 Unauthorized` | Session expired | Run `python3 scripts/login.py` first || `Room not available` | Already booked | Try adjacent time slots |
## Examples
Include 2-3 complete examples with full commands and expected output.Real examples are worth more than abstract documentation.Tutorial: Build a “GitHub Issues” Skill
Section titled “Tutorial: Build a “GitHub Issues” Skill”Let’s build a real skill from scratch. This skill lets any agent read GitHub issues, comment on them, and close them.
-
Create the skill directory
Terminal window mkdir -p ~/clawd/skills/github-issues/scriptsmkdir -p ~/clawd/skills/github-issues/templatesmkdir -p ~/clawd/skills/github-issues/tests -
Write the main script
~/clawd/skills/github-issues/scripts/list-issues.sh:#!/bin/bash# list-issues.sh — List open GitHub issues for a repo# Usage: ./list-issues.sh owner/repo [--label bug] [--limit 10]REPO="${1:?Usage: list-issues.sh owner/repo}"LABEL="${3:-}" # Optional --label flagLIMIT="${5:-20}"if [ -z "$GITHUB_TOKEN" ]; thenecho "Error: GITHUB_TOKEN not set in environment" >&2exit 1fiLABEL_FILTER=""if [ -n "$LABEL" ]; thenLABEL_FILTER="&labels=${LABEL}"ficurl -s \-H "Authorization: token $GITHUB_TOKEN" \-H "Accept: application/vnd.github.v3+json" \"https://api.github.com/repos/${REPO}/issues?state=open&per_page=${LIMIT}${LABEL_FILTER}" \| jq '.[] | {number: .number, title: .title, labels: [.labels[].name], created_at: .created_at}'Terminal window chmod +x ~/clawd/skills/github-issues/scripts/list-issues.sh -
Write a comment script
~/clawd/skills/github-issues/scripts/comment.sh:#!/bin/bash# comment.sh — Add a comment to a GitHub issue# Usage: ./comment.sh owner/repo issue_number "Your comment text"REPO="${1:?Usage: comment.sh owner/repo issue_number comment}"ISSUE="${2:?Missing issue number}"COMMENT="${3:?Missing comment text}"curl -s -X POST \-H "Authorization: token $GITHUB_TOKEN" \-H "Accept: application/vnd.github.v3+json" \"https://api.github.com/repos/${REPO}/issues/${ISSUE}/comments" \-d "{\"body\": \"$COMMENT\"}" \| jq '{id: .id, html_url: .html_url}' -
Create a response template
~/clawd/skills/github-issues/templates/issue-summary.md:## GitHub Issues Summary: {{REPO}}**Checked:** {{DATE}}**Open issues:** {{COUNT}}{{#each issues}}### #{{number}}: {{title}}- **Labels:** {{labels}}- **Opened:** {{created_at}}- **Link:** https://github.com/{{../repo}}/issues/{{number}}{{/each}} -
Write the SKILL.md
~/clawd/skills/github-issues/SKILL.md:# github-issues — Read and manage GitHub issues## What This Skill DoesLets agents read open GitHub issues, post comments, and closeissues via the GitHub API. Use this when asked to:- Check what issues are open on a repo- Summarize or triage issues- Comment on an issue with a response or fix- Close resolved issues## Prerequisites- `gh` CLI installed: `brew install gh` then `gh auth login`- OR GITHUB_TOKEN set in environment (from ~/.openclaw/.env)- `jq` installed: `brew install jq`## How to Use It### List open issues```bash# All open issuesbash ./scripts/list-issues.sh owner/repo# Filter by labelbash ./scripts/list-issues.sh owner/repo --label bug --limit 5Comment on an issue
Section titled “Comment on an issue”Terminal window bash ./scripts/comment.sh owner/repo 42 "Investigated this. The fix is in PR #43."Check issues using gh CLI (preferred when available)
Section titled “Check issues using gh CLI (preferred when available)”Terminal window gh issue list --repo owner/repo --state open --limit 10gh issue view 42 --repo owner/repogh issue comment 42 --body "Fixed in latest commit"Script Reference
Section titled “Script Reference”Script Purpose Key Args scripts/list-issues.shList open issues owner/repo [--label X] [--limit N]scripts/comment.shPost a comment owner/repo issue_number "text"Error Handling
Section titled “Error Handling”Error Cause Fix 401 UnauthorizedBad token Re-run gh auth login404 Not FoundRepo doesn’t exist or no access Check repo name and permissions jq: command not foundjq not installed brew install jqExamples
Section titled “Examples”List top 5 bugs:
Terminal window bash ./scripts/list-issues.sh facebook/react --label bug --limit 5Comment and close:
Terminal window bash ./scripts/comment.sh myorg/myrepo 17 "Resolved in v2.3.1"gh issue close 17 --repo myorg/myrepo -
Write a test
~/clawd/skills/github-issues/tests/test-list.sh:#!/bin/bash# Tests that list-issues.sh returns valid JSONecho "Testing github-issues skill..."# Should return JSON arrayRESULT=$(bash scripts/list-issues.sh octocat/Hello-World --limit 2 2>&1)if echo "$RESULT" | jq -e '.' > /dev/null 2>&1; thenecho "✓ list-issues returns valid JSON"elseecho "✗ list-issues failed: $RESULT"exit 1fiecho "All tests passed." -
Register the skill with OpenClaw
Add to
~/clawd/openclaw.json:{"skills": {"github-issues": {"path": "~/clawd/skills/github-issues","description": "Read and manage GitHub issues","triggers": ["github issues", "open issues", "check issues", "repo issues"]}}}
Testing Your Skill
Section titled “Testing Your Skill”Before trusting a skill in production, test it:
cd ~/clawd/skills/github-issues
# Test the scripts directlybash tests/test-list.sh
# Test via agentopenclaw chat main> Use the github-issues skill to list the top 5 open issues in torvalds/linuxWatch for these failure modes:
- Credential errors: Is
GITHUB_TOKENin your env? Does~/.openclaw/.envexport it? - Path errors: Scripts reference
./scripts/— always run from skill root or use absolute paths - API changes: Check the script output against current API docs if something breaks
Skill Template Patterns
Section titled “Skill Template Patterns”Some patterns show up in almost every skill:
Credential check at top of every script:
if [ -z "$GITHUB_TOKEN" ]; then echo "Error: GITHUB_TOKEN not set. Add to ~/.openclaw/.env" >&2 exit 1fiStructured JSON output (agents parse this reliably):
# Prefer structured output over human-readableecho '{"status": "success", "room": "210", "time": "14:00", "confirmation": "R-7821"}'Retry logic for flaky APIs:
import time, requests
def with_retry(fn, retries=3, delay=2): for i in range(retries): try: return fn() except requests.HTTPError as e: if e.response.status_code == 429: time.sleep(delay * (i + 1)) else: raise raise Exception(f"Failed after {retries} retries")Sharing on ClaWHub
Section titled “Sharing on ClaWHub”When your skill is solid, share it:
# Package the skillopenclaw skill pack github-issues --version 1.0.0
# Publish to ClaWHub (requires account)openclaw skill publish github-issues
# Others install with:openclaw skill install your-username/github-issuesGood skills to publish:
- Anything that requires non-obvious credential setup
- Tools with complex APIs that take time to figure out
- Workflow automations others likely need (booking systems, CRMs, etc.)
Quick Reference
Section titled “Quick Reference”| File | Purpose | Required? |
|---|---|---|
SKILL.md | Agent instruction manual | ✅ Yes |
scripts/ | Executable helpers | Recommended |
templates/ | Output formats | Optional |
tests/ | Regression tests | Strongly recommended |
README.md | Human documentation | Optional (for sharing) |
About the author: JD Davenport builds AI agent systems at OpenClaw. Follow on LinkedIn for updates on building AI agents for business.