[object Object]

← back to Cli Printing Press

feat(skills): add URL detection and disambiguation to printing-press skill (#73)

cac7eac23f70092027ad0c1ae58495ac11c5c1c6 · 2026-03-30 11:00:53 -0700 · Trevin Chow

When users pass a URL instead of an API name, the skill now probes the
content first (spec? HAR? website?) and asks a clear disambiguation
question via AskUserQuestion when the target is a website. Adapts
Phase 1 research and Phase 1.7 sniff gate to skip redundant steps
when the user has already chosen the website-sniff path.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit cac7eac23f70092027ad0c1ae58495ac11c5c1c6
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Mon Mar 30 11:00:53 2026 -0700

    feat(skills): add URL detection and disambiguation to printing-press skill (#73)
    
    When users pass a URL instead of an API name, the skill now probes the
    content first (spec? HAR? website?) and asks a clear disambiguation
    question via AskUserQuestion when the target is a website. Adapts
    Phase 1 research and Phase 1.7 sniff gate to skip redundant steps
    when the user has already chosen the website-sniff path.
    
    Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
 skills/printing-press/SKILL.md | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/skills/printing-press/SKILL.md b/skills/printing-press/SKILL.md
index 7e91fe36..12620200 100644
--- a/skills/printing-press/SKILL.md
+++ b/skills/printing-press/SKILL.md
@@ -25,6 +25,8 @@ Generate the best useful CLI for an API without burning an hour on phase theater
 /printing-press Discord codex
 /printing-press --spec ./openapi.yaml
 /printing-press --har ./capture.har --name MyAPI
+/printing-press https://postman.com/explore
+/printing-press https://postman.com
 /printing-press emboss notion
 /printing-press emboss notion-pp-cli
 /printing-press emboss ~/printing-press/library/notion-pp-cli
@@ -234,6 +236,36 @@ These do not need to be 200+ lines. Keep them dense, evidence-backed, and direct
 Before new research:
 
 1. Resolve the spec source.
+
+   **URL Detection** — If the argument contains `://`, it's a URL. Determine whether it's a spec or a website before proceeding.
+
+   **Step 1: Content probe.** Fetch the URL (light GET via `WebFetch`) and inspect the response:
+   - Check the `Content-Type` header and the first few lines of the body.
+   - If the fetch fails (timeout, 404, DNS error), skip to Step 2 — treat it as a website.
+
+   If the content starts with `openapi:`, `swagger:`, or is valid JSON containing an `"openapi"` or `"swagger"` key → it's a spec. Treat as `--spec` and proceed directly. No disambiguation needed.
+
+   If the content is a HAR file (JSON with `"log"` and `"entries"` keys) → treat as `--har` and proceed directly.
+
+   **Step 2: Disambiguation.** If the content is HTML or the probe failed, ask the user what they want. Extract the site name from the hostname (e.g., `postman.com` → "Postman", `app.linear.app` → "Linear"). Derive `<api>` from the site name using the same `cleanSpecName` normalization the generator uses.
+
+   Use `AskUserQuestion` with:
+   - **question:** `"What kind of CLI do you want for <SiteName>?"`
+   - **header:** `"CLI target"`
+   - **multiSelect:** `false`
+   - **options:**
+     1. **label:** `"<SiteName>'s official API"` — **description:** `"Build a CLI for <SiteName>'s documented API (e.g. REST endpoints, webhooks, OAuth)"`
+     2. **label:** `"The <SiteName> website itself"` — **description:** `"Build a CLI that does what the website does — I'll figure out the underlying API by exploring the site"`
+
+   The user can also pick the automatic "Other" option to describe what they're after in free text.
+
+   **Routing after disambiguation:**
+   - "<SiteName>'s official API" → use `<api>` as the argument, proceed with normal discovery (Phase 1 research, then Phase 1.7 sniff gate evaluates independently as usual)
+   - "The <SiteName> website itself" → use `<api>` as the argument, set `SNIFF_TARGET_URL=<url>`. Proceed to Phase 1 research. When Phase 1.7 is reached, skip the sniff gate decision and go directly to "If user approves sniff" (the user already approved in Phase 0 — do not re-ask). Use `SNIFF_TARGET_URL` as the starting URL for browser capture.
+   - "Other" → read the user's free-form response and adapt
+
+   **End of URL detection.** The remaining spec resolution rules apply when the argument is NOT a URL:
+
    - If the user passed `--har <path>`, this is a HAR-first run. Run `printing-press sniff --har <path> --name <api> --output "$RESEARCH_DIR/<api>-sniff-spec.yaml"` to generate a spec from captured traffic. Use the generated spec as the primary spec source for the rest of the pipeline. Skip the sniff gate in Phase 1.7 (sniff already ran).
    - If the user passed `--spec`, use it directly (existing behavior).
    - Otherwise, proceed with normal discovery (catalog, KnownSpecs, apis-guru, web search).
@@ -314,6 +346,8 @@ Resolve the API key gate (or skip it for public APIs) before moving to Phase 1.
 
 ## Phase 1: Research Brief
 
+**When `SNIFF_TARGET_URL` is set:** Skip the catalog check, spec/docs search, and SDK wrapper search — none of these exist for an undocumented website feature. Focus research on understanding what the site/feature does, who uses it, what workflows it supports, and what competitors offer similar functionality. The spec will come from sniffing in Phase 1.7.
+
 Before starting research, check if the API has a built-in catalog entry:
 
 ```bash
@@ -392,7 +426,7 @@ Suggested shape:
 
 ## Phase 1.7: Sniff Gate
 
-After Phase 1 research, evaluate whether sniffing the live site would improve the spec. Skip this gate entirely if the user already passed `--har` or `--spec` (spec source is already resolved).
+After Phase 1 research, evaluate whether sniffing the live site would improve the spec. Skip this gate entirely if the user already passed `--har` or `--spec` (spec source is already resolved). If `SNIFF_TARGET_URL` is set (user chose "The website itself" in Phase 0), skip the decision matrix and go directly to "If user approves sniff" — the user already approved, and `SNIFF_TARGET_URL` is the starting URL.
 
 **IMPORTANT:** When the decision matrix below says "Offer sniff", you MUST ask the user via `AskUserQuestion`. Do NOT silently decide to skip sniff because the docs look thorough — the user should make that call. The only case where you skip silently is "spec appears complete" (no gap detected).
 

← 91c87cde feat(cli): add Sources & Inspiration section to generated RE  ·  back to Cli Printing Press  ·  feat(skills): add browser-use version compatibility check to 89ca2ffd →