---
name: cli-installer-ux
description: Design and harden compact, useful CLI installers, updaters, setup wizards, and command output surfaces without leaking debug logs or machine JSON into human UX.
license: MIT
tags: [cli, installer, updater, terminal, ux, testing, node, shell]
agents: [claude-code, codex, autojack]
category: terminal
metadata:
version: "1.0.0"
capabilities:
network: true
filesystem: readwrite
tools: [Bash, Read, Edit, Write]
resources:
- path: references/cli-ux-checklist.md
type: file
- path: examples/compact-install.sh
type: file
- path: examples/clack-ui.ts
type: file
- path: examples/cli-output.test.ts
type: file
---CLI Installer UX
Use this when a project needs a command-line installer, updater, setup wizard, doctor command, or other user-facing CLI surface that should feel compact and intentional while keeping diagnostics, subprocess logs, and machine output out of the default path.
When to use
- The user asks for a CLI installer, upgrader, first-run setup flow, doctor command, or command catalog.
- A CLI currently dumps raw JSON, structured logs, child-process output, stack traces, or verbose internals during normal success paths.
- A project needs both human output and parseable
--jsonoutput. - An installer must support interactive terminals, redirected stdout, CI/headless agents, and quiet or verbose modes.
Workflow
- Inspect the current command surfaces before editing. Find entrypoints, shell installers, update commands, logging helpers, subprocess calls, and tests. Capture which commands are human-facing, which are machine-facing, and which mutate user state.
- Define the output contract. Human mode gets compact branded status, plan-first summaries, bounded tables, and explicit next actions. Machine mode gets strict JSON only. Errors go to stderr. Internal diagnostics stay behind verbose flags or log files.
- Build tiny shared UI primitives rather than one-off strings: theme/color detection, ASCII fallback, badges, key/value rows, list truncation, safe text escaping, task spinners, and success/error summaries.
- Keep installers plan-first. Print platform, runtime, install path, storage path, current version, target version, install state, and release notes before writing anything. Support
--dry-run,--yes,--quiet,--verbose, and--noteswhere they make sense. - Contain subprocess noise. Route child stdout/stderr to a temp log during success paths. Show a short tail only on failure, or in explicit verbose mode when the output is useful. For library calls that log internally, wrap them in the project's log-suppression helper.
- Treat interactivity as a capability, not an assumption. If stdin is not a TTY but
/dev/ttyis available, attach the guided flow there. If no TTY exists, defer the wizard and print the exact command to resume. Do not execute mutating updates from a non-TTY session unless an explicit yes flag is present. - Add passive update notices only to human output. Keep them compact: current to latest, run command, disable command. Never append notices to JSON, markdown, or other machine-readable output.
- Make review and repair flows safe by default. Summarize counts first, hide long diagnostic detail until review/advanced/verbose modes, recommend non-destructive choices first, and show restore commands after backup-style actions.
- Test the transcript as a public API. Cover human snapshots with color off, JSON parseability, stderr cleanliness, suppressed child noise on success, log tails on failure, non-TTY behavior, quiet output, verbose output, command suggestions, and update notice gating.
Output standards
- Default output should fit in a short terminal viewport and answer: what happened, what changed, what needs attention, and what to run next.
--jsonoutput must be parseable with no banners, update notices, warnings, or trailing prose.- Normal successful commands should not print server logs, storage warnings, dependency install transcripts, stack traces, or raw API payloads.
- Every interactive prompt should have a safe default and a clear recovery command if skipped.
Anti-patterns
- Printing debug logs because they are technically useful.
- Letting passive notices contaminate JSON or other machine-readable streams.
- Showing full subprocess output on success.
- Using animation without a deterministic non-TTY fallback.
- Repeating large brand marks throughout a transcript.
- Treating
--verboseas the default user experience. - Performing destructive or persistent changes before showing the plan and asking or honoring an explicit yes flag.
- Hiding failures completely; suppress success noise, but surface failure tails and actionable next steps.