关于 printing-press-import
此技能将 Printing Press 公共库中的已发布 CLI 导入内部工作库,并一并导入稿件。它通过注册表解析 CLI 名称,覆盖前检查来源,必要时备份,并重写模块路径、验证构建。
主要功能
- 01通过注册表解析 CLI 名称
- 02导入 CLI 和稿件
- 03覆盖前检查来源信息
- 04备份现有库内容
- 05重写模块路径并验证构建
适用场景
- 01将公共库中的 CLI 导入内部库
- 02恢复缺失或不同步的内部副本
- 03为已发布的 CLI 准备润色或重新发布
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mvanhorn/ cli-printing-press --skill printing-press-import安装后在 Claude Code 中输入/printing-press-import确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/import-backup.shimport-fetch.shimport-place.shimport-rewrite.sh详细介绍
/printing-press-import
将公共库中的已发布 CLI
(mvanhorn/printing-press-library)
导入内部库 $PRESS_LIBRARY/,使其符合生成器生成的格式。手稿也会一并导入。
/printing-press-import notion
/printing-press-import cal.com
/printing-press-import allrecipes --from-clone ~/Code/printing-press-library
内部库是工作副本;公共库是持久化产物。导入后,CLI 即可进行润色、压印或重新发布——发布步骤会重新应用模块路径重写。
何时运行
- 公共库中有一个你本地没有的 CLI
- 内部副本损坏、丢失或不同步
- 你想在对已发布的 CLI 运行润色前,先准备一个干净的基线
如果用户要求润色 CLI,并提到“在公共库中/来自公共库”或“来自仓库”,建议先运行此技能。
设置
PRESS_HOME="${PRINTING_PRESS_HOME:-$HOME/printing-press}"
PRESS_LIBRARY="$PRESS_HOME/library"
PRESS_MANUSCRIPTS="$PRESS_HOME/manuscripts"
SCRIPTS_DIR="$(dirname "${BASH_SOURCE[0]:-.}")/references"
if ! command -v go >/dev/null 2>&1; then
echo ""
echo "[setup-error] Go toolchain not found."
echo ""
echo "This Printing Press flow runs Go-based build or validation commands."
echo "Install Go 1.26.10 or newer from https://go.dev/dl/, then verify with:"
echo " go version"
echo "Then re-run this skill."
echo ""
return 1 2>/dev/null || exit 1
fi
_pp_check_disk_space() {
_pp_disk_warn_kb="${PRINTING_PRESS_DISK_WARN_KB:-3145728}"
_pp_disk_fail_kb="${PRINTING_PRESS_DISK_FAIL_KB:-524288}"
case "$_pp_disk_warn_kb$_pp_disk_fail_kb" in
""|*[!0-9]*) return 0 ;;
esac
_pp_disk_path="$PRESS_HOME"
while [ ! -e "$_pp_disk_path" ] && [ "$_pp_disk_path" != "/" ]; do
_pp_disk_path="$(dirname "$_pp_disk_path")"
done
_pp_disk_avail_kb="$(df -Pk "$_pp_disk_path" 2>/dev/null | awk 'BEGIN {
if ((getline header) <= 0 || (getline record) <= 0) exit
field_count = split(record, fields)
if (field_count >= 4) print fields[4]
}')"
case "$_pp_disk_avail_kb" in
""|*[!0-9]*) return 0 ;;
esac
if [ "$_pp_disk_avail_kb" -lt "$_pp_disk_fail_kb" ]; then
echo ""
echo "[setup-error] Critically low disk space on the Printing Press workspace volume."
echo "PRESS_DISK_PATH=$_pp_disk_path"
echo "PRESS_DISK_AVAIL_KB=$_pp_disk_avail_kb"
echo "PRESS_DISK_FAIL_KB=$_pp_disk_fail_kb"
echo "Free disk space or set PRINTING_PRESS_HOME to a volume with more room, then re-run this skill."
echo ""
return 1
fi
if [ "$_pp_disk_avail_kb" -lt "$_pp_disk_warn_kb" ]; then
echo ""
echo "[low-disk] Printing Press workspace volume is low on free space."
echo "PRESS_DISK_PATH=$_pp_disk_path"
echo "PRESS_DISK_AVAIL_KB=$_pp_disk_avail_kb"
echo "PRESS_DISK_WARN_KB=$_pp_disk_warn_kb"
echo "This flow may need several GiB for generated files, Go build cache, module downloads, or repository clones."
echo ""
fi
}
_pp_check_disk_space || { return 1 2>/dev/null || exit 1; }
四个参考脚本与此 SKILL.md 一同放在 references/ 下:
import-fetch.sh <library-path> <staging> [--clone <path>]import-backup.sh <api-slug>(在标准输出中打印 zip 路径)import-rewrite.sh <staging> <api-slug>import-place.sh <staging> <api-slug>
如果设置过程输出了 [low-disk],请告知用户这一提示,并继续操作,除非设置过程还输出了 [setup-error]。[low-disk] 表示此运行可能需要数 GiB 空间,用于仓库克隆、暂存文件、备份、Go 构建缓存或模块下载。
阶段 1 — 解析 CLI
参数可以是任意自然表达:API slug(notion)、品牌名(cal.com)、旧 CLI 名称(notion-pp-cli)或近似名称(Allrecipes)。通过公共库的 registry.json 解析——一次获取即可读取每个条目的 name、category、api、description 和 path。
REGISTRY=$(mktemp)
gh api -H "Accept: application/vnd.github.v3.raw" \
repos/mvanhorn/printing-press-library/contents/registry.json \
> "$REGISTRY"
按以下顺序匹配:
- 精确匹配
name—jq --arg q "$ARG" '.entries[] | select(.name == $q)' "$REGISTRY" - 规范化后精确匹配 — 去掉
-pp-cli后缀,转换为小写,将点替换为连字符,然后精确匹配 - 对
name或description进行子字符串匹配 — 不区分大小写
# Exact:
jq --arg q "$ARG" '.entries[] | select(.name == $q)' "$REGISTRY"
# Normalized exact (after $ARG2 = lowercase, dot→hyphen, suffix-stripped):
jq --arg q "$ARG2" '.entries[] | select(.name == $q)' "$REGISTRY"
# Fuzzy (substring on name or description):
jq --arg q "$ARG2" '.entries[]
| select((.name | ascii_downcase | contains($q | ascii_downcase))
or (.description | ascii_downcase | contains($q | ascii_downcase)))
' "$REGISTRY"
如果匹配到一个结果:使用它。如果有多个结果:通过 AskUserQuestion 向用户展示最多 4 个候选项,每个候选项显示 name 和 description。如果没有结果:告知用户公共库中没有该 CLI。
匹配到的条目包含所需的全部信息:
- 从
.path获取LIB_PATH(例如library/productivity/cal-com) - 从
.name获取API_SLUG - 从
.category获取CATEGORY
处理候选项时,不要一次性读取整个文件。 上述字段已足够;如果确实需要更多信息,每个 CLI 的清单位于 <LIB_PATH>/manifest.json,其中的描述也可以用相同方式提取(gh api -H "Accept: ... raw" .../manifest.json | jq -r '.description')。
阶段 2 — 决定是否覆盖
检查内部库中是否已有此 CLI:
LIB_TARGET="$PRESS_LIBRARY/$API_SLUG"
MAN_TARGET="$PRESS_MANUSCRIPTS/$API_SLUG"
如果两处都不存在: 直接导入——进入阶段 3。
如果任一处存在: 读取两边的来源信息,以决定是否覆盖。不要读取整个 .printing-press.json 文件——只提取相关字段:
# Internal provenance (if present):
jq '{run_id, generated_at, printing_press_version, spec_checksum}' \
"$LIB_TARGET/.printing-press.json" 2>/dev/null
# Public provenance (one-shot via raw):
gh api -H "Accept: application/vnd.github.v3.raw" \
repos/mvanhorn/printing-press-library/contents/$LIB_PATH/.printing-press.json \
| jq '{run_id, generated_at, printing_press_version, spec_checksum}'
根据差异判断:
run_id相同 — 公共库和内部库来自同一次生成。很可能无需操作;覆盖前应询问用户。如果用户仍希望导入(例如,为了恢复损坏的内部副本),则继续。- 公共库的
generated_at更新 — 公共库包含内部库没有的更改。导入是安全的做法;请用户确认。 - 内部库的
generated_at更新 — 内部库包含公共库没有的工作(进行中的润色、手动修复)。导入会覆盖这些内容。停止并告知用户——他们可能应先发布内部更改。 - 任一侧缺少
.printing-press.json— 版本较旧或由人工导入。询问用户。
用户确认覆盖后,阶段 3 的备份步骤会保存当前内部状态。
阶段 3 — 导入
STAGING=$(mktemp -d)
# Fetch (remote unless --from-clone was passed)
if [[ -n "${CLONE_PATH:-}" ]]; then
bash "$SCRIPTS_DIR/import-fetch.sh" "$LIB_PATH" "$STAGING" --clone "$CLONE_PATH"
else
bash "$SCRIPTS_DIR/import-fetch.sh" "$LIB_PATH" "$STAGING"
fi
# Backup if anything is being clobbered. Prints zip path on stdout.
if [[ -d "$LIB_TARGET" || -d "$MAN_TARGET" ]]; then
BACKUP_ZIP=$(bash "$SCRIPTS_DIR/import-backup.sh" "$API_SLUG")
echo "Backed up to: $BACKUP_ZIP"
fi
# Reverse the publish-step module path rewrites.
bash "$SCRIPTS_DIR/import-rewrite.sh" "$STAGING" "$API_SLUG"
# Atomically move staging into place.
bash "$SCRIPTS_DIR/import-place.sh" "$STAGING" "$API_SLUG"
第 4 阶段 — 验证内部一致性
移入后,确认导入的 CLI 能够构建且结构完整。将任何失败都视为实际问题——不要掩盖问题。
cd "$LIB_TARGET"
# Module path is local form
grep -q "^module ${API_SLUG}-pp-cli\$" go.mod \
|| { echo "FAIL: go.mod still on public module path"; exit 1; }
# No public module path leaked into source
if grep -rq "github.com/mvanhorn/printing-press-library/library" \
--include='*.go' --include='*.yaml' --include='*.yml' .; then
echo "FAIL: source still references public module path"
exit 1
fi
# Build
go build ./... \
|| { echo "FAIL: go build"; exit 1; }
# Doctor (self-check)
make doctor 2>/dev/null \
|| ./bin/${API_SLUG}-pp-cli doctor 2>/dev/null \
|| true # best-effort; not all CLIs have doctor wired the same way
报告导入结果:
- 源路径(来自注册表:
<category>/<api-slug>) - 运行 ID(来自
.printing-press.json) - 已放置的 Manuscripts 运行 ID(数量 + 名称)
- 备份 zip 路径(如有)
- 构建状态
Polish 侧提示
如果用户是因 polish 请求而触发导入(例如,他们说“润色公共库中的 Notion”),请建议:
Imported $API_SLUG. To polish: /printing-press-polish $API_SLUG
polish 技能作用于内部库,因此从已发布的 CLI 开始时,正确的流程是先导入再润色。