mcpField
P
printing-press-import

printing-press-import

github.com/mvanhorn开发4.9k6.5k 次安装今天更新
代码仓库

关于 printing-press-import

此技能将 Printing Press 公共库中的已发布 CLI 导入内部工作库,并一并导入稿件。它通过注册表解析 CLI 名称,覆盖前检查来源,必要时备份,并重写模块路径、验证构建。

主要功能

  1. 01通过注册表解析 CLI 名称
  2. 02导入 CLI 和稿件
  3. 03覆盖前检查来源信息
  4. 04备份现有库内容
  5. 05重写模块路径并验证构建

适用场景

  1. 01将公共库中的 CLI 导入内部库
  2. 02恢复缺失或不同步的内部副本
  3. 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.sh
import-fetch.sh
import-place.sh
import-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"

按以下顺序匹配:

  1. 精确匹配 name — jq --arg q "$ARG" '.entries[] | select(.name == $q)' "$REGISTRY"
  2. 规范化后精确匹配 — 去掉 -pp-cli 后缀,转换为小写,将点替换为连字符,然后精确匹配
  3. 对 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 开始时,正确的流程是先导入再润色。

评论

支持 Markdown