printing-press-amend

printing-press-amend

热门

通过两种输入源对已发布的 CLI 进行修正升级:(1) 吃狗粮模式(dogfood mode):自动挖掘当前 Claude Code 会话记录中的使用卡点(例如缺失 flag 参数、手撸 API 请求体、静默返回 null 等);(2) 直接输入模式(direct-input mode):接收用户明确提出的需求(重命名命令、添加命令或 feed、修复指定 bug,或者嗅探源站寻找新 API 接口)。系统会与用户确认修改范围,全自动规划并执行修复、擦除 PII 敏感信息,并向 mvanhorn/printing-press-library 提交 PR。整个流程包含两个人工确认节点:捕获信息后的范围确认,以及提交前的 PR 草案确认。触发短语:"amend the CLI", "submit a patch", "fix what I just dogfooded", "open a PR for this CLI", "patch this CLI", "add features to my CLI", "rename this command", "add these feeds to <cli>", "sniff for new APIs in <cli>", "amend with these ideas", "use printing-press-amend", "run printing-press-amend"。

4204Star
450Fork
更新于 2026/7/20
SKILL.md
只读
名称
printing-press-amend
描述

通过两种输入源对已发布的 CLI 进行修正升级:(1) 吃狗粮模式(dogfood mode):自动挖掘当前 Claude Code 会话记录中的使用卡点(例如缺失 flag 参数、手撸 API 请求体、静默返回 null 等);(2) 直接输入模式(direct-input mode):接收用户明确提出的需求(重命名命令、添加命令或 feed、修复指定 bug,或者嗅探源站寻找新 API 接口)。系统会与用户确认修改范围,全自动规划并执行修复、擦除 PII 敏感信息,并向 mvanhorn/printing-press-library 提交 PR。整个流程包含两个人工确认节点:捕获信息后的范围确认,以及提交前的 PR 草案确认。触发短语:"amend the CLI", "submit a patch", "fix what I just dogfooded", "open a PR for this CLI", "patch this CLI", "add features to my CLI", "rename this command", "add these feeds to <cli>", "sniff for new APIs in <cli>", "amend with these ideas", "use printing-press-amend", "run printing-press-amend"。

版本
0.2.0

/printing-press-amend

把实测吃狗粮(dogfood)会话中积累的体验问题,转化为针对公共仓库中已打印 CLI 的 PR 补丁。

/printing-press-amend                 # 从当前会话中自动检测目标 CLI
/printing-press-amend superhuman      # 显式指定简称
/printing-press-amend superhuman-pp-cli
/printing-press-amend "$PRESS_LIBRARY/superhuman"

该 Skill 存在于本仓库(即“机器”本身),作用于公共仓库中已打印的 CLI。它与 /printing-press-publish(添加新 CLI)、/printing-press-polish(发布前打磨 CLI)以及 /printing-press-retro(对机器本身进行复盘反思)属于同级 Skill。以上其他 Skill 均不涵盖由真实会话卡点驱动的发布后 CLI 修正。

该 Skill 生成的产物在语义上是一个“补丁(patch)”(即 git/PR 概念上的补丁),由公共仓库的 .printing-press-patches/ 目录进行追踪(每个补丁对应一个文件)。行内 // PATCH(...) 源码注释属于可选的导航辅助,在对定制化站点进行 grep 查找时方便定位。Slash-skill 的名称定为 amend,是为了与已有的 cli-printing-press patch 二进制子命令做区分(后者是通过 AST 注入预定义功能 —— 机制不同,意图也不同)。

Setup

在执行任何其他操作前:

<!-- PRESS_SETUP_CONTRACT_START -->

# min-binary-version: 4.0.0

# Derive scope first — needed for local build detection
_scope_dir="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
_scope_dir="$(cd "$_scope_dir" && pwd -P)"

# Prefer local build when running from inside the printing-press repo.
_press_repo=false
if [ -x "$_scope_dir/cli-printing-press" ] && [ -d "$_scope_dir/cmd/cli-printing-press" ]; then
  _press_repo=true
  export PATH="$_scope_dir:$PATH"
  echo "Using local build: $_scope_dir/cli-printing-press"
elif ! command -v cli-printing-press >/dev/null 2>&1; then
  if [ -x "$HOME/go/bin/cli-printing-press" ]; then
    echo "cli-printing-press found at ~/go/bin/cli-printing-press but not on PATH."
    echo "Add GOPATH/bin to your PATH:  export PATH=\"\$HOME/go/bin:\$PATH\""
  else
    echo "cli-printing-press binary not found."
    echo "Install with:  go install github.com/mvanhorn/cli-printing-press/v4/cmd/cli-printing-press@latest"
  fi
  return 1 2>/dev/null || exit 1
fi

# Resolve and emit the absolute path the agent must use for every later
# `cli-printing-press` invocation. `export PATH` above only affects this one
# Bash tool call; subsequent calls open a fresh shell and resolve bare
# `cli-printing-press` against the user's default PATH, where a stale global
# can silently shadow the local build. The agent captures this marker and
# substitutes the absolute path into every later invocation.
if [ "$_press_repo" = "true" ]; then
  PRINTING_PRESS_BIN="$_scope_dir/cli-printing-press"
else
  PRINTING_PRESS_BIN="$(command -v cli-printing-press 2>/dev/null || true)"
fi
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.5 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
echo "PRINTING_PRESS_BIN=$PRINTING_PRESS_BIN"

_pp_semver_lt() {
  awk -v a="$1" -v b="$2" 'BEGIN {
    split(a, x, "."); split(b, y, ".")
    for (i = 1; i <= 3; i++) {
      if ((x[i] + 0) < (y[i] + 0)) exit 0
      if ((x[i] + 0) > (y[i] + 0)) exit 1
    }
    exit 1
  }'
}

_pp_go_version_norm() {
  printf '%s\n' "$1" | sed -nE 's/.*go([0-9]+)\.([0-9]+)(\.([0-9]+))?.*/\1.\2.\4/p' | awk -F. 'NF >= 2 { printf "%d.%d.%d\n", $1, $2, ($3 == "" ? 0 : $3) }'
}

_pp_check_go_currency() {
  _pp_go_installed="$(_pp_go_version_norm "$(go env GOVERSION 2>/dev/null)")"
  _pp_go_required="$(_pp_go_version_norm "$(go version "$PRINTING_PRESS_BIN" 2>/dev/null)")"
  if [ -z "$_pp_go_installed" ] || [ -z "$_pp_go_required" ] || ! _pp_semver_lt "$_pp_go_installed" "$_pp_go_required"; then
    return 0
  fi

  echo ""
  if [ "${GOTOOLCHAIN:-auto}" = "local" ]; then
    echo "[setup-error] Go $_pp_go_required or newer is required by this cli-printing-press binary (installed: $_pp_go_installed)."
    echo "GOTOOLCHAIN=local disables automatic toolchain downloads, so later Go quality gates would fail."
    echo "Install Go $_pp_go_required or newer from https://go.dev/dl/, or unset GOTOOLCHAIN."
    echo ""
    return 1
  fi

  echo "[go-toolchain-old] Go $_pp_go_required or newer is required by this cli-printing-press binary (installed: $_pp_go_installed)."
  echo "PRESS_GO_INSTALLED=$_pp_go_installed"
  echo "PRESS_GO_REQUIRED=$_pp_go_required"
  echo "Default GOTOOLCHAIN behavior may download the required toolchain during Go commands."
  echo ""
  return 0
}
_pp_check_go_currency || { return 1 2>/dev/null || exit 1; }

PRESS_BASE="$(basename "$_scope_dir" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9_-]/-/g; s/^-+//; s/-+$//')"
if [ -z "$PRESS_BASE" ]; then
  PRESS_BASE="workspace"
fi

PRESS_SCOPE="$PRESS_BASE-$(printf '%s' "$_scope_dir" | shasum -a 256 | cut -c1-8)"
PRESS_HOME="${PRINTING_PRESS_HOME:-$HOME/printing-press}"
PRESS_RUNSTATE="$PRESS_HOME/.runstate/$PRESS_SCOPE"
PRESS_LIBRARY="$PRESS_HOME/library"
PRESS_MANUSCRIPTS="$PRESS_HOME/manuscripts"
PRESS_CURRENT="$PRESS_RUNSTATE/current"

_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 'NR == 2 { print $4; exit }')"
  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; }

mkdir -p "$PRESS_RUNSTATE" "$PRESS_LIBRARY" "$PRESS_MANUSCRIPTS" "$PRESS_CURRENT"

# --- Currency-floor check (standalone, fail-open) ---
# Hard-stop on binaries below the published supported floor so amend does not
# regenerate CLIs with since-fixed bugs. Repo checkouts build from source and
# are exempt. The floor is clamped to <= latest so a bad value cannot brick
# every install. Fetched fresh each run rather than reusing the printing-press
# preflight's TTL cache: amend is low-frequency, so the bounded curl + go-list
# cost is not worth its own cache here.
if [ "$_press_repo" != "true" ] && command -v curl >/dev/null 2>&1; then
  _semver_lt() {
    awk -v a="$1" -v b="$2" 'BEGIN {
      split(a, x, "."); split(b, y, ".")
      for (i = 1; i <= 3; i++) {
        if ((x[i] + 0) < (y[i] + 0)) exit 0
        if ((x[i] + 0) > (y[i] + 0)) exit 1
      }
      exit 1
    }'
  }
  _floor_installed=$("$PRINTING_PRESS_BIN" version --json 2>/dev/null | sed -nE 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p')
  _floor_doc=$(curl -fsSL --max-time 5 \
    https://raw.githubusercontent.com/mvanhorn/cli-printing-press/main/supported-versions.txt 2>/dev/null || true)
  _floor_min=$(printf '%s\n' "$_floor_doc" | awk -F= '/^min_supported=/{print $2; exit}')
  _floor_reason=$(printf '%s\n' "$_floor_doc" | sed -nE 's/^reason=//p' | head -n 1)
  _floor_latest=""
  if command -v go >/dev/null 2>&1; then
    _floor_latest=$(go list -m -json github.com/mvanhorn/cli-printing-press/v4@latest 2>/dev/null | awk '/"Version":/{v=$2; gsub(/[",]/,"",v); sub(/^v/,"",v); print v; exit}')
  fi
  if [ -n "$_floor_min" ] && [ -n "$_floor_installed" ] && [ -n "$_floor_latest" ] &&
     _semver_lt "$_floor_installed" "$_floor_min" &&
     ! _semver_lt "$_floor_latest" "$_floor_min"; then
    echo ""
    echo "[upgrade-required] printing-press v$_floor_min is the minimum supported version (you have v$_floor_installed)"
    echo "PRESS_REQUIRED_MIN=$_floor_min"
    echo "PRESS_REQUIRED_INSTALLED=$_floor_installed"
    echo "PRESS_REQUIRED_REASON=$_floor_reason"
    echo ""
  fi
fi

<!-- PRESS_SETUP_CONTRACT_END -->

运行 setup 合约后,从标准输出(stdout)中捕获 PRINTING_PRESS_BIN=<abs-path> 这一行。本 Skill 随后每次调用 cli-printing-press ... 时,都必须使用该绝对路径(请替换为具体的路径值,不要直接使用字面量 $PRINTING_PRESS_BIN 变量)—— 上述 export PATH 仅对当前调用的这单个 Bash 工具生效,后续调用会开启全新的 shell,直接输入 cli-printing-press 会解析用户默认的 PATH,此时旧版的全局二进制可能会静默覆盖掉本地构建版本。

如果 setup 输出了 [go-toolchain-old][low-disk],请将这些提示展示给用户并继续执行(除非 setup 同时输出了 [setup-error])。[go-toolchain-old] 意味着后续 Go 命令可能会自动下载所需的 Toolchain,或者在禁用下载时导致失败;[low-disk] 则意味着本次运行可能需要几 GiB 空间用于生成文件、Go 构建缓存、模块下载或仓库克隆。

捕获二进制文件路径后,检查二进制版本的兼容性。读取该 Skill 的 YAML frontmatter 中的 min-binary-version 字段。运行 <PRINTING_PRESS_BIN> version --json 并从输出中解析版本号。按照 semver 语义化版本规则将其与 min-binary-version 进行比较。如果已安装的二进制版本低于最低要求,请立即终止并告知用户:"cli-printing-press binary vX.Y.Z is older than the minimum required vA.B.C. Run go install github.com/mvanhorn/cli-printing-press/v4/cmd/cli-printing-press@latest to update."

如果 setup 合约输出了 [upgrade-required] 日志块,说明已安装的二进制文件低于公开发布的最低版本门槛 (PRESS_REQUIRED_MIN) —— 较旧的版本重新生成 CLI 时可能会重新带入后续已修复的 bug (PRESS_REQUIRED_REASON)。这是与 min-binary-version 不同的硬性拦截门槛:绝对不要基于该版本的二进制进行修正或重新生成。通过 AskUserQuestion 提供一键升级选项 —— Yes — upgrade now(运行 go install github.com/mvanhorn/cli-printing-press/v4/cmd/cli-printing-press@latest,重新捕获 PRINTING_PRE...