publish
Validate, scan, pack, and publish a skill version — single-dir or bulk.
skillhub publish validates, scans, packs, and publishes a skill version. A
single-dir publish is promptless; passing multiple directories is the bulk path,
which confirms each skill (use --yes to batch). A blocking local scan exits
with code 4 before any network call is made.
The target registry comes from the manifest's publishConfig, or you can
override it with --to <@owner/registry>. Visibility is not set here — there
is no --access flag. A registry's visibility (private or public) is chosen when
the registry is created, via registry create --visibility
or the dashboard.
Publishing a skill you installed
Point skillhub publish at a skill that skillhub installed — its store
directory, or the link to it in an agent directory — and it publishes straight
back to the registry it came from:
skillhub publish .skillhub/skills/tokens-workflowNo --to and no --version. The registry and the version both come from the
lockfile, --bump (default patch) derives the next number, and the result is
recorded in the lockfile so the next publish is the same one-liner. Nothing is
written into your SKILL.md.
Two registries can disagree about where such a skill belongs — the lockfile
records where you installed it from, and its SKILL.md may name its author's
registry. That stops the publish and names both, so you settle it once with
--to; the choice is recorded and not asked again.
On a registry that requires review, the
derived release lands untagged, reported as accepted and held for review.
That withheld tag is the review: latest stays where the reviewers left it, and
an admin moving it onto your version is the approval.
Synopsis
skillhub publish [dir…] [--to <@owner/registry>] [--version <semver>] [--bump <level>] [--tag <tag>] [--type <type>] [--allow-warnings] [--yes] [--force]Flags
| Flag | Description |
|---|---|
--to <@owner/registry> | Target registry (@owner/registry); overrides the manifest's publishConfig |
--version <semver> | Exact version to publish; overrides the manifest's version metadata (cannot be used with a bulk multi-dir publish) |
--bump <level> | Version increment for a skill installed by skillhub: patch (default), minor, or major. Derived from the version the lockfile records, so one level can apply to several skills at once. Alternative to --version |
--tag <tag> | Dist-tag to move on success (default: latest, per server policy) |
--type <type> | Skill type override: project, general, or meta |
--allow-warnings | Acknowledge benign structural warnings (nesting depth, entry count) and publish without prompting |
--yes | Confirm every skill in a bulk multi-dir publish without prompting |
--force | Upload despite blocking scan findings (registry admins only) |
Examples
skillhub publish --to @studio/design-systems
skillhub publish ~/.claude/skills/* --to @studio/design-systems --type general
skillhub publish --tag beta
skillhub publish .skillhub/skills/tokens-workflow
skillhub publish .skillhub/skills/tokens-workflow --bump minorJSON output
With --json, the data object contains:
published[]— each{ ref, version, tag (string|null — null when a review policy withheld it), status: published | held-for-review, scanStatus: pass | warn | fail | pending, warnings[{ code, message, path (string|null) }] }.statusstates what happened rather than leaving it to be inferred from a null tag:held-for-reviewmeans the version landed and awaits an admin's tag move. Thewarnings[]entries are the structural warnings recorded on the version — the benign shape and content-length limits--allow-warningsacknowledges, not scan findings.skipped[]— directories whose per-skill confirmation was declined.outcomes[]— one{ ref, name, status: published | held-for-review | forbidden | failed | skipped, version (string|null), tag (string|null), code (string|null), message (string|null) }per skill published in place from a managed store, the ones that did not land included. Empty for an authoring publish, which fails the whole run on the first error. When any outcome did not go cleanly —forbidden,failed, or a landed version carryingcode: "PUBLISH_UNRECORDED"— the command exits non-zero with aPUBLISH_FAILEDerror whosedetailscarries this same payload.