Skip to main content

tui-verify-change

Verify a change to Warp's headless TUI front-end (crates/warp_tui) by running it — locally via ./script/run-tui, or in a headless cloud runner via a WARP_API_KEY dogfood build — and reading the rendered screen back (under tmux when it's installed, otherwise directly). Use whenever you change TUI UI, rendering, input, or behavior and need to confirm the real on-screen result.

소스 정보

저장소
warpdotdev/warp
최근 소스 활동
2026년 7월 27일 17:38
감지된 SKILL.md 언어
영어
스타
65,700
포크
5,704

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
tui-verify-change
description
Verify a change to Warp's headless TUI front-end (crates/warp_tui) by running it — locally via ./script/run-tui, or in a headless cloud runner via a WARP_API_KEY dogfood build — and reading the rendered screen back (under tmux when it's installed, otherwise directly). Use whenever you change TUI UI, rendering, input, or behavior and need to confirm the real on-screen result.
# tui-verify-change Verify a change to Warp's **headless TUI** front-end (`crates/warp_tui`, and the cell-grid element library in `crates/warpui_core/src/elements/tui`) by running it and reading back the actual rendered screen. The whole point: **the TUI is a console program, so you can run it in a real terminal and read the actual rendered screen straight back.** When `tmux` is available it's the ideal driver — you run the TUI in a tmux pane, drive it with `tmux send-keys`, and read the frame back with `tmux capture-pane` — but tmux is **not required**: if it isn't installed you can still run and observe the TUI directly (see **If tmux isn't installed** under Step 2). Either way you (the agent) see the actual screen text — no `computer_use`, no real display, no cloud screenshot agent, and no relying on a separate watcher's description of what it saw. (Contrast the GUI-only `gui-onboarding-verification-skill`, `gui-integration-test`, `gui-integration-test-video`, and the `computer_use` / `verify-ui-change-in-cloud` flow.) This is the fast, preferred way to confirm a TUI change end-to-end. This skill covers the **manual live-run** verification. For a durable regression that runs in CI, also add a render-to-lines unit test per `tui-testing` — the two are complementary: the live run confirms real behavior; the snapshot test locks it in. ## When to use - You changed anything a TUI user sees or interacts with: an element/layout in `crates/warpui_core/src/elements/tui`, a TUI view/screen in `crates/warp_tui` (transcript, input, zero state, login placeholder, etc.), TUI keybindings, or TUI rendering/behavior. - You want to confirm the *actual* rendered result, not just that it compiles or a unit test passes. If your change is GUI-only (`app/`, WarpUI pixel `Element`/`View`), this is the wrong skill — use the GUI verification path instead. ## Local vs cloud verification (pick your context first) *How* you build, run, and log in depends on **where you're running**. Decide this up front — it determines whether you use `./script/run-tui` or the `WARP_API_KEY` path below. - **Local context** — you're working in a local dev checkout, typically alongside the user. Just run **`./script/run-tui`** directly: it builds `warp_tui` and runs it, selecting the internal `local` channel when the `warp-channel-config` generator is available and falling back to `warp-tui-oss` otherwise. **Do not reach for `WARP_API_KEY`** here — it's generally **not set** in a local environment, and you don't need it: a local build reaches the authenticated state through the normal interactive device-auth login flow (or you're already signed in on this machine). The non-interactive `WARP_API_KEY` login below is a *cloud-runner* affordance, not a local one, so don't let a missing key block you locally. - **Cloud context** — you're a headless cloud agent (e.g. the factory-client runner) with no browser for device-auth, so reaching a **signed-in** surface relies on the non-interactive `WARP_API_KEY` already in the environment. That does **not** mean bypassing `./script/run-tui`: when the `warp-channel-config` generator is available, `./script/run-tui` selects the internal `local` binary; otherwise it falls back to `warp-tui-oss`. Both accept the inherited `WARP_API_KEY`, so prefer the maintained runner unless you need a specific binary or profile. In the cloud, the inherited key signs you in without the browser device-auth flow. The logged-**out** surface (the `Sign in to continue` placeholder and any pure element/layout) needs neither login path — a plain OSS build is enough in either context. ## Step 1 — Build the TUI Always build with a small job count so the large `warp` dependency tree doesn't OOM the machine: ```bash cd <warp-repo-root> CARGO_BUILD_JOBS=2 cargo build -p warp_tui --bin warp-tui-oss ``` - `warp-tui-oss` is the OSS channel binary and the safest default (no internal `warp-channel-config` generator required). `./script/run-tui` does the equivalent, selecting the internal `local` binary when the generator is available and falling back to `warp-tui-oss` otherwise. - Fix all compile errors before running (see `fix-errors`). The first build of this tree takes a while; **incremental rebuilds after a one-line change are fast (~10s)**, so the edit → rebuild → re-capture loop below is quick. ### Logged-in vs logged-out (important) The OSS build starts **logged out** and stops at a `Sign in to continue` placeholder (it drives a device-authorization login flow that needs a browser). The login-gated root has three pre-session states you may see: - `AwaitingLogin` → a centered placeholder that reads `Sign in to continue`, then `Opening your browser…` (or, once the device code is known, `Open <uri> in your browser` and `and enter code: <code>`). It does **not** show a Ctrl-C hint. - `LoggedIn` → briefly `Starting terminal…`, then the **zero state** (`Warp Agent` + version, a "What's new" list, and the project context section) with the input view. - `Failed` → `Login failed: <message>` followed by `Press Ctrl-C to exit.` (Exact strings live in `crates/warp_tui/src/ui.rs` — verify against it if you're asserting on placeholder text.) So: if your change is on the **login placeholder** or a pure element/layout, the logged-out OSS build is enough. If your change is in the **live terminal / transcript / input** surface, you must reach the authenticated state (see the next section), or your change will sit behind the login gate and you'll only ever see `Sign in to continue`. ### Logging in non-interactively (`WARP_API_KEY`) — cloud context **This is the cloud path.** In a local checkout, skip it: run `./script/run-tui` and log in interactively (see **Local vs cloud verification** above), since `WARP_API_KEY` usually isn't set locally. Use the flow here when you're a headless cloud runner where the key *is* set and there's no browser for device-auth. You can reach the authenticated (`LoggedIn`) state headlessly — no browser, no device-auth flow — by launching any TUI channel binary with a `WARP_API_KEY` in the environment. This is the fast way to verify live terminal/transcript/input changes. Key constraints: - **All channels are supported.** API-key login works with `warp-tui-oss` as well as the Preview, Dev, Local, and Stable binaries. - **The key must already be in the environment.** In a sandbox where `WARP_API_KEY` is set, a freshly started `tmux` server inherits it. Never echo, print, or inline the secret value in a command — just rely on the inherited environment variable. (`--api-key <key>` on the command line also works but would expose the secret, so prefer the env var.) ```bash cd <warp-repo-root> CARGO_BUILD_JOBS=2 cargo build -p warp_tui --bin warp-tui-oss tmux kill-session -t tuicheck 2>/dev/null # WARP_API_KEY is inherited from the environment by the new tmux server. tmux new-session -d -s tuicheck -x 120 -y 40 './target/debug/warp-tui-oss' sleep 20 # login + session start tmux capture-pane -t tuicheck -p # expect the logged-in zero state ``` When it works you'll see the **zero state** (`Warp Agent` + input view + model selector) instead of `Sign in to continue`, and you can `send-keys` a real prompt and read the agent's reply back with `capture-pane`. (This login path was added in warpdotdev/warp#13583.) ## Step 2 — Run under tmux and read the frame back The TUI needs a **real interactive PTY** — a tmux pane is exactly that, and it lets you both send input and read the rendered screen back as text. Start the TUI in a detached session with an explicit size (don't skip `-x`/`-y`; a degenerate 1-row pane renders nothing useful): ```bash cd <warp-repo-root> tmux kill-session -t tuicheck 2>/dev/null # clear any prior run tmux new-session -d -s tuicheck -x 120 -y 40 './target/debug/warp-tui-oss' sleep 1 # let it draw + probe the terminal tmux capture-pane -t tuicheck -p # <-- the rendered screen, as text ``` `tmux capture-pane -p` prints the pane's current contents (the TUI's alternate screen) to stdout, so **you read the real frame directly** and assert on it. Add `-e` to include ANSI escape sequences when you need to check colors/styles: ```bash tmux capture-pane -t tuicheck -p -e # includes color/style escapes ``` Drive interactions with `tmux send-keys`, sleeping to let the UI settle, then capture again. For example (type a line, submit it, wait, then read the screen): ```bash tmux send-keys -t tuicheck "What is 2+2? Answer in one short sentence." && \ sleep 1 && tmux send-keys -t tuicheck Enter && sleep 5 && \ tmux capture-pane -t tuicheck -p -e ``` Send special keys by name (`Enter`, `Escape`, `C-c` for Ctrl-C, `Up`/`Down`). When done, tear the session down: `tmux kill-session -t tuicheck`. ### If tmux isn't installed `tmux` is the preferred driver because it gives you programmatic `send-keys` + `capture-pane`, but it is **not** a hard requirement — never block verification just because tmux is missing. Check with `command -v tmux`; if it's absent, fall back: - **Local context:** the simplest path is to run `./script/run-tui` directly in a real terminal and read the rendered output yourself — you already have a PTY. When you're working alongside the user, you can also have them run it and report what renders. Installing tmux is optional, not a prerequisite. - **Cloud / no-tmux context:** run the built binary inside another PTY wrapper so you can still capture output — e.g. `script` (util-linux): `script -qe -c './target/debug/warp-tui-oss' /tmp/tui.log`, then read `/tmp/tui.log`. If tmux is installable in your environment (`apt-get install -y tmux`) and that's cheaper, do that and use the flow above instead. If none of these work, run the binary directly, capture whatever output you can, and **say so** in the PR/thread rather than implying a tmux-driven capture. Everything else in this skill (what to look for, the snapshot test, the evidence) is identical whether or not tmux drove the run. ### Iterate loop Because incremental rebuilds are ~10s, iterate tightly: edit the TUI code → `cargo build -p warp_tui --bin warp-tui-oss` → `tmux kill-session` + restart the session → `capture-pane` and compare. Verified before/after example: changing the login placeholder string and rebuilding flips the captured line from `Sign in to continue` to the new text, visible directly in `capture-pane` output. ## Step 3 — Check the captured frame against your change You have the real screen text, so verify it yourself: grep/scan the `capture-pane` output for the **exact string or layout** your change should produce, and diff the before/after captures. No watcher interpretation needed — if the expected text isn't in the capture, the change isn't rendering. ## Pitfalls (learned hands-on) - **Run it in a real terminal / tmux pane** (a PTY), and drive + capture it via tmux as above. - **If it exits (code 101) right after the first frame instead of staying up:** don't assume it's a terminal/stdin problem — **check the TUI log first**: `tail -40 ~/.local/state/warp-terminal-tui/oz/warp-tui.log`. One cause seen in the headless OSS/logged-out sandbox build is a debug-only binding-validation panic: `crates/warpui_core/src/keymap/matcher.rs` (`validate_bindings`, gated on `#[cfg(debug_assertions)]`) panics with `Bindings failed validation` when a *keystroke* binding matches a TUI keymap context without being TUI-owned (it was `app:reopen_closed_session`, Ctrl+Alt+T). It does **not** reproduce in every setup — it depends on which keystroke bindings the running config loads, and the validator exempts non-keystroke (palette/custom) triggers — so treat this as one thing to check, not a guarantee. If you hit it, two ways to still verify a change: - **Build `--release`** — the validator is compiled out, so the TUI stays up and you can `send-keys`/`capture-pane` freely: `cargo build --release -p warp_tui --bin warp-tui-oss` then run `./target/release/warp-tui-oss`. - **Or poll `capture-pane` right after launch** on the debug build to grab the first frame before the panic: ```bash tmux new-session -d -s tuicheck -x 120 -y 40 './target/debug/warp-tui-oss' for i in $(seq 1 15); do frame=$(tmux capture-pane -t tuicheck -p | sed 's/[[:space:]]*$//' | grep .) [ -n "$frame" ] && { echo "$frame"; break; } sleep 0.2 done tmux kill-session -t tuicheck 2>/dev/null ``` If the debug build stays up on your machine, you can `send-keys`/`capture-pane` repeatedly without racing. - **Alt screen is handled for you.** `capture-pane` reads the alternate screen, so you don't need to fight escape-sequence soup the way piping stdout would. - **Startup probe.** On launch the TUI emits terminal probes (OSC `10`/`11` + a device-attributes query) to pick a theme; a normal tmux pane answers them. Give it ~0.5–1s (a `sleep`) before the first capture. - **Quitting.** Ctrl-C is `tmux send-keys -t tuicheck C-c`. On the login placeholder one Ctrl-C exits; in a live session it's press-again-to-exit (first press cancels/clears input and arms a ~1s window; a second within the window exits). Always `tmux kill-session` at the end so a stray session doesn't linger. ## Step 4 — Capture screenshots and video (asciinema + agg) `capture-pane` text is the fast inner-loop check (Step 3) and enough to *assert* on a change. But for PR evidence — and for attaching durable image/video artifacts — you often want an actual **screenshot** or a short **video** of the rendered TUI. Because the TUI is a console program, capture it by recording its PTY session with **asciinema**, rendering that recording with **agg**, and transcoding it to an **MP4** (the same format Warp's `computer_use` screen recording produces) with `ffmpeg`; pull a still frame out with `ffmpeg` too. **Install the tooling (cloud runner — one-time).** asciinema and ffmpeg are packaged; `agg` ships as a prebuilt binary rather than in apt: ```bash sudo apt-get update && sudo apt-get install -y asciinema ffmpeg tmux # agg is not in apt — install a PINNED release binary and verify its checksum before # installing as root (don't pull an unpinned `latest`). The checksum below is for the # x86_64 build; on another arch use that asset's published checksum from the release. AGG_VERSION=v1.9.0 AGG_SHA256=f111e315cd71056b116302342553dd765b7297579ed511f111d0cedb442aeda6 curl -fsSL -o /tmp/agg \ "https://github.com/asciinema/agg/releases/download/${AGG_VERSION}/agg-$(uname -m)-unknown-linux-gnu" echo "${AGG_SHA256} /tmp/agg" | sha256sum -c - # aborts on mismatch sudo install -m 0755 /tmp/agg /usr/local/bin/agg ``` **Record the session.** asciinema needs a real PTY, so run it **inside tmux** (a bare `asciinema rec` in a non-interactive runner shell fails with "not a terminal"). Drive the TUI with `tmux send-keys` exactly as in Step 2 — the keys reach the binary running under asciinema: ```bash cd <warp-repo-root> tmux kill-session -t tuicap 2>/dev/null # clear only THIS capture session (not kill-server) # asciinema records the TUI's PTY; -c runs the binary; --overwrite replaces a prior cast. tmux new-session -d -s tuicap -x 120 -y 40 \ 'asciinema rec --overwrite -c "./target/debug/warp-tui-oss" /tmp/tui.cast' sleep 1 # let it draw + answer the theme probe # ...drive the interaction you want to show, e.g.: # tmux send-keys -t tuicap "hello" Enter && sleep 3 # Quit the TUI so asciinema finalizes the cast. The logged-out placeholder exits on one # Ctrl-C, but a live/logged-in session needs a SECOND press within its ~1s window (see # "Quitting" under Pitfalls) — so send two; the extra press is a harmless no-op if it # already exited (the session is gone, hence 2>/dev/null). tmux send-keys -t tuicap C-c && sleep 0.5 && tmux send-keys -t tuicap C-c 2>/dev/null sleep 1 ``` For a **logged-in** capture, build/run `warp-tui-dev` with `WARP_API_KEY` per Step 1 instead of `warp-tui-oss`. **Render the video (MP4).** Match the format Warp's `computer_use` screen recording uses — an **H.264 / yuv420p MP4** with `+faststart` (see `crates/computer_use/src/linux/recording.rs`) — so TUI captures are consistent with GUI/computer-use recordings. `agg` only emits GIF, so render to GIF and then transcode to MP4 with those settings. libx264 + yuv420p require **even** dimensions, so pad up by a pixel when the terminal render is odd-sized: ```bash agg --cols 120 --rows 40 /tmp/tui.cast /tmp/tui.gif ffmpeg -y -i /tmp/tui.gif -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" \ -c:v libx264 -pix_fmt yuv420p -movflags +faststart /tmp/tui.mp4
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기