If you have a working OpenClaw skill and you want more people than just your coworker on Slack to use it, ClawHub is where you publish. This guide shows exactly how to get a skill from your laptop into the public catalog, pass the automated checks, survive the human security review, and keep the thing running as OpenClaw keeps shipping weekly minors.

What ClawHub Expects From a Published Skill

ClawHub is a curated registry, not a file dump. Every submission is linted, sandbox-tested, and scanned before it shows up in the UI. Understanding the checklist up-front saves three rounds of “please fix the following”.

  • OpenClaw version: your skill must declare compatibility with at least openclaw@>=3.4.0. The review bot installs that exact version to run tests.
  • Repository: public on GitHub or GitLab, MIT, Apache-2.0, or GPL-3.0 only.
  • Metadata file: skill.json in the repo root, 1 KB max, UTF-8.
  • Unit tests: minimum 80% coverage; Jest or Vitest.
  • Security: no plaintext API keys, must use OpenClaw’s getSecret() helper.
  • Docs: README.md with usage, inputs, outputs, and a GIF under 4 MB.

1. Scaffold the Skill Folder Correctly

If you used npx openclaw@latest init --skill you’re 90% there. If you started from scratch, match this minimal tree:

my-weather-skill/ ├── src/ │ └── index.ts ├── __tests__/ │ └── index.test.ts ├── skill.json ├── README.md ├── LICENSE └── package.json

Key points:

  • src/index.ts must export a default Skill instance.
  • skill.json is machine-readable metadata; ClawHub ignores your package.json description field.
  • Tests live in __tests__ so the CI runner can glob **/__tests__/**/*.test.*.

skill.json schema

{ "name": "my-weather-skill", "displayName": "Weather by Coordinates", "description": "Returns current weather for latitude/longitude using the Open-Meteo API.", "version": "1.0.0", "license": "MIT", "author": "Jane Doe <jane@doe.dev>", "openClaw": ">=3.4.0", "inputs": { "lat": { "type": "number", "description": "Latitude" }, "lon": { "type": "number", "description": "Longitude" } }, "outputs": { "temperature": { "type": "number", "unit": "°C" } }, "permissions": ["https://api.open-meteo.com/*"], "homepage": "https://github.com/janedoe/my-weather-skill" }

Run the schema validator before submitting:

npx @openclaw/validator skill.json

2. Write Tests That the Bot Can Run Headless

ClawHub uses the same GitHub Actions matrix as the core repo: Node 22 on Ubuntu, macOS, and Windows. Your Jest config should not rely on a display or Docker-in-Docker. If your skill spins a browser, switch to the --ci Chromium bundle:

npm install --save-dev @openclaw/headless-chromium

Example test for our weather skill:

import skill from ".."; describe("weather skill", () => { it("returns temp as number", async () => { const out = await skill.run({ lat: 47.01, lon: 15.43 }); expect(typeof out.temperature).toBe("number"); }); });

Generate coverage:

jest --coverage

The coverage summary is parsed; if it’s <80% your PR gets the friendly red X.

3. Security Review: Secrets, Network, and Sandboxing

This is where most submissions stall. The security bot (claw-ci-sec-001) replays your tests inside Firecracker VMs with seccomp filters. The job fails if:

  • You read /etc/passwd or anything outside /sandbox.
  • The code tries to spawn a shell without declaring "shell": true in skill.json permissions.
  • An outbound request hits a domain not whitelisted in permissions.
  • Any environment variable matches /[_-]?key|token|secret/i and is longer than 8 chars.

Fixes:

  • Use context.http.fetch instead of axios; it auto-adds the allowlist header.
  • Store tokens via ClawCloud’s UI; fetch at runtime: const apiKey = await context.secrets.get("OPEN_METEO_KEY").
  • Document every external call in permissions.

Manual review

Once the bot passes, a human reads the diff. Average SLA is 48 business hours. The reviewer mainly checks for:

  • Clipboard or file exfiltration patterns.
  • License compliance (no vendored GPL in MIT repo).
  • Reasonable resource usage (no while(true){…} crypto loops).

Pro tip: add a SECURITY.md explaining threat model and trade-offs. It speeds the manual pass.

4. Submit to ClawHub: The PR Dance

Publishing is a pull request to openclawhub/skills. Fork, add a directory under /skills/<your-skill>, commit, and open PR. Template:

git clone https://github.com/openclawhub/skills.git cd skills mkdir my-weather-skill cp -r ../my-weather-skill/* ./my-weather-skill/ git checkout -b add/my-weather-skill git add . git commit -m "feat: add weather by coordinates skill" git push origin add/my-weather-skill

The repo has a PR template that asks for:

  • One-liner description
  • Link to CI badge in your repo
  • Why the skill is useful (bullet list)
  • Checklist confirm (metadata, tests, license, docs)

After CI and security review complete, a maintainer merges. GitHub Actions publishes the package to the ClawHub registry, tags the commit, and comments the final registry URL. Within ten minutes it appears in the ClawCloud UI under “Community → New”.

5. Semantic Versioning and Breaking Changes

Once public, you can’t erase 1.0.0. ClawHub keeps every tagged version so agents don’t break. Follow semver religiously:

  • Patch (1.0.1): bug fix, no new inputs/outputs.
  • Minor (1.1.0): new optional input, new output, performance.
  • Major (2.0.0): remove or rename anything, change default behavior.

Update skill.json and git tag:

npm version minor # bumps package.json too git push --follow-tags

OpenClaw’s loader resolves ^1.0.0 ranges, so agents on 1.x won’t see 2.0.0 unless the owner opts in. This saves you angry Telegram DMs.

6. Keeping Up with OpenClaw Core Releases

OpenClaw ships a minor every Thursday (UTC). New APIs stay behind feature flags for one release, then go default. To verify your skill still builds:

  1. Enable Renovate in your repo. The default config opens PRs when openclaw deps bump.
  2. Subscribe to “Skill Breakers” label on the main repo. These issues list deprecations.
  3. Run nightly CI on openclaw@canary. Example GitHub Action:
name: nightly-canary on: schedule: - cron: '0 3 * * *' jobs: test: runs-on: ubuntu-latest strategy: matrix: node: [22] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - run: npm ci - run: npm install openclaw@canary --save-exact - run: npm test

When the canary breaks, you get a failing badge before users file issues.

7. Responding to Issues and PRs From the Community

Published skills sometimes take off. The weather skill sat at 50 installs for weeks, then a WhatsApp automation blogged it and it jumped to 2,300. A few lessons:

  • Label your GitHub issues with triage-needed so you can filter.
  • Use discussions for questions; keep issues for bugs.
  • Automate sanity tests on external PRs. Example pull_request_target workflow that runs npm test without giving write perms.
  • Changelog first: add an unreleased section in CHANGELOG.md. Reviewers look for it.

8. Deprecating or Handing Off a Skill

Life happens. If you can’t maintain the skill:

  1. Mark the repo ARCHIVED in the README header.
  2. Open an issue in openclawhub/skills titled “Looking for Maintainer: my-weather-skill”.
  3. Add "deprecated": true and a note to skill.json. Users get a yellow banner in the UI.
  4. Transfer npm ownership (npm owner add <user> my-weather-skill).

This avoids orphaned installs and keeps the catalog clean.

9. Checklist Before You Hit “Create Pull Request”

  • [ ] All tests pass locally on Node 22
  • [ ] Coverage ≥ 80%
  • [ ] skill.json validates
  • [ ] No hard-coded secrets
  • [ ] README has install + usage + GIF
  • [ ] LICENSE is OSI-approved
  • [ ] Changelog updated
  • [ ] Version bumped

That’s it. Publish, wait for the green checkmarks, answer reviewer comments, and your skill is live. Next time you refresh ClawCloud, search your skill name, click “Install”, and watch users in real-time. Good luck, and see you in the PR queue.