Batch-sync locally developed Skills to three public platforms:
- ClawHub — International general-purpose Skills community, enforces MIT-0 license
- Tencent SkillHub — Skills community optimized for Chinese users, no license restrictions
- Lenovo Open Platform — For the Lenovo AI agent ecosystem, uses
@lenovo-open/skill-cli(Node.js); no mandatory license
Supports reading .gitignore to smartly ignore sensitive files and temporary files. The three platforms each maintain an independent allowlist file (allowlist-clawhub.yaml / allowlist-skillhub.yaml / allowlist-lenovo.yaml); the same skill can have its fields maintained independently across multiple files (one-to-many, no forced non-duplicate distribution).
Dependencies
System dependencies
| Dependency | Purpose | Installation method |
|---|---|---|
rsync |
prepare-publish.sh Copy filtered files to the temporary publish directory |
Bundled with macOS; Linux: sudo apt-get install rsync |
git |
prepare-publish.sh Use git ls-files to precisely match tracked files |
Bundled with macOS; Linux: sudo apt-get install git |
| Python 3 | Run the Tencent SkillHub CLI (Python script) | Bundled with macOS; Linux: sudo apt-get install python3 |
Node.js(≥ 18)+ npm |
Run Lenovo lenovoskill CLI(npx @lenovo-open/skill-cli runs on the Node.js runtime) |
Bundled with macOS or brew install node;Linux: sudo apt-get install -y nodejs npm |
CLI tools (install on demand per target platform)
| CLI | Purpose | Installation command | Required scenario |
|---|---|---|---|
clawhub |
Publish to ClawHub | See ClawHub official documentation | Only when publishing to ClawHub |
skillhub |
Publish to Tencent SkillHub | Official CLI,skillhub self-upgrade upgrade (must be ≥ 2026.7.29) |
Only when publishing to SkillHub |
lenovoskill(npx @lenovo-open/skill-cli) |
Upload to Lenovo Open Platform | npx @lenovo-open/skill-cli <cmd>(no install required, recommended) or npm i -g @lenovo-open/skill-cli |
Only when uploading to Lenovo Platform |
⚠️ Version requirement (important)
Tencent
skillhubCLI must be ≥ 2026.7.29 to supportpublish/login. Earlier versions (such as 2026.3.18) only havesearch/install, and cannot publish. Runskillhub self-upgradeto upgrade to the latest version; if unsure, first useskillhub self-upgrade --check-onlyto check whether a new version is available.
First-time installation checklist (SkillHub publishing)
# 1. 安装 CLI(macOS/Linux)
curl -fsSL https://skillhub-1388575217.cos.ap-guangzhou.myqcloud.com/install/install.sh | bash
# 2. 升级到支持发布的版本(≥ 2026.7.29)
skillhub self-upgrade
# 3. 验证(应含 publish/login 命令)
skillhub --help
# 4. 登录(token 从 https://skillhub.cn 个人设置获取,skh_ 前缀)
skillhub login --key skh_xxx
# 5. 确认身份
skillhub auth whoami
ClawHub enforces the MIT-0 license(no attribution required, commercial use allowed). Tencent SkillHub has no license restrictions, so CC-BY-NC / MIT / Apache etc. can all be published.
ClawHub license key terms(from the official Skill Format documentation, verified as of 2026-08):
- "All skills published on ClawHub are licensed under
MIT-0." —— All publishing is equivalent to MIT-0.- "Anyone may use, modify, and redistribute published skills, including commercially." —— Anyone may use them commercially.
- "Attribution is not required." —— No attribution required.
- "ClawHub does not support per-skill license overrides." —— Per-skill license overrides are not supported(frontmatter writes
license: CC-BY-NCplatform-level does not take effect).- "Do not add conflicting license terms in
SKILL.md." —— Do not add conflicting license terms in SKILL.md。Therefore (v1.7.1 three independent list architecture):
- Each platform independently maintains its own allowlist file: one each for ClawHub / SkillHub / Lenovo
- MIT-licensed general-purpose tool skill → by default publish only to ClawHub (
allowlist-clawhub.yaml)- Legal skills under restrictive licenses such as CC-BY-NC → by default publish only to SkillHub (
allowlist-skillhub.yaml, ClawHub MIT-0 conflicts are not accepted)- Skills that want to be distributed additionally to the Lenovo ecosystem beyond ClawHub / SkillHub → register in
allowlist-lenovo.yaml(no license restrictions, can be registered in duplicate with SkillHub / ClawHub, i.e. the same skill appearing across multiple files is completely allowed)- If the ClawHub slug is taken and cannot be published → move from
allowlist-clawhub.yamltoallowlist-skillhub.yamlorallowlist-lenovo.yamli.e.three independent allowlist files, each independently maintains the skill list and fields for its own platform; the same skill can appear in multiple files at the same time (one-to-many), with no need to change the configuration of old skills for a new platform. See DECISIONS
D-2026-08-12-02。For ClawHub licenses see ClawHub Skill Format official documentation
Platform comparison
| Dimension | ClawHub | Tencent SkillHub | Lenovo Open Platform |
|---|---|---|---|
| CLI tool | clawhub |
skillhub(official CLI,skillhub self-upgrade upgrade;must be ≥ 2026.7.29 to support publish/login) |
lenovoskill(npx @lenovo-open/skill-cli, Node.js runtime) |
| Login command | clawhub login |
skillhub login --key skh_xxx |
lenovoskill login(OAuth browser authorization) |
| Publish command | clawhub publish <path> --slug --name --version --changelog |
skillhub publish <path> [--version] [--changelog] [--dry-run] |
lenovoskill package && lenovoskill push(two steps: first create the zip then upload) |
| skill identifier | --slug + --name(passed in via the command line) |
slug + displayName(prepare-publish.sh injects a temporary copy from allowlist-skillhub.yaml ; the source SKILL.md does not contain it) |
slug + displayName(prepare-publish.sh injects a temporary copy from allowlist-lenovo.yaml ; the source SKILL.md does not contain it) + in-project .skill-config.json |
| Credential location | clawhub CLI default | local skillhub configuration | ~/.lenovoskill/auth.json(600, OAuth dual token: Login Token + Biz Token) + ~/.lenovoskill/config.json(default API) |
| Visibility | None | — (no such concept) | — (no such concept) |
| namespace | None | Yes(bound to the account, not passed in the publish command, recorded for traceability) | None(OAuth dual token, no namespace concept) |
| License | Mandatory MIT-0 | Unrestricted | Unrestricted |
| Default registry/API | Built-in | https://api.skillhub.cn |
https://open.lenovomm.com |
| Official tutorial | — | https://skillhub.cn/tutorials#publish-via-cli | https://open.lenovomm.com |
Prerequisites
Required SKILL.md frontmatter fields
---
name: skill-name
description: 技能描述
version: "1.0.0" # 推荐但不强制
homepage: https://github.com/cat-xierluo/legal-skills # 自动设置
---
slug / displayName are not written into SKILL.md. The fields required by SkillHub are read from
config/allowlist-skillhub.yaml; the fields required by Lenovo Open Platform are read fromconfig/allowlist-lenovo.yaml.Each platform has an independent allowlist, and fields are maintained independently(The same skill can appear in multiple files at once, one-to-many). Before publishing,prepare-publish.sh(--platform skillhubor--platform lenovo) automatically injects a temporary copy of the frontmatter. The source SKILL.md retains only the standard skill fields, decoupling platform metadata from the skill itself. ClawHub does not rely on frontmatter (it uses--slug/--namecommand-line arguments).
CLI Installation
For the complete installation method and version requirements of the CLI tool, see the "Dependencies" section at the beginning of this document.
Quickly verify installation:
clawhub --version # ClawHub
skillhub --help # SkillHub(确认含 publish/login 命令即为发布版)
Usage
1. Log in to the platform (first-time use)
ClawHub:
clawhub login
Tencent SkillHub(uses an API Token, format skh_xxx, obtained from SkillHub personal settings):
# token 从 https://skillhub.cn 个人设置获取(skh_ 前缀)
skillhub login --key skh_xxx
# 如需临时使用其他 token 覆盖登录态(不写入本地)
skillhub login --key skh_yyy
After logging in, the token is stored locally, and subsequent publish commands do not need to pass the token again. You can also temporarily override it with
skillhub publishwhen--token skh_xxx.
2. Verify login status
# ClawHub
clawhub whoami
# 腾讯 SkillHub
skillhub auth whoami
3. Sync skills
ClawHub
Sync a single skill:
clawhub sync skills/<skill-name>
Sync all skills:
clawhub sync --all
Note:
--allis subject toskills/skill-publish-sync/config/allowlist-clawhub.yaml. Only skills listed in that file will be synced to ClawHub. The same applies to SkillHub / Lenovo (each has its own independent whitelist file).
Tencent SkillHub
SkillHub recommends publishing skills one by one (specify the directory via the publish command; the identifier comes from the SKILL.md frontmatter, see "Single Skill Sync Workflow" below).
# 发布目录(自动打包)
skillhub publish ./my-skill
# 指定版本和 changelog
skillhub publish ./my-skill --version 1.2.0 --changelog "新增xxx"
# 先预检(只校验 + 打包,不实际发请求)
skillhub publish ./my-skill --dry-run
SkillHub uses
slug+displayName(before publishing, prepare-publish.sh injects it into a temporary copy fromconfig/allowlist-skillhub.yaml; the source SKILL.md does not contain it) to identify the skill. The namespace is bound to the account (no need to specify it on the command line when publishing). There is no concept of visibility.
Interactive selection sync: The user can specify the list of skills to sync and the target platform, and I will execute the sync commands one by one.
Single Skill Sync Workflow
Use this workflow when you need to sync specified skills (rather than all of them). The process is common to both platforms; only the commands differ in the "Execute Publish" step.
Pre-checks
-
Check login status
clawhub whoami # ClawHub skillhub auth whoami # 腾讯 SkillHub -
Check whitelist
- Read
skills/skill-publish-sync/config/allowlist-${PLATFORM}.yaml(platform-specific whitelist) - Confirm that the target skill appears in the allowlist file for the corresponding platform (each platform has an independent file, with no
platformsfield) - Independent file paths for the three platforms:
- ClawHub →
allowlist-clawhub.yaml - SkillHub →
allowlist-skillhub.yaml - Lenovo →
allowlist-lenovo.yaml
- ClawHub →
- Read
-
Check license(required only for ClawHub)
- Read the
licensefield in the target skill's SKILL.md frontmatter - ClawHub: only skills with the MIT license can be synced
- SkillHub / Lenovo: no license restrictions, all can be synced
- Read the
Version detection
Compare two version numbers (read the record according to the target platform):
| Source | Location | Format |
|---|---|---|
| New version | skills/<skill-name>/SKILL.md frontmatter's version |
"1.2.0" |
| Recorded version | skills/skill-publish-sync/config/sync-records.yaml in records.<skill>.platforms.<platform>.version |
"1.1.0" |
Version comparison logic(semantic versioning):
new_version > recorded_version → 需要同步
new_version == recorded_version → 跳过(无变化)
new_version < recorded_version → 警告(版本回退?)
recorded_version 为 null → 需要同步(首次发布)
Execute sync
Step 1: Prepare the publish directory
# ClawHub(默认平台,可省略 --platform)
bash skills/skill-publish-sync/scripts/prepare-publish.sh skills/<skill-name>
# 腾讯 SkillHub
bash skills/skill-publish-sync/scripts/prepare-publish.sh --platform skillhub skills/<skill-name>
The script will create a temporary directory:
- ClawHub:
/tmp/clawhub-publish-<skill-name> - SkillHub:
/tmp/skillhub-publish-<skill-name>
Step 2: Execute publishing
ClawHub(Use clawhub publish, explicitly specify slug and name):
clawhub publish /tmp/clawhub-publish-<skill-name> \
--slug <skill-name> \
--name "<Display Name>" \
--version "<新版本号>" \
--changelog "<变更说明>"
⚠️ You must specify --slug and --name
- Temporary directory names may contain a prefix (such as
clawhub-publish-), causing an incorrect slug at publish time--slug <skill-name>Ensure the correct skill identifier is used--name "<Display Name>"Ensure the correct name is displayed on ClawHub
Tencent SkillHub(Use skillhub publish, specify version and changelog):
skillhub publish /tmp/skillhub-publish-<skill-name> \
--version "<新版本号>" \
--changelog "<变更说明>"
Tencent identifies skills by slug + displayName: These two fieldsare not written into the source SKILL.md, but are read before publishing by
prepare-publish.sh --platform skillhubfromconfig/allowlist-skillhub.yamland injected into the temporary copy's frontmatter (slug defaults toname, displayName takes the configureddisplay_name). The namespace is bound to the account (no command-line specification is needed at publish time), and there is no concept of visibility. The version number and changelog are passed explicitly via--version/--changelog; without--version, it is decided by the CLI. Before publishing, you can add--dry-runto perform only a pre-check.
Lenovo Open Platform(Use lenovoskill, first build the zip and then upload in two steps):
# 1. 准备:先在临时目录生成 .skill-config.json(联想 CLI 项目级配置)
cd /tmp/lenovo-publish-<skill-name>
# 源 skill 若已带 .skill-config.json,prepare-publish.sh 已一并复制,跳过 init;
# 否则跑一次 init 生成默认配置再按需编辑:
lenovoskill init
# 2. 打 zip
lenovoskill package
# → 生成 <skill-name>.zip
# 3. 上传 zip
lenovoskill push
Lenovo likewise reads slug + displayName from the SKILL.md frontmatter: These two fields are injected by
prepare-publish.sh --platform lenovointo the temporary copy (sharing the same Python logic with SkillHub). At the same time, the Lenovo CLI also reads the project's.skill-config.json— the two coexist, and thedisplayName/slugfield should remain consistent between the SKILL.md frontmatter and.skill-config.json..skill-config.jsonRecommendedGenerate/copy only in the temporary directory, and do not commit it into the source skill (it is Lenovo CLI's private adaptation layer and has nothing to do with the standard skill structure).
Step 3: Update the sync record
Update skills/skill-publish-sync/config/sync-records.yaml, and write the record under the corresponding platform:
records:
<skill-name>:
platforms:
clawhub: # 或 skillhub / lenovo
version: "<新版本号>"
last_sync: "<ISO 8601 时间>"
git_hash: "<当前 commit hash>"
status: synced
changelog_summary: "<变更说明>"
url: "https://clawhub.ai/skills/<skill-name>" # ClawHub
# 或 SkillHub:
# url: "https://skillhub.cn/skills/<slug>"
# 或联想开放平台:
# url: "https://open.lenovomm.com/skills/<slug>"
publish_id: "<从命令输出获取>"
# SkillHub 还要加一行 namespace: "<your-namespace>";ClawHub / 联想无 namespace 字段
Example: Sync skill (publish to the corresponding platform according to the routing policy)
A. MIT tools → ClawHub (using git-batch-commit as an example)
# 1. 检查白名单
grep -A1 "^git-batch-commit:" skills/skill-publish-sync/config/allowlist-clawhub.yaml
# 输出:platforms: [clawhub] # MIT 工具,只发 ClawHub
# 2. 比较版本
# SKILL.md: version: "1.2.0"
# sync-records.yaml: platforms.clawhub.version: "1.1.0" → 需要同步
# 3. 准备并发布到 ClawHub
bash skills/skill-publish-sync/scripts/prepare-publish.sh skills/git-batch-commit
clawhub publish /tmp/clawhub-publish-git-batch-commit \
--slug git-batch-commit --name "Git Batch Commit" \
--version "1.2.0" --changelog "本次变更说明"
# 4. 更新 sync-records.yaml 的 platforms.clawhub 字段
B. CC-BY-NC legal category → SkillHub (using legal-qa-extractor as an example)
# 1. 检查白名单
grep -A2 "^legal-qa-extractor:" skills/skill-publish-sync/config/allowlist-skillhub.yaml
# 输出:platforms: [skillhub] + display_name: "法律问答知识提取"
# 2. 准备(--platform skillhub 会自动从配置读 display_name/slug 注入临时副本 frontmatter)
bash skills/skill-publish-sync/scripts/prepare-publish.sh --platform skillhub skills/legal-qa-extractor
# 3. 发布到 SkillHub
skillhub publish /tmp/skillhub-publish-legal-qa-extractor \
--version "<新版本号>" --changelog "<变更说明>"
# 4. 更新 sync-records.yaml 的 platforms.skillhub 字段
Failure handling
- On sync failure, record
status: failed - Do not retry; let the user decide the next action
- Record the failure reason to
changelog_summary
SkillHub-specific notes
Token acquisition
- Log in to SkillHub
- Generate an API Token in personal settings (format
skh_xxx, prefixskh_) - Via
skillhub login --key skh_xxxsave to local
skillhub login --key skh_xxx
skillhub auth whoami # 确认身份
Security reminder: A token is equivalent to an account password;absolutely do notwrite it into configuration files or commit it to Git.
skillhub loginThe token has already been saved locally, so subsequent publish commands do not need to pass the token again (the CLI reads it automatically); if you need to temporarily override it, you can useskillhub publishat--token skh_xxx。
slug / namespace and version number rules
Tencent SkillHub uses slug + displayName + namespace(account-bound) to identify skills.slug/displayName are not written into the source SKILL.md, but are configured in config/allowlist-skillhub.yaml(platform-specific whitelist), and before publishing are injected by prepare-publish.sh into the temporary copy's frontmatter:
- slug: kebab-case, 2-128 characters (actual validation regex). Default = skill directory name (i.e.
name); override with theallowlist-skillhub.yamlfield inslug:(to handle duplicate names/names already taken). The slug is unique within the same namespace; duplicate names are allowed across namespaces (e.g.@cat-xierluo/md2worddoes not conflict with someone else's@xxx/md2word) - namespace: namespace,bound to the account(server-side
@<namespace>/<slug>format), the publish commanddoes not need to and cannotspecify it on the command line—the CLI uses the logged-in account's identity, and the server automatically assigns it under your namespace. Your namespace can be determined viaskillhub search <你的skill>by looking at the@xxx/slugprefix of a published skill - version: valid SemVer (
major.minor.patch), e.g.1.0.0. It is recommended to start from0.1.0or1.0.0. Published versions cannot be modified; you can only publish a new version
API host
The default API host is https://api.skillhub.cn. To override it,skillhub publish use --host <URL> to specify it.
SKILL.md frontmatter requirements
When publishing to Tencent SkillHub, skill metadata is read from the SKILL.md frontmatter (of a temporary copy).The source SKILL.md does not need to include slug/displayName——prepare-publish.sh will read from config/allowlist-skillhub.yaml and inject into the temporary copy:
| Field | Source | Description |
|---|---|---|
slug |
Defaults to name;allowlist-skillhub.yaml of slug: can be overridden |
kebab-case, 2-128 characters |
displayName |
allowlist-skillhub.yaml of display_name:(required) |
SkillHub display name (Chinese) |
version |
Source SKILL.md frontmatter (or --version override) |
Valid SemVer |
summary |
Source SKILL.md (optional) | Short summary |
description |
Source SKILL.md (optional) | Longer description |
tags |
Source SKILL.md (optional) | Tag array |
license |
Source SKILL.md (optional) | License identifier |
homepage |
Source SKILL.md (optional) | Homepage URL |
Field differences between ClawHub and Tencent: ClawHub uses the
namefield + command-line--slug/--name; Tencent usesslug+displayName(injected into the temporary copy, not written to the source file; the namespace is bound to the account). The source SKILL.md keeps only standard fields such asname/description/version; the identification needs of both platforms are satisfied by the publishing process (command-line parameters / config injection), without polluting the skill itself.
CLI version notes
Tencent skillhub CLI is a Python script.Older versions (< 2026.7.29) do not support publish/login, run skillhub self-upgrade to upgrade to the latest version; if unsure, first use skillhub self-upgrade --check-only to check whether a new version is available.
Publishing rate limits (avoid concurrent throttling)
The Tencent SkillHub API has rate limits on publish requests.Multiple consecutive skillhub publish will trigger throttling(error "请求过于频繁,请稍后再试"), a single publish failure needs to be retried, and it will slow down the entire batch process.
Actual measured safe interval: for each skillhub publish between sleep 12-15 seconds. Batch publishing N items estimated total time ≈ N × (single publish time + 15s).
Recommended approach(Sequential + sleep, do not parallelize):
while IFS='|' read -r s v; do
bash prepare-publish.sh --platform skillhub "skills/$s" >/dev/null 2>&1
echo "$s: $(skillhub publish /tmp/skillhub-publish-$s --version "$v" --changelog '...' 2>&1 | tail -1)"
sleep 15
done <<EOF
skill-a|1.0.0
skill-b|1.1.0
EOF
Failure handling: When encountering a rate limit error, do not immediately rerun the entire batch.sleep 30-60 seconds later, retry the failed skill individually (from sync-records.yaml see which platforms are still pending)。
Avoid:for s in ...; do (skillhub publish $s &); done(parallel) —— 100% triggers rate limiting.
Lenovo Open Platform (LenovoSkill CLI) upload
Lenovo Open Platform (https://open.lenovomm.com) is a skill distribution channel for the Lenovo AI agent ecosystem.Under the v1.7.1 three independent list architecture, Lenovo is the third channel parallel to ClawHub / SkillHub——any skill can be registered in allowlist-lenovo.yaml (no license restrictions), with fields maintained independently from the ClawHub / SkillHub platforms. One-to-many: the same skill can appear simultaneously in allowlist-clawhub.yaml + allowlist-skillhub.yaml + allowlist-lenovo.yaml multiple files.
Differences from the first two platforms
| Dimension | ClawHub | Tencent SkillHub | Lenovo Open Platform |
|---|---|---|---|
| Platform role | Independent list platform(allowlist-clawhub.yaml) |
Independent list platform(allowlist-skillhub.yaml) |
Independent list platform(allowlist-lenovo.yaml, parallel to SkillHub / ClawHub) |
| Workflow | Single publish command |
Single publish command |
Two steps:package zip → push upload zip |
| CLI | clawhub |
skillhub(Python) |
lenovoskill(npx @lenovo-open/skill-cli,Node.js) |
| Credentials | clawhub login |
skillhub login --key skh_xxx |
lenovoskill login(OAuth browser authorization) |
| Identifier mechanism | Command line --slug/--name |
Temporary copy frontmatter (slug/displayName) | Temporary copy frontmatter (slug/displayName) + in-project .skill-config.json |
| namespace | None | Yes(bound to account, not passed in publish command, used for tracing records) | None(OAuth dual token) |
| License | Mandatory MIT-0 | Unrestricted | Unrestricted |
| Sync record | sync-records.yaml platforms.clawhub |
sync-records.yaml platforms.skillhub(including namespace) |
sync-records.yaml platforms.lenovo(no namespace) |
CLI installation
# 方式 1:npx(推荐,免装、始终最新版)
npx @lenovo-open/skill-cli <cmd>
# 方式 2:全局安装(短命令、可离线)
npm install -g @lenovo-open/skill-cli
# 之后用 lenovoskill 代替 npx @lenovo-open/skill-cli
Hereafter uniformly use lenovoskill; when using npx, just replace it.Prerequisite dependencies: Node.js ≥ 18 + npm(see the "Dependencies · System Dependencies" section of this document).
First login
lenovoskill login # 浏览器 OAuth 授权
lenovoskill whoami # 确认身份
lenovoskill logout # 退出登录
Credentials and configuration (OAuth secure storage,forbidden to write into repository or public platforms):
| File | Mode | Purpose |
|---|---|---|
~/.lenovoskill/auth.json |
600 | Login Token + Biz Token(OAuth dual token) + user information |
~/.lenovoskill/config.json |
Default | API URL (default https://open.lenovomm.com) + default visibility |
Upload workflow (5 steps)
# ① 准备安全过滤目录(复用 prepare-publish.sh,会触发 SkillHub/联想 共用的 frontmatter 注入段)
bash skills/skill-publish-sync/scripts/prepare-publish.sh --platform lenovo skills/<skill-name>
# → 生成 /tmp/lenovo-publish-<skill-name>;临时副本 SKILL.md 已注入 slug + displayName
cd /tmp/lenovo-publish-<skill-name>
# ② 准备 .skill-config.json(联想 CLI 项目级元数据,与 SKILL.md frontmatter 互补)
# - 源 skill 目录若已带 .skill-config.json,prepare-publish.sh 已一并复制,直接用
# - 否则从源目录复制,或在此目录跑一次 lenovoskill init 生成默认配置再按需编辑
lenovoskill init # 生成默认 .skill-config.json(可手编 ignore patterns)
# ③ 打 zip
lenovoskill package
# → 生成 <skill-name>.zip
# ④ 上传 zip
lenovoskill push
⚠️ Must first pass prepare-publish.sh: Lenovo CLI has no built-in .gitignore filtering; directly packaging the source directory will include local real
config/*.yaml、scripts/intermediate artifacts,.DS_Storeand so on into the zip for upload. Run prepare-publish.sh first; the temporary directory is already the "clean content" after git ls-files filtering, so only then is it safe to zip.
.skill-config.json
The Lenovo CLI reads this file in the root directory of each skill project, containing:
- Skill metadata: name / version / description, etc. (can be consistent with the SKILL.md frontmatter)
- Ignore patterns: files to additionally exclude when packaging (double insurance in coordination with prepare-publish.sh)
Recommendation: this fileis only generated/copied in the temporary directory, and is not written back to the source skill repository — it is merely a private adaptation layer of the Lenovo CLI and has nothing to do with the standard skill structure.
Relationship with frontmatter slug/displayName: the Lenovo CLI simultaneously reads from the SKILL.md frontmatter
slug+displayName(injected into the temporary copy by prepare-publish.sh) and from the project's.skill-config.jsonto read metadata.The two should remain consistent——displayName/slugmust not conflict between the SKILL.md frontmatter and.skill-config.json.
Command quick reference
| Command | Purpose |
|---|---|
lenovoskill login |
Log in to the Lenovo Open Platform (OAuth) |
lenovoskill logout |
Log out |
lenovoskill whoami |
Show the currently logged-in user |
lenovoskill init |
Initialize .skill-config.json in the current directory |
lenovoskill package |
Package the current directory into a zip |
lenovoskill push |
Upload the zip to the Lenovo Open Platform |
Failure handling
pushfails: first runlenovoskill whoamito confirm the login state; check.skill-config.jsonfields; confirm the zip is the onepackagejust generated.- Packaged content is incorrect:Return to step 1, modify the source skill and rerun
prepare-publish.sh, do not repackage directly in the source directory (this would bypass the security filtering). - Want to revoke a published version: refer to the "Fixing Published Skills" section of this document, but contacting Lenovo platform support is left to the user's own decision and is outside the scope of this skill.
Relationship with sync-records.yaml
Lenovo platform publish resultsmustbe written into sync-records.yaml the platforms.lenovoof — just like SkillHub / ClawHub, it is a fixed component of the three-platform independent whitelist architecture.platforms.lenovo The field is isomorphic with platforms.skillhub / platforms.clawhub (version / last_sync / git_hash / status / changelog_summary / url / publish_id),no namespace field(OAuth dual-token mechanism, with no concept of namespace).
records:
<skill-name>:
platforms:
lenovo: # 三平台独立白名单架构(联想是独立第三选项,允许与其他平台字段独立维护)
version: "<新版本号>"
last_sync: "<ISO 8601 时间>"
git_hash: "<当前 commit hash>"
status: synced
changelog_summary: "<变更说明>"
url: "https://open.lenovomm.com/skills/<slug>"
publish_id: "<从 lenovoskill push 输出获取>"
# 无 namespace:联想用 OAuth 双 token(Login Token + Biz Token)
⚠️ NOT_VERIFIED: the details of the above LenovoSkill CLI commands (
login/init/package/pushbehavior,.skill-config.jsonfields, OAuth flow, platform license review,whether slug/displayName are actually read from the SKILL.md frontmatter)come from materials provided by the user and have not been independently tested. For the first actual push, the CLI's actual behavior shall prevail; if the behavior deviates (for example, if testing finds that the Lenovo CLI does not read the frontmatter and relies entirely on.skill-config.json), come back and correct this section — the inject section may be meaningless for lenovo, and this decision needs to be re-evaluated.
Sync strategy
Version number handling
- Extract the version number from the
CHANGELOG.mdfirst line of the skill - Format requirements:
## [x.y.z] - YYYY-MM-DD - Automatically handle the
vprefix (v1.0.0→1.0.0)
Automatic fields
| Field | Handling method |
|---|---|
homepage |
Automatically set to the GitHub repository address |
version |
Extracted from CHANGELOG.md (if not specified in SKILL.md) |
Sync scope control (allowlist mechanism, three independent lists in v1.7.1)
Configuration files: Three independent allowlist files (v1.7.1 architecture, see DECISIONS D-2026-08-12-02):
skills/skill-publish-sync/config/allowlist-clawhub.yaml(ClawHub platform allowlist)skills/skill-publish-sync/config/allowlist-skillhub.yaml(SkillHub platform allowlist)skills/skill-publish-sync/config/allowlist-lenovo.yaml(Lenovo Open Platform allowlist)
Priority: allowlist > default ignore rules
- If the corresponding platform's
allowlist-${PLATFORM}.yamlexists: only sync the skills listed in that file (each platform independently reads its own allowlist file) - If the corresponding platform's
allowlist-${PLATFORM}.yamldoes not exist: use the default ignore rules (ignore test/, private-skills/, node_modules/)
Configuration format (three independent lists in v1.7.1, each file has no platforms field):
# allowlist-clawhub.yaml(17 条 MIT 通用工具,display_name/slug 可选)
md2word:
patent-download:
# ...
# allowlist-skillhub.yaml(12 条 CC-BY-NC 法律类,display_name 必填)
legal-qa-extractor:
display_name: "法律问答知识提取"
contract-copilot:
display_name: "合同起草与审查助手"
# ...
# allowlist-lenovo.yaml(0 条,初始空,用户按需手动添加)
# contract-copilot:
# display_name: "合同起草与审查助手" # 与 skillhub 分区独立维护,可不同
One-to-many semantics: the same skill can appear in multiple files at the same time (e.g., contract-copilot can be simultaneously registered in allowlist-skillhub.yaml and allowlist-lenovo.yaml , each maintaining its own independent display_name). There is no need to modify the old skill's configuration for a new platform.
If you need to enable/disable a skill on a certain platform, simply add/comment out that skill's line in the corresponding platform's allowlist file.
Configuration files and privacy (example vs local, three independent lists in v1.7.1)
Configuration files are split into a public template and a local real version, making it easy for this skill to be reused by others:
| File | Role | Whether committed | Contains local real data |
|---|---|---|---|
config/allowlist-clawhub.example.yaml |
ClawHub allowlist public template | ✅ Committed | None |
config/allowlist-skillhub.example.yaml |
SkillHub allowlist public template | ✅ Committed | None |
config/allowlist-lenovo.example.yaml |
Lenovo allowlist public template | ✅ Committed | None |
config/sync-records.example.yaml |
Sync record public template | ✅ Committed | Uses placeholders |
config/allowlist-clawhub.yaml |
ClawHub local real allowlist | ❌ Excluded by gitignore | — |
config/allowlist-skillhub.yaml |
SkillHub local real allowlist | ❌ Excluded by gitignore | — |
config/allowlist-lenovo.yaml |
Lenovo local real allowlist | ❌ Excluded by gitignore | — |
config/sync-records.yaml |
Local real sync record | ❌ Excluded by gitignore | Fill in the actual publish_id, etc. |
First-time use: copy the corresponding
.example.yamland remove the.examplesuffix, then fill in your actual data. The three allowlist filesare maintained independently——the same skill can be registered independently in different allowlists (one-to-many). In the SkillHub / Lenovo allowlist files,display_nameis required (Chinese display name, injected into the temporary copy's frontmatter byprepare-publish.shbefore publishing; the source SKILL.md does not contain this field).sync-records.yamlrecordspublish_idand other publishing results.The root directory
.gitignore's**/config/*.yaml+!**/config/*.example.yamlrulestake effect for all platforms (ClawHub / SkillHub / Lenovo)(sharedprepare-publish.shfilter logic). When actually publishingskill-publish-syncitself, the three realallowlist-*.yamlandsync-records.yamlall do not enter the temporary directory; only the.example.yamltemplate will be uploaded.The root directory
.gitignorealready passes the**/config/*.yaml+!**/config/*.example.yamlrules, automatically excluding real configuration and retaining the template.
File Filtering Rules
When publishing, .gitignore filtering rules are automatically applied to ensure that sensitive files and temporary files are not uploaded. All three platforms share the same filtering logic.
Dual Filtering Mechanism:
- Project Root .gitignore - Automatically detect the Git repository root's
.gitignore - Skill Internal .gitignore - If the skill directory has its own
.gitignore, it will additionally apply
Default exclusions(always in effect):
.git/- Git directorynode_modules/- Node.js dependencies__pycache__/- Python cache.DS_Store- macOS system files
Sync Process
Before each sync, the following will automatically:
- Create a temporary directory - The prefix varies by platform:
/tmp/clawhub-publish-<skill>or/tmp/skillhub-publish-<skill> - Copy the filtered files - Use rsync to copy files following .gitignore rules
- Publish to the target platform - Execute the corresponding platform's publish command from the temporary directory
- Clean up the temporary directory - Automatically cleaned up after publishing is complete
Manually Prepare the Publish Directory
If you need to manually check the files to be published:
# ClawHub(默认)
bash skills/skill-publish-sync/scripts/prepare-publish.sh skills/trademark-assistant
ls -la /tmp/clawhub-publish-trademark-assistant/
# 腾讯 SkillHub
bash skills/skill-publish-sync/scripts/prepare-publish.sh --platform skillhub skills/trademark-assistant
ls -la /tmp/skillhub-publish-trademark-assistant/
Security Best Practices
Pre-publish Checklist
- Confirm that
.gitignoreincludes all sensitive file patterns - Use
prepare-publish.shto check the files to be published - Do not include API keys, passwords, etc. in the skill
- Use
.env.exampleinstead of.envfiles
Common Sensitive Files
.env- Environment variables (use.env.exampleas a template)config.yaml- Configuration files (useconfig.example.yamlas a template)*.db,*.sqlite- Database fileslogs/- Log directoriesdownloads/,output/- Output directories
Fix a Published Skill
If you find that a published skill contains sensitive information:
- Update immediately - Delete the sensitive files from the skill directory
- Update .gitignore - Ensure they will not be included again in the future
- Republish - Use
clawhub publish/skillhub publish/lenovoskill pushto update the corresponding platform - Contact platform support - If the old version needs to be deleted
Important Reminder:
- Both platforms are public platforms: anyone can access the published skill
- Do not include customer information: case files, communication records, etc. should be excluded
- Do not include credentials: API keys, tokens, etc. should use environment variables
FAQ
Version number not updated?
Check the CHANGELOG.md format:
## [1.0.0] - 2026-03-21
### 新增
- 新功能描述
Sync failed?
- ClawHub: Run
clawhub sync --dry-runto check the configuration - SkillHub: Confirm
skillhub auth whoamilogin is working,config/allowlist-skillhub.yamlconfigured for this skilldisplay_name(slug defaults to name; if display_name is missing, prepare-publish.sh will fail-closed with an error) - Lenovo Open Platform: Confirm
lenovoskill whoamilogin is working,config/allowlist-lenovo.yamlconfigureddisplay_name(Lenovo also has frontmatter injected by prepare-publish.sh); Node.js ≥ 18 +npxavailable; temp directory generated.skill-config.json(generated by init or copied from source) - Confirm that the SKILL.md frontmatter format is correct
- Check the allowlist: whether the target skill is in the corresponding platform's
allowlist-${PLATFORM}.yaml(v1.7.1 has three independent lists, with a separate file per platform)
ClawHub reporting a license conflict?
Licenses such as CC-BY-NC conflict with ClawHub MIT-0 and cannot be published to ClawHub. Skills of this kind should be published to SkillHub instead (no license restrictions). See ClawHub Skill Format official documentation。
Input/Output
Input
- Required: the locally developed skill directory
- Optional: specify the skill name list, target platform (
clawhub/skillhub/lenovo, with a separate allowlist file per platformallowlist-${PLATFORM}.yaml; see the platform comparison table and the sync scope control section for details), allowlist configuration
Output
- Sync result report (success/failure list, grouped by platform)
- Error messages (if any)
Sync records
After each sync, config/sync-records.yaml will be updated as a record file to facilitate traceability and incremental sync. Records are stored separately by platform.
Record structure
records:
<skill-name>:
platforms:
clawhub: # ClawHub 平台记录
<fields>
skillhub: # 腾讯 SkillHub 平台记录(含 namespace 字段)
<fields>
lenovo: # 联想开放平台记录(无 namespace 字段)
<fields>
Record fields
| Field | Description | Applicable platform |
|---|---|---|
version |
Version number at sync time | All three |
last_sync |
Last sync time (ISO 8601) | All three |
git_hash |
Commit hash at sync time | All three |
status |
synced / pending / failed / skipped / slug_conflict / deleted |
All three |
changelog_summary |
Change summary | All three |
url |
Platform publish URL | All three |
publish_id |
Platform internal ID | All three |
namespace |
Namespace (account binding, such as cat-xierluo; not passed during publishing, recorded for traceability of install commands) |
SkillHub only(ClawHub / Lenovo have no namespace concept) |
Record example
records:
md2word:
platforms:
clawhub:
version: "1.1.8"
last_sync: "2026-03-24T16:42:00+08:00"
git_hash: "fbb1db4"
status: synced
changelog_summary: "全书自动更新目录域"
url: "https://clawhub.ai/skills/md2word"
publish_id: "k97dtn63cty6ezwzj9g9ry85818axkdq"
skillhub:
namespace: "cat-xierluo"
version: "1.1.8"
last_sync: "2026-08-01T10:00:00+08:00"
git_hash: "fbb1db4"
status: synced
changelog_summary: "首次发布 SkillHub"
url: "https://skillhub.cn/cat-xierluo/md2word"
publish_id: "sh_xxxxxxxxxxxxxxxx"
lenovo:
# 无 namespace:联想用 OAuth 双 token(Login Token + Biz Token)
version: "1.1.8"
last_sync: "2026-08-12T10:00:00+08:00"
git_hash: "fbb1db4"
status: synced
changelog_summary: "首次发布联想开放平台"
url: "https://open.lenovomm.com/skills/md2word"
publish_id: "len_xxxxxxxxxxxxxxxx"
Purpose
- Incremental sync: only sync
status: pendingor skills with version updates (judged independently per platform) - Traceability: use
git_hashto trace the code state at publish time - Quick access: use
urlto directly access the skill page on the platform