ClawHub CLI Reference: Commands, Flags, Config, and Lockfile Behavior
Complete reference for the ClawHub CLI, covering commands, global flags, environment variables, HTTP proxy support, and lockfile behavior. Essential for developers and DevOps engineers using ClawHub.
Read this when
- Using the ClawHub CLI
- Debugging install, update, or publish
CLI
The CLI package is clawhub, and its binary is clawhub.
Use npm or pnpm to install it globally:
npm i -g clawhub
# or
pnpm add -g clawhub
After installation, confirm it works:
clawhub --help
clawhub login
clawhub whoami
Global flags
--workdir <dir>: the directory the CLI operates in, defaulting to the current working directory, or the Clawdbot workspace when one is configured--dir <dir>: where packages get installed under the working directory, defaulting toskills--site <url>: the URL used for browser-based login, defaulting tohttps://clawhub.ai--registry <url>: the base address for API calls, auto-detected unlesshttps://clawhub.aiis used as the default--no-input: turns off all interactive prompts
Corresponding environment variables:
CLAWHUB_SITE(older name:CLAWDHUB_SITE)CLAWHUB_REGISTRY(older name:CLAWDHUB_REGISTRY)CLAWHUB_WORKDIR(older name:CLAWDHUB_WORKDIR)
HTTP proxy
For setups behind corporate proxies or restricted networks, the CLI honors the standard HTTP proxy environment variables:
HTTPS_PROXY/https_proxyHTTP_PROXY/http_proxyNO_PROXY/no_proxy
Outbound traffic goes through the designated proxy whenever any of these variables is present. HTTPS requests rely on HTTPS_PROXY, while HTTP_PROXY handles plain HTTP. To exclude particular hosts or domains from proxying, NO_PROXY / no_proxy is respected.
This becomes necessary when direct outbound connections are unavailable, such as inside Docker containers, on Hetzner VPS instances with proxy-only internet, or behind corporate firewalls.
Example:
export HTTPS_PROXY=http://proxy.example.com:3128
export NO_PROXY=localhost,127.0.0.1
clawhub search "my query"
If no proxy variable is configured, the CLI behaves as usual, connecting directly.
Config file
Keeps your API token and the cached registry URL on disk.
- macOS:
~/Library/Application Support/clawhub/config.json - Linux/XDG:
$XDG_CONFIG_HOME/clawhub/config.jsonor~/.config/clawhub/config.json - Windows:
%APPDATA%\\clawhub\\config.json - Legacy fallback: when
clawhub/config.jsonis absent butclawdhub/config.jsonexists, the older path is used instead - override:
CLAWHUB_CONFIG_PATH(older name:CLAWDHUB_CONFIG_PATH)
Commands
login / auth login
- Standard flow: opens the browser at
<site>/cli/authand finishes through a loopback callback. - Headless mode:
clawhub login --token clh_... - Remote or headless interactive:
clawhub login --deviceshows a code, then waits while you approve it at<site>/cli/device.
whoami
- Checks the saved token by calling
/api/v1/whoami.
token
- Outputs the stored API token to stdout.
- Handy for feeding a local login token into CI secret setup commands.
star <skill> / unstar <skill>
- Toggles a skill in your Bookmarks. The commands stay named
starandunstarfor backward compatibility. - Invokes
POST /api/v1/stars/<slug>andDELETE /api/v1/stars/<slug>. - Confirmation is bypassed with
--yes.
search <query...>
- Invokes
/api/v1/search?q=.... - The result includes the skill slug, owner handle, display name, and a relevance score.
- Exact slug or name token matches rank ahead of download popularity. For instance, a standalone slug token like
mapaligns withpersonal-mapmore closely than the substring found withinamap. - Popularity acts as a minor ranking prior, not a promise of top results.
--prefix: returns a deterministic page of matching slugs via/api/v1/skills; keep passing the printed--cursoruntil no cursor remains.--exact: limits relevance search to exact slug matches.--prefixand--exactcannot be used together.--cursorworks only when paired with--prefix.- If a skill is missing from results, run
clawhub inspect @owner/slugwhile authenticated to review owner-visible moderation diagnostics before changing metadata.
explore
- Shows the most recent skills through
/api/v1/skills?limit=...&sort=createdAt, ordered bycreatedAtdescending. - Options:
--limit <n>(1-200, defaults to 25)--sort newest|updated|rating|downloads|trending(defaults to newest). Older install sort aliases remain functional for backward compatibility.--json(output in machine-readable form)
- Output:
<slug> v<version> <age> <summary>(summary capped at 50 characters).
inspect @owner/slug
- Retrieves skill metadata and version files without performing an install.
--version <version>: check a particular version (latest is the default).--tag <tag>: check a version by tag (for example,latest).--versions: show the version history (first page only).--limit <n>: cap the number of versions listed (1-200).--files: display files for the chosen version.--file <path>: obtain raw file bytes, with a 10MB ceiling.--json: machine-readable output;--fileincludes exact bytes as base64 and UTF-8 text when available.
install @owner/slug
- Determines the latest version for the specified owner and skill.
- Pulls the zip via
/api/v1/download. - Unpacks into
<workdir>/<dir>/<slug>. - Will not overwrite pinned skills; execute
clawhub unpin <skill>beforehand. - Creates:
<workdir>/.clawhub/lock.json(previously.clawdhub)<skill>/.clawhub/origin.json(previously.clawdhub)
uninstall <skill>
- Deletes
<workdir>/<dir>/<slug>and clears the lockfile entry. - Sends best-effort telemetry when logged in so current install counts can be deactivated.
- Interactive mode asks for confirmation.
- Non-interactive mode (
--no-input) demands--yes.
list
- Parses
<workdir>/.clawhub/lock.json(formerly.clawdhub). - Displays
pinnedbeside skills frozen withclawhub pin, including the optional reason.
pin <skill>
- Flags an installed skill as pinned within the lockfile.
--reason <text>logs why the skill is frozen.- Pinned skills are ignored by
update --alland blocked by directupdate <skill>. - Pinned skills also reject
install --force, preventing accidental replacement of local bytes.
unpin <skill>
- Strips the lockfile pin from an installed skill, allowing future updates to alter it.
update [@owner/slug] / update --all
- Derives a fingerprint from local files.
- If the fingerprint matches a known version: no prompt appears.
- If the fingerprint does not match:
- refuses by default
- overwrites with
--force(or prompts, when interactive)
- Pinned skills are never touched by
--force. update <skill>fails immediately for pinned skills and directs you to runclawhub unpin <skill>first.update --allbypasses pinned slugs and reports which items stayed frozen.
skill publish <path>
- The local bundle's fingerprint is checked against ClawHub, and the command exits with a success code when the content has already been published.
- For new skills, the default version is
1.0.0; for modified skills, the next patch version becomes the default. - Publishing with an explicit version is handled by
--version <version>, which proceeds even if the content matches an already existing version. - With
--dry-run, the publish is resolved without any upload;--jsonoutputs the result in a machine-readable format. - When the actor holds publisher access,
--owner <handle>publishes using an org or user publisher handle. - While releasing a new version,
--migrate-ownerrelocates an existing skill to--owner. Admin or owner rights are required on both publishers. - Comma-separated values are accepted by
--categories <slugs>and--topics <topics>, which determine the browse filter placement for the skill. If a skill is first published without--categories, it is recorded asother; a subsequent publish that omits the flag preserves the stored value. The valid category slugs, limits, and reserved topic names appear in Skill catalog metadata. - Details on owner and review behavior are covered in
docs/publishing.md. - Releasing a skill on ClawHub means it is published under
MIT-0. - Published skills can be used, modified, and redistributed freely, with no attribution required.
- Paid skills and per-skill pricing are not supported on ClawHub.
publish <path>serves as the legacy alias.
clawhub skill publish ./my-skill --dry-run
clawhub skill publish ./my-skill
clawhub skill publish ./my-skill --version 2.0.0
GitHub Actions
For a single skill_path, or for each immediate skill folder under root (default: skills), the reusable skill-publish.yml workflow on ClawHub invokes skill publish. Unchanged skills are skipped, and the same automatic patch-version behavior applies.
To preview without a token, set dry_run: true. The clawhub_token secret is mandatory for actual publishes.
The optional changelog, categories, and topics inputs correspond to the matching skill publish flags, while clear_categories and clear_topics strip metadata that a skill already has. When a skill is first published without categories, it is stored as other, identical to sync. Since catalog metadata applies to every skill in the run and disables the unchanged-skill skip mentioned earlier, review the notes under GitHub Actions before enabling it across the catalog.
sync
- Local skill folders containing
SKILL.mdorskill.mdare found by scanning the current workdir, the configured skills directory, and any--root <dir>folders. - Each local skill fingerprint is compared against ClawHub, and only new or modified skills are published.
- New skills are published as
1.0.0; modified skills default to the next patch version. For update batches needing a larger semver step, use--bump minor|major. - The publish plan is displayed by
--dry-runwithout uploading;--jsonprovides a machine-readable version of the plan. - Without prompting,
--allpublishes every new or modified skill. If--allis absent, interactive terminals allow you to choose which skills to publish. - With publisher access,
--owner <handle>publishes under an org or user publisher handle. syncis strictly one-way publishing. It performs no installation, updates, downloads, or install/download telemetry reporting.- Neither
--categoriesnor--topicsexists insync. Skills first published throughsyncare recorded asotheruntil skill catalog metadata is set on them.
clawhub sync --all --dry-run
clawhub sync --all
clawhub sync --root ./skills --owner openclaw --bump minor
scan --slug <slug>
clawhub loginis a prerequisite.- ClawHub ClawScan gets invoked through
POST /api/v1/skills/-/scan, with polling continuing until the scan reaches a terminal state. - Because scans run asynchronously, completion can take a while. While a scan sits in the queue, the terminal spinner indicates its current priority position along with the count of scans ahead of it.
- To publish a scan, you need ownership or publisher management privileges. Moderators and admins reach the same backend functionality via
clawhub-admin. --updateonly works in combination with--slug; it sends successful published scan results back to the chosen version.- Using
--output <file.zip>pulls the complete report archive, which includesmanifest.json,clawscan.json,skillspector.json,static-analysis.json,virustotal.json, andREADME.md. --jsonoutputs the entire poll response, which is handy for automation.- Local path scanning has been removed. Instead, upload a fresh version and then call
scan downloadto fetch the stored scan results tied to that submitted version.
clawhub scan --slug gifgrep
clawhub scan --slug gifgrep --version 1.2.3
clawhub scan --slug gifgrep --update --output report.zip
scan download <name>
clawhub loginis required.- Fetches the stored scan report ZIP for a submitted skill or plugin version, even if ClawHub security checks blocked or hid that version.
- For skills, the download uses the skill slug and falls back to
--kind skill. - For plugins, the package name drives the download, and
--kind pluginis mandatory. - Authors must supply
--versionso they can inspect the exact submitted version that ClawHub rejected. --output <file.zip>determines where the file gets saved.
clawhub scan download gifgrep --version 1.2.3
clawhub scan download @scope/demo --version 2.0.0 --kind plugin --output report.zip
GitHub Actions
ClawHub provides an official reusable workflow at
/.github/workflows/skill-publish.yml
that works for both skill repos and catalog repos.
A typical catalog setup looks like this:
name: Skill Publish
on:
pull_request:
workflow_dispatch:
jobs:
dry-run:
if: github.event_name == 'pull_request'
uses: openclaw/clawhub/.github/workflows/skill-publish.yml@v1
with:
owner: nvidia
dry_run: true
publish:
if: github.event_name == 'workflow_dispatch'
uses: openclaw/clawhub/.github/workflows/skill-publish.yml@v1
with:
owner: nvidia
dry_run: false
changelog: "Describe the changes in this release."
categories: "automation"
topics: "code-review,linting"
secrets:
clawhub_token: ${{ secrets.CLAWHUB_TOKEN }}
Additional details:
rootusesskillsas its default for catalog repos.- To handle just one skill folder, pass
skill_path: skills/review-helper. - The CLI flag
--ownercorresponds toowner; leave it out and publishing happens under the authenticated user's identity. - The optional
changelog,categories, andtopicseach map to their respectiveskill publishflags. When you omit them, the metadata already published stays untouched. - Just like
tags, all three of these affect every skill in the run. If the values describe a single skill rather than the whole catalog, passskill_pathinstead. - Both
categoriesandtopicsturn off the "skip unchanged skills" logic described earlier. The CLI treats any catalog metadata you supply as authoritative and skips its already-published short-circuit, meaning a catalog-wide run publishes a new patch version for each selected skill, even those with no file changes. Theclear_categoriesandclear_topicsflags count as supplied metadata and behave the same way.changelogdoes not: a run that only passeschangelogstill reports unchanged skills asalreadySynced. To stop a metadata edit from releasing an entire catalog, useskill_path. changelogreaches the CLI exactly as written, the same wayskill publish --changelogstores it, so Markdown indentation and trailing hard-break spaces survive the workflow; a value made up only of whitespace is treated as omitted. Being slug lists,categoriesandtopicsget trimmed instead.- Categories and topics arrive comma-separated and get validated on the server, so an unknown category slug or a topic exceeding the per-skill cap fails the publish after the run has already built and validated the skill.
- To strip categories or topics already attached to a skill, set
clear_categories: trueorclear_topics: true. A workflow input cannot tellcategories: ""apart from an omittedcategories, so the empty string keeps its "leave them alone" meaning and the boolean is what sends the CLI's--categories "". Supplying a non-empty value together with itsclear_flag fails the run rather than silently choosing one.changeloghas no such flag: the CLI already treats an omitted--changelogas empty. - The run logs echo the resolved
skill publishcommand for each target, so any forwarded flag shows up in CI output. Keep the values non-sensitive. - V1 skill publishing relies on
clawhub_token; GitHub OIDC trusted publishing is package-only at this time.
delete <skill>
- To soft-delete a skill, use
--versionwithout it. Owners, moderators, and admins are the only roles permitted. - This invokes
DELETE /api/v1/skills/{slug}. - When an owner starts a soft delete, the slug stays reserved for 30 days, and the command displays when that reservation ends.
- With
--version <version>, you can withdraw a single owned version that isn't the latest, through a route that fails closed and targets that version specifically. That version number stays reserved, so republishing it with altered content isn't possible. Before removing the current latest version, publish a replacement first. For this version-only operation, platform staff don't bypass ownership rules. --reason <text>logs a moderation note and an audit entry when a whole-skill soft delete happens.--note <text>serves as an alias for--reason.- Confirmation is bypassed with
--yes. - The older
POST /api/cli/skill/deleteendpoint, when given aversion, rejects it rather than treating it as a delete for the whole skill.
undelete <skill>
- To restore a hidden skill, use this. Owners, moderators, and admins are the allowed roles.
- It calls
POST /api/v1/skills/{slug}/undelete. --version <version>brings back only the exact retained artifact that the same owner actor previously withdrew. The restored version isn't set as latest, and removed tags aren't recreated.- Version restoration triggers
POST /api/v1/skills/{slug}/versions/{version}/restore. - A moderation note and audit log entry are recorded via
--reason <text>. --note <text>is an alias for--reason.- Confirmation is skipped with
--yes.
skill tag <skill> <version>
- This moves a tag on an owned skill to an existing public version, with
latestas the default choice. - It calls
POST /api/v1/skills/{slug}/tags/{tag}. - For org publishers, owner or admin membership is required, matching the rules for version withdrawal.
- Use this to roll
latestback if you accidentally published a higher version; publishing a lower version by itself doesn't replace the latest version by highest semver. - Another tag can be selected with
--tag <tag>. - Confirmation is skipped via
--yes.
Example:
clawhub skill tag @owner/example 1.2.3 --yes
hide <skill>
- Hide a skill. Owners, moderators, and admins can do this.
- This is an alias for
delete.
unhide <skill>
- Unhide a skill. Owners, moderators, and admins can do this.
- This is an alias for
undelete.
skill rename <skill> <new-name>
- Rename a skill you own, and the previous slug becomes a redirect alias.
- It calls
POST /api/v1/skills/{slug}/rename. - Confirmation is skipped with
--yes.
skill merge <source> <target>
- Merge one skill you own into another skill you own.
- The source slug no longer appears in public listings and becomes a redirect alias pointing to the target.
- It calls
POST /api/v1/skills/{sourceSlug}/merge. - Confirmation is skipped via
--yes.
transfer
- Workflow for transferring ownership.
- When transferring to a user handle, a pending request is created, and the recipient must accept it.
- Transfers to org or publisher handles apply right away only if the actor has admin access to both the current owner and the destination publisher.
- Subcommands:
transfer request <skill> <handle> [--message "..."] [--yes]transfer list [--outgoing]transfer accept <skill> [--yes]transfer reject <skill> [--yes]transfer cancel <skill> [--yes]
- Endpoints:
POST /api/v1/skills/{slug}/transferPOST /api/v1/skills/{slug}/transfer/acceptPOST /api/v1/skills/{slug}/transfer/rejectPOST /api/v1/skills/{slug}/transfer/cancelGET /api/v1/transfers/incomingGET /api/v1/transfers/outgoing
package explore [query...]
- Lets you browse or search the combined package index with
GET /api/v1/packagesandGET /api/v1/packages/search. - Intended for plugins and other package-family items;
searchat the top level still handles skill searches. - Available flags:
--family skill|code-plugin|bundle-plugin--official--executes-code--target <target>,--os <os>,--arch <arch>,--libc <libc>--requires-browser,--requires-desktop,--requires-native-deps--requires-external-service,--external-service <name>--binary <name>,--os-permission <name>--artifact-kind legacy-zip|npm-pack--npm-mirror--limit <n>(1-100, default: 25)--json
Sample usage:
clawhub package explore --family code-plugin
clawhub package explore --family code-plugin --os darwin --requires-desktop
clawhub package explore --family code-plugin --artifact-kind npm-pack
clawhub package explore --npm-mirror
clawhub package explore episodic-claw --family code-plugin
package inspect <name>
- Pulls package metadata without performing an installation.
- Suitable for plugin metadata, compatibility checks, verification, source inspection, and version/file review.
--version <version>: examine a particular version (default: latest).--tag <tag>: examine a version by tag (for instance,latest).--versions: show the first page of the version list.--limit <n>: maximum number of versions displayed (1-100).--files: show files for the version you selected.--file <path>: retrieve a limited UTF-8 text preview (capped at 200KB).--json: output in a machine-readable format.
package download <name>
- Determines a package version via
GET /api/v1/packages/{name}/versions/{version}/artifact. - Pulls the artifact from the resolver's
downloadUrl. - Confirms the ClawHub SHA-256 for every artifact.
- For ClawPack npm-pack artifacts, additionally confirms npm
sha512integrity, the npm shasum, and the tarball'spackage.jsonname/version. - Legacy ZIP versions follow the legacy ZIP download path.
- Flags:
--version <version>: download a chosen version.--tag <tag>: download a version by tag (default:latest).-o, --output <path>: destination file or directory.--force: replace an existing output file.--json: output in a machine-readable format.
Sample usage:
clawhub package download @openclaw/example-plugin --tag latest
clawhub package download @openclaw/example-plugin --version 1.2.3 -o artifacts/
package verify <file>
- Calculates ClawHub SHA-256, npm
sha512integrity, and npm shasum for a local artifact. - With
--package, pulls expected metadata from ClawHub and checks the local file against the published artifact metadata. - Using direct digest flags, verification happens without a network call.
- Flags:
--package <name>: package name for resolving expected artifact metadata.--version <version>or--tag <tag>: expected package version.--sha256 <hex>: expected ClawHub SHA-256.--npm-integrity <sri>: expected npm integrity.--npm-shasum <sha1>: expected npm shasum.--json: output in a machine-readable format.
Sample usage:
clawhub package verify ./example-plugin-1.2.3.tgz --package @openclaw/example-plugin --version 1.2.3
clawhub package verify ./example-plugin-1.2.3.tgz --sha256 <hex>
package validate <source>
- Executes the Plugin Inspector bundled with the ClawHub CLI on a local plugin package directory.
- By default, validation is offline and static, with no attempt to locate or import a local OpenClaw checkout.
- Hard compatibility errors cause a non-zero exit. Warning-level findings are printed, yet the exit code remains zero.
- Flags:
--out <dir>: output Plugin Inspector reports to the specified directory.--openclaw <path>: validate against a designated local OpenClaw checkout.--runtime: turn on runtime capture, which imports plugin code.--allow-execute: permit runtime capture within an isolated workspace.--no-mock-sdk: turn off the mocked OpenClaw SDK during runtime capture.--json: produce output in a machine-readable format.
Example:
clawhub package validate ./example-plugin
Should validation surface any package, manifest, SDK import, or artifact issue, consult Plugin validation fixes and then run the command again.
package delete <name>
- In the absence of
--version, a package along with all its releases is soft-deleted. - With
--version <version>, a single non-latest release that you own is withdrawn through a fail-closed, version-specific path. That version stays reserved and cannot be republished with altered contents. Before deleting the current latest version, publish a replacement. This version-only operation demands the package owner or an org publisher admin; platform staff do not override package ownership. - Soft-deleting an entire package requires the package owner, an org publisher owner/admin, platform moderator, or platform admin.
- Flags:
--version <version>: withdraw one non-latest version.--yes: bypass the confirmation prompt.--json: machine-readable output.
Example:
clawhub package delete @openclaw/example-plugin --yes
clawhub package delete @openclaw/example-plugin --version 1.2.3 --yes
package undelete <name>
- Brings back a soft-deleted package and its releases.
- Requires the package owner, an org publisher owner/admin, platform moderator, or platform admin.
- Invokes
POST /api/v1/packages/{name}/undelete. --version <version>restores only the specific retained release that the same owner actor previously withdrew. It neither marks the release as latest nor recreates removed package tags or dist-tags.- Restoring a version calls
POST /api/v1/packages/{name}/versions/{version}/restore. - Flags:
--version <version>: restore a single owner-withdrawn release.--yes: skip the confirmation prompt.--json: machine-readable output.
Example:
clawhub package undelete @openclaw/example-plugin --yes
package transfer <name>
- Moves a package to a different publisher.
- Requires admin access to both the current package owner and the destination publisher, unless a platform admin performs the transfer.
- Scoped package names must move to the owner of the matching scope.
- Calls
POST /api/v1/packages/{name}/transfer. - Flags:
--to <owner>: handle of the destination publisher.--reason <text>: optional audit reason.--json: machine-readable output.
Example:
clawhub package transfer @openclaw/example-plugin --to openclaw
package report
- Authenticated command used to flag a package for moderator review.
- Calls
POST /api/v1/packages/{name}/report. - Reports apply at the package level, can optionally reference a version, and are visible to moderators for assessment.
- Reports alone do not hide packages or prevent downloads.
- Flags:
--version <version>: optional package version to include with the report.--reason <text>: required reason for the report.--json: machine-readable output.
Example:
clawhub package report @openclaw/example-plugin --version 1.2.3 --reason "suspicious native payload"
package moderation-status
- Owner command that checks a package's moderation visibility.
- Calls
GET /api/v1/packages/{name}/moderation. - Displays the current package scan state, count of open reports, manual moderation state of the latest release, download block state, and moderation reasons.
- Flags:
--json: machine-readable output.
Example:
clawhub package moderation-status @openclaw/example-plugin
package readiness <name>
- Verifies whether a package is prepared for future OpenClaw use.
- Calls
GET /api/v1/packages/{name}/readiness. - Reports blockers related to official status, ClawPack availability, artifact digest, source provenance, OpenClaw compatibility, host targets, environment metadata, and scan state.
- Flags:
--json: machine-readable output.
Example:
clawhub package readiness @openclaw/example-plugin
package migration-status <name>
- Shows operator-focused migration status for a package that could replace a bundled OpenClaw plugin.
- Uses the same computed readiness endpoint as
package readiness, but outputs migration-specific status, latest version, official-package state, checks, and blockers. - Flags:
--json: machine-readable output.
Example:
clawhub package migration-status @openclaw/example-plugin
publisher create <handle>
- Establishes an org publisher owned by the authenticated user.
- The handle is lowercased and can be supplied with or without
@. - Fresh org publishers are not trusted or official by default.
- The operation fails if the handle already belongs to an existing publisher, user, or reserved route.
clawhub publisher create opik --display-name "Opik"
package publish <source>
- Sends a code plugin or bundle plugin to the registry with
POST /api/v1/packages. - The following inputs are accepted by
<source>:- A directory on disk:
./my-plugin - A ClawPack tarball produced by npm-pack locally:
./my-plugin-1.2.3.tgz - A GitHub repository:
owner/repoorowner/repo@ref - A GitHub web address:
https://github.com/owner/repo
- A directory on disk:
- Metadata gets pulled automatically from
package.json,openclaw.plugin.json, and genuine OpenClaw bundle indicators like.codex-plugin/plugin.json,.claude-plugin/plugin.json, and.cursor-plugin/plugin.json. - Any source coming from
.tgzis handled as ClawPack. The exact npm-pack byte stream is what the CLI uploads, and the extractedpackage/data serves only to validate and prefill metadata. - Publishing an experimental Claw requires an already-compiled
.tgz. Sources from Claw folders or GitHub are not allowed; runopenclaw claws buildbeforehand. The request records the local SHA-256, and after the precise bytes are accepted, ClawHub responds with that digest. - Before upload, code-plugin directories get converted into a ClawPack npm tarball so OpenClaw installs can confirm the exact artifact. Bundle-plugin directories continue down the extracted-file publish route instead.
- When the source is GitHub, attribution comes from the repository, the resolved commit, the ref, and the subpath automatically.
- For local directories, attribution is inferred from local git when the origin remote points to GitHub.
- Code plugins from outside must spell out
openclaw.compat.pluginApiandopenclaw.build.openclawVersion. The top-levelpackage.json.versionis never consulted as a fallback during publish validation. - With
--dry-run, you can see the resolved publish payload ahead of time without sending anything. --jsonproduces output that machines can parse, meant for CI pipelines.--waitblocks until pre-publication security scans finish, and only returns once the release is out or a terminal error state is hit.- The
--waittimeout is set by--wait-timeout <seconds>, which defaults to 1800. --owner <handle>releases under a user or org publisher handle provided the actor holds publisher rights.--categories <slugs>and--topics <topics>follow the same behavior as they do forskill publish, except code-plugin and bundle-plugin categories are checked against the plugin list rather than the skill one:channels,models,memory,context,voice,media,web,tools,runtime,gateway,security,other. Experimental--family clawpublishes bypass that category check and keep the provided slugs unchanged. The topic constraints in Skill catalog metadata, limits, reserved names, republish behavior, hold across every family,clawincluded.- The selected owner must match the scoped package name. Refer to
docs/publishing.md. - Overrides from existing flags (
--family,--name,--version,--source-repo,--source-commit,--source-ref,--source-path) remain functional. - Accessing private GitHub repositories needs
GITHUB_TOKEN.
clawhub package publish ./plugin.tgz --owner openclaw
Recommended local flow
Start with --dry-run so you can verify the resolved package metadata and
source attribution before going live with an actual release:
npm pack
clawhub package publish ./my-plugin-1.2.3.tgz --family code-plugin --dry-run
clawhub package publish ./my-plugin-1.2.3.tgz --family code-plugin --wait
Local folder flow
When publishing code plugins, folder publish compiles and sends a ClawPack artifact built from the package directory. This shortcut does not extend to Claws:
clawhub package publish ./my-plugin --family code-plugin --dry-run
clawhub package publish ./my-plugin --family code-plugin
Minimal package.json for --family code-plugin
External code plugins require a small set of OpenClaw metadata in
package.json. This minimal manifest suffices for a valid publish:
{
"name": "@myorg/openclaw-my-plugin",
"version": "1.0.0",
"type": "module",
"openclaw": {
"extensions": ["./index.ts"],
"compat": {
"pluginApi": ">=2026.3.24-beta.2"
},
"build": {
"openclawVersion": "2026.3.24-beta.2"
}
}
}
Mandatory fields:
openclaw.compat.pluginApiopenclaw.build.openclawVersion
Remarks:
package.json.versionindicates your package release version, yet it is not employed as a fallback for OpenClaw compatibility or build validation.openclaw.hostTargetsandopenclaw.environmentare optional metadata. ClawHub may display them if available, but they are not necessary for publishing.openclaw.compat.minGatewayVersionandopenclaw.build.pluginSdkVersionare optional additions for those wanting to include richer compatibility details.- When using an older
clawhubCLI version, update it prior to publishing so the local preflight checks execute before the upload. - Should validation return a remediation code, refer to Plugin validation fixes.
GitHub Actions
ClawHub also provides an official reusable workflow at
/.github/workflows/package-publish.yml
for plugin repositories.
Typical caller configuration:
name: Package Publish
on:
pull_request:
workflow_dispatch:
push:
tags:
- "v*"
jobs:
dry-run:
if: github.event_name == 'pull_request'
uses: openclaw/clawhub/.github/workflows/package-publish.yml@v0.12.0
with:
dry_run: true
publish:
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/')
permissions:
contents: read
id-token: write
uses: openclaw/clawhub/.github/workflows/package-publish.yml@v0.12.0
with:
dry_run: false
secrets:
clawhub_token: ${{ secrets.CLAWHUB_TOKEN }}
To include release and catalog metadata, add the matching CLI values to the
job's current with block. Keep dry_run: true for pull-request jobs; use
dry_run: false only on the trusted publish job shown above.
with:
changelog: "Describe the changes in this release."
categories: "tools"
topics: "automation,productivity"
Remarks:
- The reusable workflow sets
sourceto the caller repository by default. - For monorepos, pass
source_pathso the workflow publishes the plugin package directory, such assource_path: extensions/codex. changelog,categories, andtopicsare optional. When supplied, the workflow passes them to the corresponding package publish CLI flags. Categories and topics accept comma-separated values; leaving them out preserves the existing workflow behavior.- To clear previously declared metadata, set
clear_categories: trueorclear_topics: true. A clear input cannot be used together with its matching value input. - Anchor the reusable workflow to a stable tag or full commit SHA. Do not run release publishing from
@main. pull_requestshould rely ondry_run: trueto keep CI non-polluting.- Actual publishes should be restricted to trusted events like
workflow_dispatchor tag pushes. - Trusted publishing without a secret functions only on
workflow_dispatch; tag pushes still demandclawhub_token. - Keep
clawhub_tokenavailable for the first publish, untrusted packages, or break-glass scenarios. - Real publishes wait for definitive publication by default. Set
wait_for_publication: falseonly when a caller intentionally wants the legacy submit-and-return mode. publication_timeout_minutesmanages the publication wait timeout and defaults to 30 minutes (maximum: 40).- The workflow uploads the JSON result as an artifact and reveals it as workflow outputs.
package trusted-publisher get <name>
- Displays the GitHub Actions trusted publisher configuration for a package.
- Run this after setting config to verify the repository, workflow filename, and any environment pin.
- Flags:
--json: machine-readable output.
Example:
clawhub package trusted-publisher get @openclaw/example-plugin
package trusted-publisher set <name>
- Adds or replaces GitHub Actions trusted publisher config for an existing package.
- The package must be created beforehand through normal manual or token-authenticated
clawhub package publish. - Once config is set, future supported GitHub Actions publishes can use OIDC/trusted publishing without a long-lived ClawHub token.
--repository <repo>must beowner/repo.--workflow-filename <file>must align with the workflow file name in.github/workflows/.--environment <name>is optional. When set, the GitHub Actions environment in the OIDC claim must match exactly.- ClawHub checks the configured GitHub repository when this command runs. Public repositories can be verified via public GitHub metadata. Private repositories require ClawHub to have GitHub access to that repository, for example through a future ClawHub GitHub App installation or another authorized GitHub integration.
- Flags:
--repository <repo>: GitHub repository, such asopenclaw/example-plugin.--workflow-filename <file>: workflow file name, such aspackage-publish.yml.--environment <name>: optional exact-match GitHub Actions environment.--json: machine-readable output.
Example:
clawhub package trusted-publisher set @openclaw/example-plugin \
--repository openclaw/example-plugin \
--workflow-filename package-publish.yml \
--environment release
package trusted-publisher delete <name>
- Deletes trusted publisher config from a package.
- Use this as rollback when the workflow, repository, or environment pin needs to be disabled or re-created.
- Future real publishes must use normal authenticated publishing until config is set again.
- Flags:
--json: machine-readable output.
Example:
clawhub package trusted-publisher delete @openclaw/example-plugin
Install telemetry
- Transmitted after
clawhub install <slug>when logged in, unlessCLAWHUB_DISABLE_TELEMETRY=1is set. - Reporting is best-effort. Install commands do not fail if telemetry is unavailable.
- Details:
docs/telemetry.md.