Skip to content

fix(cli): never prompt or auto-install when nobody is at the terminal - #6617

Merged
jrusso1020 merged 2 commits into
mainfrom
fix/cli-agent-mode-prompts
Oct 28, 2026
Merged

jrusso1020 merged 2 commits into
mainfrom
fix/cli-agent-mode-prompts

Conversation

@jrusso1020

@jrusso1020 jrusso1020 commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

What

Second of four stacked PRs (base: #6616). Fixes the two P0 findings for agent and CI runs:

  • publish and upgrade called the confirmation prompt with no terminal check. With stdin from /dev/null, publish exited 13 after drawing a half prompt; with an open pipe it hung. Unattended and without --yes, both now exit 2 before doing any work, with the explanation on stderr naming --yes (upgrade also names --check).
  • The background auto-install ran by default for global installs and was not gated on agents or TTY. It no longer starts in an unattended run. The Update available ... Run: npm install -g ... notice is no longer shown while an install for that version is pending, or in an unattended run.

Why

An agent that runs hyperframes publish should get a fast, clear "pass --yes" instead of a hang or an exit 13. An agent session should not install software in the background.

Related work

Stack: #6616 (factory, isUnattended()) → this PR → help and nags → JSON envelope.

How

  • New packages/cli/src/ui/prompts.ts is the only module allowed to import @clack/prompts. A lint rule (no-restricted-imports) bans static imports elsewhere, and the contract test also fails on a dynamic import("@clack/prompts") outside it. All 18 files that used clack now import the wrapper, a mechanical swap.
  • The wrapper's confirm, select, text and password throw a usage error (exit 2) when isUnattended(), so no future command can prompt without a terminal even if it forgets to check. Its spinner prints only the final message, as a plain line on stderr, when unattended. confirmationRequired(command, hint) is the shared "pass --yes" error.
  • init, feedback, catalog and cloud delete now decide whether to ask with isUnattended() instead of their own TTY checks.
  • autoUpdate.ts: isAutoInstallDisabled() includes isUnattended(). updateCheck.ts: the notice is suppressed when unattended or when pendingUpdate is for the advertised version; CI is read with the shared isCI() (any value but false or 0).
  • HYPERFRAMES_NO_UPDATE_CHECK, HYPERFRAMES_NO_AUTO_INSTALL and NO_COLOR keep working as before.

Behavior for a person at a terminal is unchanged: prompts, spinners and the auto-install work as before.

Test plan

  • Unit tests added/updated: ui/prompts.test.ts; contract test cases for publish and upgrade without --yes and for the clack import rule; autoUpdate.test.ts (unattended skips the install), updateCheck.test.ts (no notice when unattended or while an install is pending). Tests that drive prompts or spinners now mock attendance explicitly, so they pass the same way inside an agent and in CI.
  • CLI unit suite passes locally, also with a clean CI=true environment for the touched files
  • typecheck, oxlint, oxfmt --check, fallow audit, comment ratchet pass
  • Manual testing performed (below)
  • Documentation updated: "Unattended runs never prompt" and version notices in docs/packages/cli.mdx, publish and upgrade flag notes
  • Comments follow CONTRIBUTING.md "Comments"

Manual run of the built CLI in a project directory, CLAUDECODE=1, stdin from /dev/null:

$ hyperframes publish </dev/null
# before: exit 13; stdout had the lint summary, the consent text and a half-drawn
#         "Publish this project? Yes / No" prompt with cursor escape codes
# after:  exit 2, stdout empty, stderr (after the one-time telemetry notice a fresh HOME prints):
hyperframes publish asks for confirmation, and this run cannot answer a prompt.
Pass --yes to publish without asking.

🤖 Generated with Claude Code

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits

The prompt wrapper, confirmationRequired() and the auto-install gate look right, and the publish/upgrade contract cases pass locally. One blocker comes from #6616 and surfaces here: people in Cursor or Windsurf terminals, and in Replit shells, count as unattended. That makes "Behavior for a person at a terminal is unchanged" false (inline). Fixing isUnattended() in #6616 clears it.

— Genesis

Comment thread packages/cli/src/commands/publish.ts Resolved
@jrusso1020
jrusso1020 force-pushed the fix/cli-agent-mode-prompts branch from 6e43f2d to 975d2c9 Compare October 28, 2026 05:52
heygengenesis[bot]
heygengenesis Bot previously approved these changes Oct 28, 2026

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE — 1 resolved, 0 open, 0 new · 6e43f2d → 975d2c9. This PR is stacked, so CI comes from the manual ci.yml run on the top of the stack (edc4df1, green) and my local run.

— Genesis

Base automatically changed from fix/cli-agent-mode to main October 28, 2026 07:08
@jrusso1020
jrusso1020 dismissed heygengenesis[bot]’s stale review October 28, 2026 07:08

The base branch was changed.

@mintlify

mintlify Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
hyperframes 🟢 Ready View Preview Oct 28, 2026, 7:35 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 129 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • seqplainkeys-none-pct-r0-root-z100: tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo false, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true / tracking 0.06, pressJump 0, drop 0, reload 0, render 0.03, renderKey -, undo true, teleport true

jrusso1020 and others added 2 commits October 28, 2026 07:29
publish and upgrade called the confirmation prompt with no terminal check.
With stdin from /dev/null, publish exited 13; with an open pipe it hung.
Unattended and without --yes, both now exit 2 before doing any work, and
stderr names --yes (upgrade also names --check).

All prompts and spinners now go through ui/prompts.ts, the only module allowed
to import @clack/prompts (a lint rule and a contract test enforce it). Its
confirm, select, text and password refuse to prompt in an unattended run, and
its spinner prints only the final line, on stderr. init, feedback, catalog and
cloud delete decide whether to ask with isUnattended() instead of a TTY check
of their own.

The background auto-install no longer starts in an unattended run, and the
update notice ("Run: npm install -g ...") is not shown while an install for
that version is pending. CI now counts as set for any value but "false" or "0".

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
…ugh isAgentDriven

Attendance now reads isAgentDriven(), so that is what the catalog tests stub to
stay independent of the agent running the suite.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE · re-approval after the rebase onto main · 975d2c9 → 49624ea

The patch is byte-identical (git diff d02c0e7 975d2c9 = git diff origin/main 49624ea), and none of main's newer CLI commits (#6618, #6627) touch prompts or clack. CI on this head passed. The non-required CLI: npx shim (windows-latest) job hit its 10-minute install timeout and passed on rerun.

— Genesis

@jrusso1020
jrusso1020 added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 0bdc128 Oct 28, 2026
114 of 115 checks passed
@jrusso1020
jrusso1020 deleted the fix/cli-agent-mode-prompts branch October 28, 2026 08:45

This branch was successfully deployed

1 active deployment
staging - docs — 49624ea9 Deployed Oct 28, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant