Session replay tools for analyzing Fullstory session recordings. Sparse API catalog — tools are self-describing.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add fullstorydev/subtext --skill subtext-session --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Subtext Session?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/fullstorydev-subtext-session)More formats (shields.io, HTML) on the badges page.
---
name: subtext-session
description: Session replay tools for analyzing Fullstory session recordings. Sparse API catalog — tools are self-describing.
---
# Session Replay
> **PREREQUISITE:** Read `subtext-shared` for MCP conventions.
API catalog for the session replay tools (all prefixed `review-`). One gesture — **zoom** — over two data sets: the **signal stream** (temporal) and the **snapshot** (spatial). Opening a session hands back a **map**: an always-on orientation header, never a zoom level.
## MCP Tools
| Tool | Description |
|------|-------------|
| `review-list-sessions` | Find reviewable sessions — numbered URLs + timestamps. With no arguments, the org's most recent captures. With `email_address`/`user_uid`, one user's sessions, paged with `before`. |
| `review-open` | Open a session for analysis. Returns a handle (`client_id`) plus the **map** and a digest rollup. |
| `review-summary` | Static "what happened" — the default zoom (all kinds @ `standard`), frozen. No map, no handle. Stateless, cheapest call. Use for a quick read before deciding whether to `open`. |
| `review-zoom` | The live lens. Pass a `resolution` map and/or a `t0_ms`/`t1_ms` time window — returns the matching signal slice. |
| `review-snapshot` | The screen at a moment — screenshot + component tree + boxes, rooted at an optional `component_id`. |
| `review-close` | Close the session and free resources; records a short usage summary. |
## Discovering Parameters
Parameter schemas are visible in the tool definition at call time.
## Session Input
`review-open` accepts six mutually-exclusive identifiers. Pick the one that matches what you have on hand — they're all first-class:
- `session_url` — a full Fullstory session URL. The most common form — a customer-shared link, a Slack paste, or a session from the app UI.
- `trace_id` — the 12-char base62 id from a prior `review-open` response.
- `trace_url` — a full trace URL copied from the browser or returned by a live tool.
- `device_id` + `session_id` — both required together. Use when you have the raw ids but no URL.
- `email_address` / `user_uid` — looks up the user's most recent session.
All six paths return the same handle. Capture the `client_id` from the response so follow-on `review-zoom`/`review-snapshot`/`review-close` calls don't need to re-resolve the session.
`review-open`'s `email_address`/`user_uid` jumps straight to that user's *most recent* session. To see more than one, or to search back through their history, use `review-list-sessions` instead.
## Finding a user's sessions
`review-list-sessions` with no arguments lists the org's most recently captured sessions — no filtering, no paging.
Pass `email_address` or `user_uid` to scope it to one user instead. That response reports `newest`/`oldest` — the creation-time range it covered — and, when more history exists, a note to pass `oldest` back as `before` to page further back. `before` is only valid alongside `email_address`/`user_uid`; the org-wide list isn't time-scoped.
Ticket-triage recipe: given a report against a known user, `review-list-sessions` by their `email_address`/`user_uid` to get candidates, `review-summary` each to find the one matching the report, then `review-open` it to investigate.
## The map
`review-open`'s response includes a map — a cheap counting fold over the signal layer, never a body dump:
```
## Map · 114 signals · 0.0s–353s · 2 pages
flow: /ui ▸ /settings/overview ▸ /subtext/sessions ▸ /subtext/session/asr
kinds: navigation 18 · interaction 36 · network 58 (2 err) · console 2 (2 err)
tags: error:4
```
The map is **whole** — rendered once, over the entire session. Zooming into `{navigation: "standard"}` later doesn't touch it: `error:4` stays in the map's counts regardless of what you go on to zoom into. Read the map first; it tells you what exists before you pay for a zoom.
## The resolution contract
`review-zoom` takes:
```
resolution?: { [scope | kind | tag]: "digest" | "standard" | "machine" | "detail" }
t0_ms?: number // narrow the zoom to a time window
t1_ms?: number
```
Grain ladder, coarse → fine:
| grain | what you see |
|-------|--------------|
| `digest` | one rollup line per (section × kind) — `network ×19 (1 err)` |
| `standard` *(default)* | the readable transcript — bursty/repeated signals merged into one line |
| `machine` | every signal, nothing merged |
| `detail` | every signal plus its payload — headers, bodies, stack traces |
- **Omit `resolution`** → everything at `standard`.
- **Provide it** → an explicit allow-list. Unlisted kinds are excluded from the slice (never from the map).
- **Overlap → finest-wins.** A signal matching more than one key takes the finest grain among them — order-independent, and it can only ever show *more*, never hide something.
Keys are scopes (`navigation`, `interaction`, `network`, `console`, …), kinds (`click`, `network`, `exception`, `classified`, …), or tags — they resolve the same way. `error`/`warn`/`exception` are intrinsic (derived from a signal's own fields); a project's `.sightmap/` can author more: a component's `tags:` rides onto any signal that targets it (e.g. `defect` on a checkout-error element), and a `signals:` rule can generate a brand-new `classified` signal when a match fires against another signal's fields — surfacing a classification buried in a payload (a 200 response whose body says a payment declined) as its own selectable line, without touching the signal it fired on.
### Zoom recipes
```
// what went wrong, anywhere
review-zoom resolution={ error: "standard" }
// what happened in this session
review-zoom resolution={ navigation: "standard", interaction: "standard" }
// devtool-level detail
review-zoom resolution={ network: "machine", console: "machine" }
// network readable, but every error deep — finest-wins, no override needed
review-zoom resolution={ network: "standard", error: "detail" }
// a project-authored classification (a .sightmap/ tag or signals: rule), deep
review-zoom resolution={ defect: "detail" }
```
## Snapshot
`review-snapshot` takes `client_id` + `timestamp`, plus:
- `component_id` — optional; roots **both** the image clip and the tree subtree, so "focus here" means one thing.
- `lens` — `visible` (default), `interactive`, or `full`. Governs which elements populate the tree/boxes, not the pixels.
- `include` — any of `image`, `tree`, `boxes`.
- `expand_pct` — grows the `component_id` clip outward by this percent (0–100) for surrounding context.
- `upload` — store the screenshot and return a shareable signed URL.
- `full_page` — capture the whole scrollable page instead of the viewport. Requires `include` to contain `image`; can't be combined with `component_id`. These images are big — pair with `upload`. Ignored for mobile session pages.
No network/console excerpts are stapled onto a snapshot — signals only come from `review-zoom`. Want the requests or logs around a moment? Zoom that window.
## Tips
- Read the map before you zoom. It's free and tells you whether there's anything worth looking at.
- Start every zoom at `standard` (or omit `resolution` entirely) unless you already have a hypothesis about which kind matters.
- `error` as a resolution key is a floor, not a special case — it only ever raises detail wherever it applies.
- Use `review-snapshot` for "what did the screen look like," not for signals — it's a different data set.
- Always close sessions when done to free server resources.
## See Also
- `subtext-shared` — MCP conventions
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!