How does cypress tap pin let you read a past DOM snapshot from the terminal?
answer
- The app already knows; the terminal does not
- Attach to a session, do not start one
- Same time travel, different input device
- Pin first, then read the frame
- Clear the pin when you finish
basics
~20 scypress tap pin attaches to a running Cypress open-mode session and pins a command's DOM snapshot into the app-under-test frame, exactly as clicking that Command Log row would. cypress tap dom then prints that snapshot's HTML.
solid answer
~40 s`cypress tap` is a CLI extension that attaches to an existing `cypress open` session and exposes what the app knows as terminal output. `cypress tap pin --test-id r4 --command-id 5 --at before` performs the same time travel as clicking that row: the application-under-test frame switches to that snapshot and stays there. While the pin is held, `cypress tap dom` returns the pinned page's HTML — the whole page, or the `outerHTML` of a `--selector` match, capped at 30,000 characters — and `aria` and `inspect` read the same state. `cypress tap pin --clear` releases it. It works only against an open-mode session on a Chromium-based browser, only once the run has finished, and only for tests still held in memory.
code
bash · 5 linesnpx cypress tap reporter --test-id r4
npx cypress tap command --test-id r4 --command-id 5
npx cypress tap pin --test-id r4 --command-id 5 --at before
npx cypress tap dom --selector '[data-testid="ticket-row"]' --at 0
npx cypress tap pin --cleargo deeper
Recall that the same time travel you get by clicking a Command Log row is reachable from a terminal, and that reading the page requires pinning a command first.
Explain the order of operations and the addressing: find the row, list its snapshots, pin one by name or index, read it, then clear the pin so later reads see the live page.
Show that you know where it stops working — open mode only, Chromium only, a finished run, a bounded memory window — and why a shared frame makes concurrent manual clicking dangerous.
Weigh what it changes for a team: an agent or script can now read the same evidence an engineer reads, and you have to decide how much of a debugging loop should depend on one developer's live session.
## What `cypress tap` is `cypress tap` is an extension of the Cypress command-line interface that **attaches to a running `cypress open` session** and lets you read and drive it from a terminal. It talks to the app already on screen — it does not start a headless run of its own — so everything the Cypress app knows about the current run becomes available as text: which specs exist, where the run is in its lifecycle, a test's Command Log, one entry's console properties, and the DOM of the application under test. Its subcommands split into three groups: - **Finding and driving a session** — `sessions`, `status`, `specs`, `run`. - **Reading the Command Log** — `reporter` for a spec or test report, `command` for one entry. - **Reading the page** — `pin` to time travel, then `dom`, `aria` and `inspect` to read what is showing. Every subcommand exits `0` on success and `1` on failure, accepts `--json` for a machine-readable form of the same output, and takes `--session` to target one process id when more than one Cypress app is open. ## Pinning a snapshot from the shell `cypress tap pin` does to the Cypress window exactly what clicking that row in the Command Log does: the application-under-test frame switches to the historical snapshot and stays there until the pin is released. You address a row the way `cypress tap reporter` printed it: | Option | What it names | Default | |---|---|---| | `--test-id` | the test, by the id the reporter printed, such as `r5` | required | | `--command-id` | the row — a number, an `e`-prefixed event id, or hook-qualified like `h1:3` | required | | `--at` | which snapshot on that row, by name (`before`, `after`) or 1-based index | the last one | | `--attempt` | which attempt, when the test was retried | the latest | | `--clear` | release the pin and restore the app to its pre-pin state | off | `cypress tap command --test-id r5 --command-id 3` is how you find out what there is to pin: it prints the row, a `SNAPSHOTS` table with a `#`, `NAME` and `TIME` column, and the entry's console properties expanded three levels deep by default. ## Reading the pinned page While a pin is held, three commands read the pinned snapshot rather than the app's live final state: - **`dom`** returns HTML — the whole page, or the `outerHTML` of the element matched by `--selector`, capped at 30,000 characters by default and adjustable with `--max-chars`. If the selector matches more than one element the command refuses, lists the first matches with indexes, and exits `1`; pass `--at <index>` to pick one. - **`aria`** returns the compact role/name/state accessibility tree, which is usually the cheapest way to understand a page. - **`inspect`** returns one element's tag, attributes, computed styles and box model. Release the pin with `cypress tap pin --clear` when you are done, so the next read sees the live page again. ## What it cannot do The constraints matter more here than the flags, because most of them bite silently: 1. **Open mode only.** It attaches to a `cypress open` session; there is nothing to attach to in a headless `cypress run`. 2. **Chromium-based browsers only** — Chrome, Chromium, Edge and Electron. 3. **The run must be finished.** Pins cannot be created while a spec is running, and `dom`, `aria` and `inspect` need a completed run, exactly as clicking a row in the app does. 4. **The window is bounded.** Only the most recent tests still hold snapshots, per `numTestsKeptInMemory`, so a row far back may have nothing to pin. 5. **A rerun releases the pin**, because the snapshot it named belonged to the previous run. 6. **One frame, two drivers.** The CLI and the person at the keyboard share a single application-under-test frame. Unpinning in the app releases the pin the CLI set, and pinning by hand changes what `dom` reads while `status` still reports no pin — so leave the window alone while the CLI is driving it, and check `status` before trusting a read. ## A worked loop on the ticket queue Chasing a support-ticket spec that fails intermittently, without ever leaving the terminal: ```bash npx cypress tap reporter --test-id r4 npx cypress tap command --test-id r4 --command-id 5 npx cypress tap pin --test-id r4 --command-id 5 --at before npx cypress tap dom --selector '[data-testid="ticket-row"]' --at 0 npx cypress tap pin --clear ``` The `reporter` call gives you the failing test's rows and its error. The `command` call tells you the escalate click carried two snapshots and prints what the entry logged. The `pin` puts the page back to the instant before the click, `dom` prints that ticket row's markup, and `--clear` hands the window back. If the row's markup shows the escalate button already disabled, the click never had a target and the failure is a waiting problem rather than an application bug — the same conclusion you would reach by clicking through the app, reached instead in five commands a script or an agent can run.
- Why should you leave the Cypress window alone while cypress tap is driving it?Both share one application-under-test frame. Unpinning in the app releases the pin the CLI set, and pinning a row by hand changes what `dom`, `aria` and `inspect` read while `status` still reports no pin — so a read can silently describe a different moment than the one you asked for. Check `status` before trusting a read.
- cypress tap dom reports that your selector matched 25 elements. What does it do, and what do you pass?It refuses to guess: it prints the first matches with their indexes and a suggested selector for each, then exits `1`. Pass `--at` with the index of the match you want, or narrow the selector until it is unique. The same disambiguation applies whether you are reading the live page or a pinned snapshot.
saying these in an interview costs you the question
- Thinks cypress tap starts its own headless run
- Expects it to attach to a cypress run session
- Reads the DOM without pinning a command first
- Leaves a pin held and misreads the next command
- Assumes any command in the spec is still pinnable