← back to Cli Printing Press
fix(skill): require interactive API key consent in Phase 0
d9801c33565e3add4c3f4a39499b43b8afb89c37 · 2026-03-28 14:56:19 -0700 · Matt Van Horn
Replace the non-blocking token detection ("Do not block the build on
token collection") with a mandatory interactive gate that always stops
to explain how the key will be used and gets explicit user consent
before proceeding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Files touched
A docs/plans/2026-03-28-007-fix-api-key-interactive-consent-plan.mdM skills/printing-press/SKILL.md
Diff
commit d9801c33565e3add4c3f4a39499b43b8afb89c37
Author: Matt Van Horn <mvanhorn@MacBook-Pro.local>
Date: Sat Mar 28 14:56:19 2026 -0700
fix(skill): require interactive API key consent in Phase 0
Replace the non-blocking token detection ("Do not block the build on
token collection") with a mandatory interactive gate that always stops
to explain how the key will be used and gets explicit user consent
before proceeding.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---
...-28-007-fix-api-key-interactive-consent-plan.md | 92 ++++++++++++++++++++++
skills/printing-press/SKILL.md | 20 ++++-
2 files changed, 109 insertions(+), 3 deletions(-)
diff --git a/docs/plans/2026-03-28-007-fix-api-key-interactive-consent-plan.md b/docs/plans/2026-03-28-007-fix-api-key-interactive-consent-plan.md
new file mode 100644
index 00000000..545df00e
--- /dev/null
+++ b/docs/plans/2026-03-28-007-fix-api-key-interactive-consent-plan.md
@@ -0,0 +1,92 @@
+---
+title: "fix: Require interactive API key consent in printing-press skill"
+type: fix
+status: completed
+date: 2026-03-28
+---
+
+# fix: Require interactive API key consent in printing-press skill
+
+## Overview
+
+The printing-press skill's Phase 0 silently proceeds when no API key is found, and never explains how a found key will be used. This must become an interactive gate: always stop, always explain, always get consent.
+
+## Problem Frame
+
+During a Linear CLI build, the skill detected `LINEAR_API_KEY` was empty and silently continued. The user had to interrupt and manually provide it. When a key *is* found, the skill should explain its usage (read-only smoke testing) and confirm before proceeding. The current instruction "Do not block the build on token collection" directly causes this.
+
+## Requirements Trace
+
+- R1. When no API key is detected, the skill MUST stop and ask the user to provide one
+- R2. When an API key IS detected, the skill MUST explain how it will be used (read-only live smoke testing only) and ask for confirmation before proceeding
+- R3. If the user cannot provide a key (R1) or declines usage (R2), warn that live smoke testing will be skipped but allow the build to continue
+- R4. The key must never be used for write operations — this should be stated in the consent explanation
+
+## Scope Boundaries
+
+- Only the SKILL.md Phase 0 token handling section changes
+- No Go code changes — the runtime already treats API keys as optional
+- No changes to Phase 5 (Optional Live Smoke) — it already gates on token availability
+
+## Context & Research
+
+### Relevant Code and Patterns
+
+- `skills/printing-press/SKILL.md` lines 182-192: Current Phase 0 token detection block
+- `internal/pipeline/runtime.go` line 24-25: `APIKey` is already optional in `VerifyConfig`
+- `internal/pipeline/runtime.go` line 81-84: Runtime already handles missing key gracefully (mock mode)
+- `internal/pipeline/runtime.go` line 342-346: Write commands are never tested live
+
+## Key Technical Decisions
+
+- **Interactive gate, not hard block**: The user confirmed that if they can't provide a key, the build should warn and continue rather than refuse entirely. This preserves the ability to generate CLIs without API access while making the consent explicit.
+- **Use AskUserQuestion**: The skill already has `AskUserQuestion` in its allowed-tools list. The consent flow should use it for a clean interactive experience.
+
+## Implementation Units
+
+- [x] **Unit 1: Rewrite Phase 0 token handling in SKILL.md**
+
+**Goal:** Replace the non-blocking token detection with an interactive consent flow
+
+**Requirements:** R1, R2, R3, R4
+
+**Dependencies:** None
+
+**Files:**
+- Modify: `skills/printing-press/SKILL.md`
+
+**Approach:**
+Replace lines 182-192 (the token detection block through "Do not block the build on token collection") with new instructions that define three paths:
+1. **Key found** → Explain to user: "Found `<ENV_VAR>` in your environment. This will be used for read-only live smoke testing in Phase 5 only — no write operations. OK to use it?" → If yes, proceed with key. If no, proceed without key + warning.
+2. **Key not found** → Ask user: "No API key detected for `<API>`. Provide one now for live smoke testing, or continue without it?" → If provided, proceed with key. If skipped, proceed without key + warning.
+3. **Warning path** → When continuing without a key, state clearly: "Live smoke testing (Phase 5) will be skipped. The CLI will still be generated and verified against mock responses."
+
+Remove the line "Do not block the build on token collection" and replace with "Always stop to ask about the API key before proceeding to Phase 1."
+
+**Patterns to follow:**
+- Phase 1.5 already has a mandatory stop gate ("REQUIRES USER APPROVAL before proceeding to Phase 2") — mirror that pattern
+- The skill already uses `AskUserQuestion` in its allowed-tools
+
+**Test scenarios:**
+- Happy path: Key found in env → skill explains usage and asks consent → user approves → build proceeds with key available for Phase 5
+- Happy path: Key not found → skill asks user to provide one → user provides it → build proceeds with key
+- Edge case: Key found → user declines usage → build proceeds without key, warning displayed, Phase 5 skipped
+- Edge case: Key not found → user says they don't have one → build proceeds without key, warning displayed, Phase 5 skipped
+- Edge case: Key not found → user provides an invalid-looking key (no validation needed, just accept it — Phase 5 will catch failures)
+
+**Verification:**
+- Reading the updated SKILL.md, the instructions clearly require stopping at Phase 0 for API key consent
+- The phrase "Do not block the build on token collection" no longer appears
+- All three paths (found+consent, not-found+provided, continue-without) are explicitly documented
+
+## System-Wide Impact
+
+- **Phase 5 dependency**: Phase 5 already checks for token availability, so no change needed there
+- **Codex delegation mode**: The consent flow happens before any delegation, so Codex mode is unaffected
+- **Emboss mode**: Emboss also runs Phase 0, so it will also get the consent flow — this is correct behavior
+
+## Risks & Dependencies
+
+| Risk | Mitigation |
+|------|------------|
+| User pastes API key in plaintext into chat (as happened in the session log) | The skill should instruct: "You can set it with `export ENV_VAR=...` or paste it here" — accept either path. Note: the session log key is already exposed; user should rotate it. |
diff --git a/skills/printing-press/SKILL.md b/skills/printing-press/SKILL.md
index 84231921..92f1b376 100644
--- a/skills/printing-press/SKILL.md
+++ b/skills/printing-press/SKILL.md
@@ -179,9 +179,9 @@ Before new research:
- `$PRESS_MANUSCRIPTS/<api>/*/research/*`
- `$REPO_ROOT/docs/plans/*<api>*` (legacy fallback)
3. Reuse good prior work instead of redoing it.
-4. Detect whether an API key is already available.
+4. **API Key Gate (MANDATORY STOP)** — Check for an API key and get explicit user consent before proceeding to Phase 1.
-Token detection:
+Token detection order:
- GitHub: `GITHUB_TOKEN`, `GH_TOKEN`, or `gh auth token`
- Discord: `DISCORD_TOKEN`, `DISCORD_BOT_TOKEN`
- Linear: `LINEAR_API_KEY`
@@ -189,7 +189,21 @@ Token detection:
- Stripe: `STRIPE_SECRET_KEY`
- Generic: `API_KEY`, `API_TOKEN`
-If a token is available, ask once whether to use it for read-only live testing at the end. Do not block the build on token collection.
+**If a token IS found**, stop and explain:
+> Found `<ENV_VAR>` in your environment. This key will be used **only** for read-only live smoke testing in Phase 5 — listing, fetching, and health checks. It will never be used for write operations (create, update, delete). OK to use it?
+
+- If the user approves → proceed with the key available for Phase 5.
+- If the user declines → proceed without the key and display: "Live smoke testing (Phase 5) will be skipped. The CLI will still be generated and verified against mock responses."
+
+**If no token is found**, stop and ask:
+> No API key detected for `<API>`. You can provide one now for read-only live smoke testing in Phase 5, or continue without it.
+>
+> Set it with `export <ENV_VAR>=<your-key>` or paste the key here.
+
+- If the user provides a key → proceed with the key available for Phase 5.
+- If the user declines → proceed without the key and display: "Live smoke testing (Phase 5) will be skipped. The CLI will still be generated and verified against mock responses."
+
+Always resolve the API key gate before moving to Phase 1.
## Phase 1: Research Brief
← 4120dfcb feat(pipeline): move mutable runs into scoped runstate (#30)
·
back to Cli Printing Press
·
feat(templates): add flag suggestions, sync NDJSON events, a 03882623 →