| name | terminal-cli-dev |
| description | CLI/terminal/console/PTY/ANSI/keyboard/TUI design, implementation, review, debugging, testing, or shipping. Owns the command/subcommand/flag/help contract (owned here even when nothing is rendered), with defaults/output/exit/action/confirmation/progress/recovery, plus layout, input, accessibility, and real-terminal evidence. Triggers include "命令行/TUI 界面怎么做", "CLI 界面怎么写", "refactor a terminal command / TUI view". Skip only parser/library/tooling internals owned by a language skill ("用 Python 写个命令行工具" → python-service-dev, Go CLI → go-microservice-dev, Node.js CLI → nodejs-service-dev) that provably preserve every user-facing command tree, default/action path, help/output/exit behavior, confirmation, progress, and recovery path; compose both owners when user-visible semantics change. |
Terminal CLI Dev
Use this skill for terminal and command-line product surfaces. It owns the user-facing command/subcommand/flag/default/help/output/exit/action/confirmation/progress/recovery contract, plus implementation mechanics for text UIs, console workflows, ANSI-rendered output, PTY-backed interaction, keyboard input, terminal capability handling, and real terminal verification. A language skill may own parser or library mechanics, but those mechanics do not displace this user-visible contract. This skill does not own web browsers, mobile apps, mini-program hosts, backend services, or product design judgment.
Routing
- Use
product-rd-workflow first when the work spans product intent, design, implementation, testing, release, or postmortem follow-up.
- A user-facing command/subcommand/flag/default/help/output/exit/action/confirmation/progress/recovery path is a terminal surface even when it emits only plain text and never enters an alternate screen.
- Use
product-ui-ux-design before or alongside coding for that user-facing terminal surface: hierarchy, density, interaction model, copy, states, accessibility, consequence, recovery, and visual/textual acceptance.
- Use
testing-strategy to choose unit, snapshot, PTY, integration, and real-terminal evidence; return here for terminal-specific implementation mechanics.
- Use
defect-diagnosis first for rendering regressions, input bugs, flicker, selection/copy issues, broken resize behavior, color/readability defects, or flaky terminal tests.
- Use
platform-observability for telemetry/log schema and platform-release-engineering for rollout of behavior-changing defaults, persisted settings migrations, or terminal capability fallbacks. Do not treat CLI package distribution, installer, or updater mechanics as covered unless the release skill has explicit terminal distribution guidance.
Core Workflow
Before editing a user-facing command tree, flag/default/action path, help/output/exit behavior, confirmation/progress/recovery flow, terminal UI code, output formatting, keyboard handling, PTY integration, layout, color/theme logic, or terminal tests, complete enough analysis and planning for the change to be reviewable. Scale the plan to risk: a small copy or formatting change can use a short note; a new command path, changed default, interactive surface, renderer, input mode, terminal capability change, high-risk action, release behavior, or bug fix needs explicit scenarios, target terminal environments, verification commands, and stop conditions.
Repo-local agent contracts (AGENTS.md at the repo root and in source directories) are part of the delivery contract: when a change moves a stable boundary, generated surface, workflow, or directory-local rule, update the nearest contract in the same MR and keep coverage in sync per product-rd-workflow's spec / repo-contract sync gate.
When checking a terminal/CLI project against team standards, split conformance into deterministic and agent review evidence. Deterministic checks cover exit-code conventions (0 on success / non-zero on failure; os.Exit/process.exit/sys.exit only in the entrypoint, not the library layer), stdout-vs-stderr routing (primary/machine-readable output to stdout, logs/diagnostics/progress/prompts to stderr), --help/--version/--json (or --plain) flag presence in the parser tree, signal-handler registration, NO_COLOR/isatty handling, and absence of hardcoded ANSI escape literals outside the rendering module. Agent review checks cover terminal-state restoration on every exit path, capability-fallback completeness, the NO_COLOR/non-TTY/TERM=dumb/--no-color color-disable matrix, prompt-only-on-TTY (--no-input honored), error actionability, and whether tests prove real-terminal behavior rather than only string snapshots. For the per-language deterministic executor list (Go errcheck/forbidigo, Rust Clippy print_stdout/exit/unwrap_used, Ruff T201/PLR1722) and the shipped client-terminal-ansi-check.py (CB-1: flags hardcoded ANSI escape literals outside an allowlisted rendering module), see testing-strategy/references/fitness-functions.md §4.1.3 (client language-basics; spec 006). CLI/TUI invariants have almost no off-the-shelf CLI-aware linter, so most of this contract is agent-review plus a few repository checks — prefer a capability-aware lib over hand-emitted escapes.
-
Classify the terminal surface.
- One-shot CLI output, interactive prompt, full-screen TUI, embedded terminal panel, log/status stream, diff/code viewer, installer/updater, or background task display.
- Output-only, input-driven, mouse/selection-aware, PTY-backed, or mixed.
- Plain text, ANSI-styled, hyperlink-capable, alternate-screen, scrollback-preserving, or terminal-query-dependent.
-
Define the terminal contract before coding.
- Supported terminals, shells, OS families, remote/headless behavior, CI behavior, and fallback mode.
- Whether the feature requires a TTY, raw mode, cursor control, bracketed paste, mouse reporting, focus reporting, hyperlinks, truecolor, or scrollback control.
- Behavior when capabilities are missing, disabled by user preference, blocked by a multiplexer, proxied through a remote shell, or unavailable in CI.
- State ownership for input focus, modal overlays, selection, scroll position, unseen output, pending operations, and resize recovery.
- For every user-facing terminal/CLI contract change—including command tree, subcommand, flag/default/action path, help/output/exit behavior, confirmation, progress, or recovery—load
../product-ui-ux-design/references/delivery-contract.md and consume either its full Design brief + Phase 0 or its valid low-risk copy-only record + lightweight Phase 0 before coding. Only parser/library internals that preserve all of those user-visible semantics may mark UI/UX not-applicable, with the preservation evidence recorded. The lightweight path checks semantics, accessible text, localization/width, cell extent, and target-terminal render without inventing unrelated matrices; risk-bearing copy or behavior uses the full path. For full slices, map structure, state/adaptation matrices, behavior and criteria to the screen buffer/lifecycle; record terminal classes, dimensions, input/capability modes, resize/scrollback/selection, and preserved state.
- Before the first implementation edit, add the canonical
client_entry defined there: local rule identifier or short quote and implementation decision, target surface/runtime, planned run/capture command, and behavior that must remain unchanged.
-
Render by terminal cells, not string length.
- Measure display width with ANSI-stripped, Unicode-aware logic. Cover combining marks, emoji, East Asian width, zero-width code points, variation selectors, and control characters.
- Preserve grapheme and wide-character boundaries when wrapping, truncating, slicing, highlighting, cursoring, or copying. Never split the trailing cell of a wide character into visible content.
- Keep a screen-buffer model for interactive surfaces: cell char, style, width, hyperlink, selectable/non-selectable status, soft-wrap continuation, and damage bounds.
Reference Loading
references/input-state-machines.md — full contracts for paste/clipboard ingress, configurable keybindings, and modal text editing. Load before touching any of those input surfaces (Core Workflow step 5).
references/streaming-rich-output.md — full contract for streaming rich/markdown output into scrollback, including the untrusted-content sanitization security boundary. Load before implementing or reviewing any streaming-rich-output path (step 6).
references/terminal-side-channels.md — per-surface contracts for guidance chrome, status lines, progress/notifications, title/chrome metadata, sleep leases, delay/backgrounding, and session-background shortcuts. Load before touching any side-channel surface (step 6).
Non-Negotiable Rules
- Do not treat terminal strings as layout truth; terminal cells are the layout truth.
- Do not ship a terminal UI that only works in one color depth, one width, or one local shell unless the product explicitly scopes it that way.
- Do not rely on color alone for warnings, errors, selection, current match, disabled state, or destructive action confirmation.
- Do not claim terminal behavior is verified from static code inspection or string snapshots when the change affects cursoring, focus, raw mode, resize, scrollback, selection, or color.
- Do not let generated chrome, gutters, hidden prompts, or status lines pollute copied user content.
- Do not destroy scrollback or clear the screen as a side effect of refresh unless that behavior is part of the command contract and has a fallback.
- Do not leave the terminal in raw mode, alternate screen, hidden cursor, mouse reporting, bracketed paste, focus reporting, modified keyboard mode, or non-default style state after normal exit, error, interrupt, termination signal, child crash, resize race, unmount, parent cancellation, or crash recovery.
- Do not crash or dump a traceback when a downstream consumer closes the pipe early (piping to
head, or to a pager then quitting): a write to a closed stdout/stderr raises EPIPE / BrokenPipeError. Exit quietly with the conventional status — in Python restore the default SIGPIPE disposition (signal(SIGPIPE, SIG_DFL)) or handle BrokenPipeError at the top level; in Node/JS catch the stream write EPIPE / ERR_STREAM_DESTROYED error (do not rely on a portable default-signal reset). Do not let it surface as an error stack to the user. (POSIX SIGPIPE / write(2) EPIPE.)
- Do not write a durable file output in place when an interrupt (Ctrl-C /
SIGTERM) or crash mid-write would leave a truncated or corrupt file: write to a temp file in the same directory (same filesystem — a cross-filesystem rename fails EXDEV and a copy-across-volume move is not atomic), flush and close it, then rename(2) onto the target — atomic replace on POSIX; on Windows use MoveFileEx(..., MOVEFILE_REPLACE_EXISTING) or the runtime's atomic-replace API. The reader then sees either the old file or the complete new one, never a half-written one. Streaming stdout is exempt; this is about durable file artifacts the command promises to produce.