printing-press-amend
Amend a published CLI from one of two input sources: (1) dogfood mode mines the active Claude Code session transcript for friction (missing flags, hand- rolled API payloads, silent-null returns); (2) direct-input mode accepts user-supplied asks (rename a command, add commands or feeds, fix a named b
By mvanhorn · 4,829 installs
npx skills add mvanhorn/cli-printing-press --skill printing-press-amend
Source repository · Upstream listing
/printing press amend
Turn a dogfood session into a PR for a printed CLI in the public library.
This skill lives in this repo (the machine) and acts on a printed CLI in the public library. It is sibling to /printing press publish (adds a new CLI), /printing press polish (improves a CLI pre publish), and /printing press retro (reflects on the machine itself). None of those cover post publish CLI amendments driven by real session friction.
The artifact this skill produces is semantically a "patch" (in the git/PR sense), tracked by the public library's .printing press patches/ directory (one file per patch). Inline // PATCH(...) source comments are optional navigation aids when they make a customized site easier to grep. The slash skill name is amend to disambiguate from the existing cli printing press patch binary subcommand (which AST injects pre defined features — different mechanism, different intent).
Setup
Before doing anything else:
<! PRESS SETUP CONTRACT START
<! PRESS SETUP CONTRACT END
After running the setup contract, capture the PRINTING PRESS BIN=<abs path line from stdout. Every subsequent cli printing press ... invocation in this skill must use that absolute path (substitute the value, not the literal $PRINTING PRESS BIN token) — export PATH above only affects the single Bash tool call it runs in, so later calls open a fresh shell where bare cli printing press resolves against the user's default PATH and a stale global can shadow the local build.
If setup emitted [go toolchain old] or [low disk] , surface the advisory to the user and continue unless setup also emitted [setup error] . [go toolchain old] means later Go commands may download the required toolchain or fail when downloads are blocked; [low disk] means this run may need several GiB for generated files, Go build cache, module downloads, or repository clones.
After capturing the binary path, check binary version compatibility. Read the min binary version field from this skill's YAML frontmatter. Run <PRINTING PRESS BIN version json and parse the version from the output. Compare it to min binary version using semver rules. If the installed binary is older than the minimum, stop immediately and tell the user: "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."
If the setup contract emitted an [upgrade required] block, the installed binary is below the published currency floor ( PRESS REQUIRED MIN ) — older releases regenerate CLIs with since fixed bugs ( PRESS REQUIRED REASON ). This is a hard gate distinct from min binary version : do not amend or regenerate on that binary. Offer a one click upgrade via AskUserQuestion — Yes — upgrade now (run go install github.com/mvanhorn/cli printing press/v4/cmd/cli printing press@latest , re capture PRINTING PRESS BIN , then continue) or Cancel (stop the run). There is no skip and continue; below the floor the only paths are upgrade or abort. If the upgrade command fails, surface it and stop.
Phase 0 — Input Mode Detection
This skill accepts two input sources for the finding list it later patches: a Claude Code session transcript (dogfood mode, current behavior) and user supplied asks in the slash command prompt (direct input mode, added in v0.2). The two modes diverge only in Phase 1; Phase 2 onward is mode agnostic and consumes a typed finding list with identical shape regardless of source.
Decide the mode before Phase 1 runs.
Detection rubric
Read the slash command prompt body and the immediate invocation turn from the conversation context. Classify into one of four branches:
MODE=direct — the prompt contains a concrete CLI name AND at least one direct input signal:
Action verbs targeting the CLI: rename , add , remove , fix , sniff , discover
Explicit URLs the user wants added (e.g., https://example.com/feed/x )
An enumerated list of feeds, commands, endpoints, or features
Phrasing like "these ideas", "these features", "with the following"
MODE=dogfood — the prompt is empty, OR names a CLI without any asks ("amend the superhuman CLI"), OR explicitly references the session ("what I just dogfooded", "this session's friction", "from my session today")
MODE=both — the prompt clearly references both: a session AND specific asks ("I dogfooded this session and also want to add feature X", "in addition to the friction I hit, please add command Y")
Ambiguous — only one signal is present (CLI named with no verbs, or verbs with no target CLI, or asks worded so they could be friction reports OR new asks). Ask the user via AskUserQuestion :
"Two ways to source findings for this amend. Which fits?
1. Mine the current session transcript (dogfood mode)
2. Use the asks I just typed (direct input mode)
3. Both — combine transcript friction with my asks"
Default when no slash command prompt is present at all: MODE=dogfood . This preserves the canonical UX — /printing press amend with nothing after still works exactly as it did in v0.1.
Persist the mode
Write the resolved mode to $PRESS RUNSTATE/current/mode.txt so later phases (and a resumed run) can read it:
Output
Phase 0 emits one line to Phase 1:
Phase 1 branches on this value — dogfood findings flow through 1a , direct input findings flow through 1b , and combined runs execute both sub sections in sequence. Phase 2 onward ignores the mode entirely — the finding list is the contract.
Phase 1 — Capture
This phase produces a typed finding list. The list shape is identical across modes: each finding carries id , kind , category , classification (bug or feature), evidence , target cli , rationale , and provenance ( transcript for dogfood, user ask for direct, sniff for sniff derived). Phase 2 consumes the list verbatim.
When MODE=dogfood , run only 1a . When MODE=direct , run only 1b . When MODE=both , run 1a first, then 1b , and merge the two finding lists with non colliding IDs (1b continues numbering where 1a left off).
1a. Dogfood mode (MODE=dogfood)
Read references/transcript parsing.md for the full procedure. Summary of what this sub section does:
1. Resolve the active session transcript file — derive <project dir slug from the current working directory, list ~/.claude/projects/<slug / .jsonl by mtime, pick the most recently modified. ALWAYS confirm the resolved path with the user via AskUserQuestion before reading — wrong file selection ingests friction from the wrong session.
2. Walk the transcript and extract friction signals — non zero exit codes, error messages, hand rolled API payloads (e.g. direct curl POSTs that should be a CLI command), retry after failure patterns, agent commentary like "X doesn't exist" / "X returns 400", missing flag references, silent null returns, auth confusion. Each signal carries timestamp + category + verbatim evidence + the <slug pp cli it references.
3. Classify each signal as bug or feature with a one line rationale. Bug = CLI behavior is wrong; feature = CLI behavior is missing. The classification is the agent's best read; the user confirms or overrides at the U4 scope checkpoint.
4. Auto detect target CLI — count occurrences of each <slug pp cli in the signals, propose the most touched CLI as the default. Confirm with AskUserQuestion (single CLI: simple yes/no; multiple close: pick from list). When the user passed an explicit <cli name or path argument, skip auto detect.
5. Resolve target paths and publish status — accept short name, full name, or absolute path (per R4). Normalize the input to the bare CLI slug, then resolve publish status by looking up that slug in the public library ( ~/printing press library/library/ /<slug when a local clone exists, otherwise the same path via gh api ). Do not infer publish status from the local working copy's git remotes, and do not treat a missing $PRESS LIBRARY/<slug working copy as unpublished. If the slug is found in the public library, record target category , published status: published , and route the run through the managed clone upstream PR path. Only use published status: local only when the slug is absent from the public library. The category is needed by U7's PR open phase and is captured here so it doesn't have to be re derived.
Each finding emitted by 1a carries provenance: transcript . Output flows into Phase 2 as the structured finding list documented in references/transcript parsing.md .
1b. Direct input mode (MODE=direct)
Read references/direct input parsing.md for the full procedure (introduced in v0.2). Summary of what this sub section does:
1. Read the slash command prompt body plus the immediate agent message turn that fired the skill — these carry the user's verbatim asks (e.g., "rename Digg 1000 to Digg, add these four feeds: ..., sniff for new endpoints"). There is no transcript to confirm; skip the U1 transcript path modal that 1a runs.
2. Resolve the target CLI — same name resolution rules as 1a step 4 5 (per R4), but the CLI is normally already named in the prompt itself. Extract via regex ( <slug pp cli or "the <slug CLI"); if absent, ask the user.
3. Parse the asks into structured findings using the rubric in references/direct input parsing.md . Each ask maps to one finding with a typed kind field:
rename — "rename X to Y" / "call it X instead of Y" → classification: feature
add command — "add command X" / "add subcommand X" → classification: feature
add feed — "add feed <url " / enumerated URLs the user wants added (one finding per URL) → classification: feature
add endpoint — "add endpoint <url " / explicit API path → classification: feature
fix bug — "fix X" / "X is broken" / "X returns null" → classification: bug
sniff — "sniff for new APIs" / "find new endpoints" / "discover more" → routes to the sniff subroutine in 1b.i
4. Each finding records the user's verbatim phrasing in evidence so the U4 scope confirmation modal shows the user what they actually wrote.
5. Edge cases — multi CLI asks split into two separate runs (out of scope for v0.2; ask the user to pick one). Ambiguous verbs ( update X without specifics) trigger an AskUserQuestion clarification rather than a guess.
Each finding emitted by 1b carries provenance: user ask (or provenance: sniff for findings produced by the sniff subroutine). Output flows into Phase 2 as the same structured finding list shape used by 1a.
1b.i. Sniff finding subroutine
Triggered when the parsing rubric tags any 1b ask as kind: sniff (phrases like "sniff for new APIs", "find new endpoints", "discover more endpoints in <site "). Sniff is opt in per run — never invoked unless the user named it. Skip this subroutine entirely when no sniff finding is present.
Step 1 — Resolve the target source URL. Read the target CLI's published manifest at ~/printing press library/library/<category /<slug /.printing press.json and extract source url (or spec url as fallback). Category was resolved in 1b step 2.
If neither field is set, ask the user inline:
"Sniff needs a target URL — paste the source site you want sniffed, or skip the sniff finding for this run?"
If the user skips, drop the sniff finding from the active list and continue with the other 1b findings. If the user pastes a URL, use it for steps 2 3.
Step 2 — Run crowd sniff first (fast, no browser). Replace <PRINTING PRESS BIN with the absolute path captured at setup:
crowd sniff queries npm SDKs and GitHub code search to discover candidate endpoints — no browser required. Typical runtime is under a minute.
Step 3 — Optional browser sniff (only when the user opted in deeper). When the user's ask explicitly named browser base