From posthog
Guides users from vague intent to a focused list of high-signal session recordings using PostHog. Turns goals into filters and deep-links top sessions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/posthog:finding-sessions-to-watchThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Most people open session replay with a goal ("why are signups dropping?") but no idea which of
Most people open session replay with a goal ("why are signups dropping?") but no idea which of thousands of recordings to watch. A raw, unfiltered list is the worst possible answer — it buries the useful sessions in noise. Your job is to turn their intent into a focused filter, return a handful of high-signal recordings, and offer to dig into one.
The starting points below are the same ones the product surfaces as "filter templates" — they encode the jobs people actually use replay for. Treat them as a menu, not a script.
Never dump an unfiltered recording list. Always either (a) apply a goal-based filter, or (b) sort by a signal (activity, errors) so the first few rows are worth a click. If the user's goal is unclear, ask one short question or offer the menu before querying.
| Tool | Purpose |
|---|---|
posthog:query-session-recordings-list | Find/filter recordings (the workhorse). Returns metadata + id per row. |
posthog:read-data-schema | Confirm real event names, URLs, and property values before filtering. |
posthog:execute-sql | Collect $session_ids for sessions where a specific event happened. |
posthog:cohorts-list | Resolve a cohort name → id when scoping to a user segment. |
posthog:session-recording-playlist-create | Save the resulting filter as a saved filter view (type: 'filters'). |
Hand off to the investigating-replay skill once the user picks a recording to understand in depth.
Map the request to one of the starting points below. If it's vague ("show me something interesting"), offer 3-4 options rather than guessing, or default to most active sessions (high signal, no setup).
Event names and URLs vary per project — never assume $pageview paths, a signup_completed event, or
a person property exists. Confirm with read-data-schema (event_properties,
event_property_values, entity_property_values) before putting a value in a filter. If the needed
event/property doesn't exist, say so and suggest the closest available signal.
Call query-session-recordings-list with only the filters that serve the goal. Recommended settings:
filter_test_accounts: true (the tool defaults to false) to exclude internal users, unless the
user is debugging their own session.date_from of -7d to -30d for goal-based searches; -3d for "recent".order — activity_score for "interesting", console_error_count for "broken",
start_time for "recent".limit: 10 — you want a shortlist, not a dump.Don't relay raw rows. Pick the 3-5 most promising and say why each is worth watching (long active
duration, many errors, reached the key page, high activity score). Deep-link each as
{posthog_base_url}/replay/{id} — never /replay/home?sessionRecordingId={id}. Note total matches so
the user knows how much is behind the shortlist.
investigating-replay.session-recording-playlist-create (type: 'filters' — a filter view, not a 'collection', which is
for manually curated recordings and can't carry filters).Two filter shapes cover almost everything:
visited_page ({ "type": "recording", "key": "visited_page", "operator": "icontains", "value": "/pricing" }).execute-sql, then pass them as session_ids
(see the two-step pattern below).| User goal | Approach |
|---|---|
| Signup / onboarding / pricing / checkout friction | visited_page icontains the relevant path (confirm the real path first). Order start_time, or console_error_count to surface broken ones. |
| A specific feature | Two-step: execute-sql for $session_ids where the feature event fired, then session_ids. Pair with visited_page if the feature lives on one page. |
| Rageclicks / frustration | Two-step on the $rageclick event → session_ids. |
| Errors / something broken | properties: [{ "type": "recording", "key": "console_error_count", "operator": "gt", "value": 0 }], order console_error_count. |
| A/B test / feature flag | { "type": "flag", "key": "<flag-key>", "operator": "flag_evaluates_to", "value": "<variant or true>" }. |
| A specific person / segment | person_uuid, a person property filter (e.g. email), or a cohort filter (cohorts-list for the id). |
| Mobile / responsive issues | { "type": "event", "key": "$device_type", "operator": "exact", "value": ["Mobile"] }, or { "type": "event", "key": "$screen_width", "operator": "lt", "value": 600 }. |
| Most active users / "just show me good ones" | No filter; order: "activity_score". The reliable default when the user has no specific goal. |
| Most active pages | execute-sql to rank $pageview by URL, then filter recordings by the hottest page's visited_page. |
The recordings query filters by event properties, not event names. To find sessions that contain a particular event, collect the session IDs first:
posthog:execute-sql
SELECT $session_id
FROM events
WHERE event = '$rageclick' -- or your signup/search/feature event (confirm via read-data-schema)
AND timestamp > now() - INTERVAL 7 DAY
AND $session_id != ''
GROUP BY $session_id
ORDER BY max(timestamp) DESC -- recent first: UUIDs aren't time-ordered, so the LIMIT must keep the freshest sessions
LIMIT 100
Then fetch those recordings (some session IDs won't have a recording — that's expected). Pass the same
date_from window as the SQL step — with only session_ids, the query falls back to its -3d default
and would drop sessions whose event was older than that:
posthog:query-session-recordings-list
{ "date_from": "-7d", "session_ids": ["<id1>", "<id2>", "..."] }
User: "Why are people bouncing on our pricing page? Show me some sessions."
visited_page approach.read-data-schema (event_property_values for $pathname) to confirm the path is /pricing.posthog:query-session-recordings-list
{
"date_from": "-14d",
"filter_test_accounts": true,
"order": "activity_score",
"limit": 10,
"properties": [
{ "type": "recording", "key": "visited_page", "operator": "icontains", "value": "/pricing" }
]
}
{base}/replay/{id}, noting which lingered or hit errors.investigating-replay) or save it as a saved filter view (type: 'filters').diagnosing-missing-recordings).activity_score is a solid default proxy for "worth watching" when there's no sharper signal — but it
rewards raw interaction volume, so prefer a goal-based filter (errors, a key page) when you have one.npx claudepluginhub anthropics/claude-plugins-official --plugin posthogMonitors PostHog session replay for capture integrity drops and concentrated friction (rage/dead clicks, error cohorts) across surfaces, emitting findings only when confidence thresholds are met.
Analyzes Amplitude Session Replays to surface UX friction patterns across sessions, producing a ranked friction map. Use when asked about user confusion, clunky flows, or usability issues.
Analyzes Sentry session replays to surface UX patterns, pain points, and user journeys for a specific product area via URL filtering and employee exclusion.