SkillHub

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-workflow

No --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

FlagDescription
--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-warningsAcknowledge benign structural warnings (nesting depth, entry count) and publish without prompting
--yesConfirm every skill in a bulk multi-dir publish without prompting
--forceUpload 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 minor

JSON 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) }] }. status states what happened rather than leaving it to be inferred from a null tag: held-for-review means the version landed and awaits an admin's tag move. The warnings[] entries are the structural warnings recorded on the version — the benign shape and content-length limits --allow-warnings acknowledges, 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 carrying code: "PUBLISH_UNRECORDED" — the command exits non-zero with a PUBLISH_FAILED error whose details carries this same payload.

On this page