control-cli

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Control CLI

控制CLI

Use a repeatable local harness to exercise an interactive CLI instead of poking at it manually. First reuse the repo's own test/demo harness if it exists; otherwise assemble a temporary harness from standard local tools.
使用可重复的本地测试工具来测试交互式CLI,而非手动操作。首先复用仓库中已有的测试/演示工具(如果存在);否则使用标准本地工具组装临时测试工具。

What It Is Used For

适用场景

  • Reproducing CLI/TUI bugs with deterministic input.
  • Verifying keyboard flows, prompts, interrupts, resize behavior, and terminal layout.
  • Capturing before/after transcripts for bug fixes.
  • Profiling startup time, slow operations, hangs, or memory growth.
  • Recording a short terminal demo when output is easier to show than explain.
  • 利用确定性输入重现CLI/TUI bug。
  • 验证键盘流程、提示、中断、窗口调整行为和终端布局。
  • 捕获bug修复前后的会话记录。
  • 分析启动时间、缓慢操作、挂起或内存增长情况。
  • 当输出比解释更直观时,录制简短的终端演示。

Harness Loop

测试工具流程

  1. Identify the command under test and the smallest reproducible workspace.
  2. Discover existing local harnesses: package scripts, e2e tests, demo recorders, expect scripts, or PTY helpers.
  3. If no harness exists, launch the CLI in an isolated terminal session with deterministic env vars.
  4. Capture the current screen before interacting.
  5. Send one action at a time: text, Enter, arrows, Escape, Ctrl-C, resize.
  6. Wait for a concrete screen pattern or prompt before the next action.
  7. Save the transcript and any profile artifacts.
  8. Kill the session cleanly.
  1. 确定待测试的命令以及最小可复现工作区。
  2. 查找现有本地测试工具:包脚本、端到端测试、演示录制器、expect脚本或PTY辅助工具。
  3. 如果没有现成的测试工具,在隔离的终端会话中使用确定性环境变量启动CLI。
  4. 交互前捕获当前屏幕内容。
  5. 逐个发送操作:文本、回车键、方向键、Esc键、Ctrl-C、窗口调整。
  6. 等待出现具体的屏幕模式或提示后再执行下一个操作。
  7. 保存会话记录和所有分析产物。
  8. 干净地终止会话。

Harness Options

测试工具选项

  • Repo-native harness: prefer checked-in scripts because they know the app's startup, env, and prompts.
  • tmux
    : managed sessions,
    capture-pane
    ,
    send-keys
    , attach/detach.
  • PTY probe: use a short Python, Node, or Expect script when tmux is unavailable.
  • Runtime inspector: use Node or Bun inspector for CPU profiles, heap snapshots, and live evaluation.
  • Terminal recorder: use repo-local demo tools or asciinema-compatible tools when the user asks for a demo.
  • 仓库原生工具:优先使用已提交的脚本,因为它们了解应用的启动方式、环境和提示逻辑。
  • tmux
    :可管理会话,支持
    capture-pane
    send-keys
    、附加/分离会话等操作。
  • PTY探测脚本:当tmux不可用时,使用简短的Python、Node或Expect脚本。
  • 运行时检查器:使用Node或Bun检查器获取CPU分析报告、堆快照和实时评估结果。
  • 终端录制器:当用户需要演示时,使用仓库本地的演示工具或兼容asciinema的工具。

Minimal tmux Harness

极简tmux测试工具

bash
SESSION="cli-harness-$(date +%s)"
tmux new-session -d -s "$SESSION" -- <command-under-test>
tmux capture-pane -pt "$SESSION"
tmux send-keys -t "$SESSION" "help" Enter
tmux capture-pane -pt "$SESSION"
tmux kill-session -t "$SESSION"
For Node CLIs:
bash
NODE_OPTIONS="--inspect=127.0.0.1:0" tmux new-session -d -s "$SESSION" -- <node-cli-command>
Read the terminal output to find the inspector URL, then use Chrome DevTools-compatible tooling if profiling is needed.
bash
SESSION="cli-harness-$(date +%s)"
tmux new-session -d -s "$SESSION" -- <command-under-test>
tmux capture-pane -pt "$SESSION"
tmux send-keys -t "$SESSION" "help" Enter
tmux capture-pane -pt "$SESSION"
tmux kill-session -t "$SESSION"
针对Node CLI:
bash
NODE_OPTIONS="--inspect=127.0.0.1:0" tmux new-session -d -s "$SESSION" -- <node-cli-command>
读取终端输出找到检查器URL,若需要分析则使用兼容Chrome DevTools的工具。

Minimal PTY Harness

极简PTY测试工具

Use a PTY script when you need deterministic waits in a repo that does not have tmux or a demo harness. Keep it temporary unless the user asks to add a reusable test.
python
import os
import pty
import select
import subprocess
import time

master_fd, slave_fd = pty.openpty()
proc = subprocess.Popen(
    ["<command>", "<arg>"],
    stdin=slave_fd,
    stdout=slave_fd,
    stderr=slave_fd,
    close_fds=True,
)
os.close(slave_fd)

deadline = time.time() + 30
buffer = b""
while time.time() < deadline:
    ready, _, _ = select.select([master_fd], [], [], 0.25)
    if not ready:
        continue
    chunk = os.read(master_fd, 4096)
    buffer += chunk
    if b"<ready text>" in buffer:
        os.write(master_fd, b"help\n")
        break

print(buffer.decode(errors="replace"))
proc.terminate()
os.close(master_fd)
If the CLI needs richer terminal control, use
pty.fork()
or an existing PTY library.
当你需要在没有tmux或演示工具的仓库中实现确定性等待时,使用PTY脚本。除非用户要求添加可复用测试,否则将其作为临时脚本保留。
python
import os
import pty
import select
import subprocess
import time

master_fd, slave_fd = pty.openpty()
proc = subprocess.Popen(
    ["<command>", "<arg>"],
    stdin=slave_fd,
    stdout=slave_fd,
    stderr=slave_fd,
    close_fds=True,
)
os.close(slave_fd)

deadline = time.time() + 30
buffer = b""
while time.time() < deadline:
    ready, _, _ = select.select([master_fd], [], [], 0.25)
    if not ready:
        continue
    chunk = os.read(master_fd, 4096)
    buffer += chunk
    if b"<ready text>" in buffer:
        os.write(master_fd, b"help\n")
        break

print(buffer.decode(errors="replace"))
proc.terminate()
os.close(master_fd)
如果CLI需要更丰富的终端控制,请使用
pty.fork()
或现有的PTY库。

Profiling Recipes

分析方案

  • Startup regression: capture baseline and treatment startup timings under the same machine, env, and command.
  • Slow operation: start a CPU profile, perform the operation, stop the profile, and compare top self-time functions.
  • Memory leak: force GC if available, take a heap snapshot, perform the operation repeatedly, force GC again, and take another snapshot.
  • Hang: capture the screen, active handles/resources, and a stack/CPU sample before interrupting.
  • 启动回归测试:在相同机器、环境和命令下捕获基准版本和待测试版本的启动时间。
  • 缓慢操作分析:启动CPU分析,执行操作,停止分析,对比自耗时最高的函数。
  • 内存泄漏检测:若支持则强制垃圾回收,获取堆快照,重复执行操作,再次强制垃圾回收,然后获取另一个堆快照。
  • 挂起排查:捕获屏幕内容、活动句柄/资源以及堆栈/CPU样本,再中断进程。

Guardrails

注意事项

  • Prefer deterministic waits over sleeps. If you must sleep, explain why.
  • Do not send credentials or destructive commands into a controlled session.
  • Keep the harness in
    /tmp
    unless the repo already has a testing/demo harness.
  • Do not hard-code paths from another repository. Adapt commands to the current repo's scripts and runtime.
  • Clean up tmux sessions, temp dirs, inspector processes, and demo artifacts unless the user asks to keep them.
  • 优先使用确定性等待而非休眠。如果必须休眠,请说明原因。
  • 不要在受控会话中发送凭据或破坏性命令。
  • 除非仓库已有测试/演示工具,否则将测试工具放在
    /tmp
    目录下。
  • 不要硬编码其他仓库的路径。根据当前仓库的脚本和运行时调整命令。
  • 清理tmux会话、临时目录、检查器进程和演示产物,除非用户要求保留。