printing-press-publish
Publish a generated CLI to the printing-press-library repo
What this skill does
# /printing-press publish
Publish a generated CLI from your local library to the [printing-press-library](https://github.com/mvanhorn/printing-press-library) repo as a pull request.
```bash
/printing-press publish notion-pp-cli
/printing-press publish notion
/printing-press publish notion --from-polish
/printing-press publish notion --skip-live-test=auth-unavailable
/printing-press publish notion --blocked-api-journal notion
/printing-press publish
```
## Direct User Invocation Required
Publishing can fork `mvanhorn/printing-press-library`, push a branch, and open or
update a PR. Before setup or validation, check the invocation context. If this
skill was invoked as a chained continuation from `printing-press-polish`'s
Publish Offer, including an `AskUserQuestion` answer or auto-resolved polish
recommendation, stop immediately and tell the user to send
`/printing-press-publish <cli-name> --from-polish` in a fresh message. A fresh
user-authored request that explicitly asks to publish is sufficient; do not add
another confirmation prompt on top of a direct publish request.
If the fresh user-authored request includes `--from-polish`, record
`POLISH_HANDOFF=true` for the terminal-state step and ignore that marker when
resolving the CLI name. The marker is not a second confirmation and is not
passed to `cli-printing-press`; it only preserves standalone polish's old
post-publish retro offer after the fresh-turn publish completes.
If the request includes `--blocked-api-journal`, enter **Blocked API Journal
Mode** below instead of the normal printed-CLI publish flow. This mode may be
invoked from `/printing-press`'s hold-path menu after the user explicitly chose
"Add to blocked-API journal"; that parent menu choice is sufficient user
authorization for the public-library journal write. Do not require a second
fresh-turn invocation for this journal-only mode.
If the fresh user-authored request includes `--skip-live-test=<reason>`, record
the exact non-empty reason as `SKIP_LIVE_TEST_REASON` and remove the flag before
resolving the CLI name. This is the only supported escape valve for the
publish-time live test gate. Use it only for auth-unavailable, known upstream
outage, LAN-unreachable hardware APIs, or similarly concrete operator-approved
cases; never infer a skip from ordinary latency or from the presence of an
older Phase 5 marker.
The public library treats `library/<category>/<api-slug>/.printing-press.json`
and `manifest.json` as the source of truth for registry-display fields. Do not
edit `registry.json`, README catalog cells, or `cli-skills/pp-<api-slug>/SKILL.md`
in publish PRs; all three are bot-regenerated post-merge by the library's own
workflows. The library's `Fail on changes to generated artifacts` check in
`verify-library-conventions.yml` hard-fails any PR — fork or same-repo — whose
diff against base touches `registry.json` or `cli-skills/pp-*/SKILL.md`, so a
publish that includes either is pre-rejected before review.
The public library also owns per-CLI release accounting. Do not manually bump
`CHANGELOG.md`, `.printing-press-release.json`, or runtime `var version = ...`
for a publish PR. Fresh printed CLIs may include blank release-ledger skeletons;
the library's post-merge workflow assigns the final `YYYY.M.N` release and
stamps the runtime version after merge. When replacing an existing public
library CLI, preserve its existing release-ledger files so changelog history is
not lost in the reprint PR.
`blocked-apis.json` is different: it is a hand-maintained public-library journal,
not a generated registry surface. Journal-only PRs may edit `blocked-apis.json`
and must not stage `library/`, `registry.json`, README catalog cells, or
`cli-skills/`.
## Blocked API Journal Mode
Use this mode only when the invocation includes `--blocked-api-journal`. It
records a held `/printing-press` attempt whose blocker is likely to repeat for
other users until a machine or upstream issue changes.
Required fields from the caller:
- `slug`: canonical API slug, not the CLI binary name.
- `attempted_at`: `YYYY-MM-DD`.
- `verdict`: `hold`.
- `reason`: concise blocker reason, with no secrets, local paths, cookies,
tokens, or account-specific details.
- `blocking_issue`: Printing Press issue number if known, otherwise `null`.
- `permanent`: boolean.
If the caller did not provide one of these fields, infer only safe values from
the current run context. If `reason` is missing or vague, stop and ask for one
specific blocker sentence; do not write an unhelpful journal entry.
Run the normal Setup, Configuration, scoped clone cleanup, and GitHub auth
checks, then prepare the public-library clone exactly as the normal publish
flow does: fork if needed, ensure `upstream` points to
`mvanhorn/printing-press-library`, fetch `upstream`, and reset the clone to
`upstream/main` before editing.
Then update only `$PUBLISH_REPO_DIR/blocked-apis.json`:
```bash
cd "$PUBLISH_REPO_DIR"
if [ ! -f blocked-apis.json ]; then
printf '[]\n' > blocked-apis.json
fi
jq --arg slug "<api-slug>" \
--arg attempted_at "<YYYY-MM-DD>" \
--arg verdict "hold" \
--arg reason "<reason>" \
--argjson blocking_issue '<number-or-null>' \
--argjson permanent '<true-or-false>' '
(if type == "array" then . else [] end)
| map(select(.slug != $slug))
+ [{
slug: $slug,
attempted_at: $attempted_at,
verdict: $verdict,
reason: $reason,
blocking_issue: $blocking_issue,
permanent: $permanent
}]
| sort_by(.slug)
' blocked-apis.json > blocked-apis.json.tmp || {
rm -f blocked-apis.json.tmp
echo "Error: jq failed to update blocked-apis.json"
exit 1
}
if ! jq empty blocked-apis.json.tmp; then
rm -f blocked-apis.json.tmp
echo "Error: blocked-apis.json update produced invalid JSON"
exit 1
fi
mv blocked-apis.json.tmp blocked-apis.json
```
Create a journal branch and PR:
```bash
git checkout -B chore/blocked-api-<api-slug>
git add blocked-apis.json
git commit -m "chore(<api-slug>): journal blocked API"
git push --force-with-lease -u origin chore/blocked-api-<api-slug>
```
Open the PR against `mvanhorn/printing-press-library` with a body that includes:
- the held API slug and reason
- whether the block is permanent or tied to `blocking_issue`
- the expected Phase 0 behavior: future `/printing-press <api-slug>` runs warn
before repeating the attempt
After the PR is open, report the URL and stop. Do not continue into normal
printed-CLI package, live-test, registry, or skill-mirror steps.
## Setup
Before doing anything else:
<!-- PRESS_SETUP_CONTRACT_START -->
```bash
# 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 intRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.