Pendo のセッション再生(ユーザー操作の記録)に映された問題を、開発ログの取得、エラーのコードへの対応付け、修正案の提案、プルリクエストの要求を通じて優先順位付け(整理)します。 再生動画の URL を直接指定するか、チケットの参照(Jira のキーや URL、GitHub のイシュー URL など)を指定できます。チケットを指定した場合は、自動的に再生動画のリンクを取得します。 **次のような場合に使用:** ユーザーが報告したバグについて、再生動画のリンクまたはそれを含むチケット経由で引き継がれ、調査、診断、デバッグ、優先順位付け、修正が求められるとき。 **必要な接続:** Pendo コネクタが必要です。チケットを指定した場合は、利用可能なチケット管理ツール(Atlassian、`gh` など)の MCP またはコマンドラインツールを使用します。
Triage issues captured in a Pendo session replay by fetching devlogs, mapping errors to the local codebase, proposing fixes, and prompting for a pull request. Accepts either a replay URL directly or a ticket reference (e.g. Jira key or URL, GitHub issue URL, etc.) and will pull the replay link from the ticket. Use whenever someone hands off a user-reported bug — via a replay link or a ticket that contains one — and asks to investigate, diagnose, debug, triage, or fix it. Requires Pendo connector; uses whatever ticketing MCP or CLI is available (Atlassian, `gh`, etc.) when a ticket is supplied.
Given a Pendo session replay — supplied directly as a URL or referenced from a ticket (Jira, GitHub, etc.) — pull the devlog events (console errors and HTTP failures) captured during that session, cross-reference them against the current codebase, propose a fix, and prompt the user to open a PR.
This skill is designed for application developers triaging a user-reported issue: start from the replay that witnesses the bug, end at a proposed code change.
The user may supply one of:
https://<hostname>/s/<subId>/replay/player/<sessionId>?startTime=...&endTime=...https://<hostname>/s/<subId>/replay/clip/saved/<clipId>ABC-12345) or full Atlassian URLhttps://github.com/org/repo/issues/123)If the user gives only a bug description with no replay URL or ticket, ask for one first. This skill is useless without a replay.
If the user gave a ticket reference instead of a replay URL, look it up and extract the replay URL from its description and comments. Choose the tool based on where the ticket lives and what's available in the current environment — do not hardcode one system:
mcp__atlassian__getJiraIssue), call it. If not, try mcp__atlassian__search or ask the user for the replay URL directly.gh issue view <url-or-number> --comments via Bash. This is almost always available.When fetching, request the description and comments — replay links are often added in a comment after the bug was filed.
Scan the ticket content for a Pendo replay URL. Match on the shape /replay/player/ or /replay/clip/saved/ in the hostname path — don't just search for "pendo", which will false-match unrelated links. If you find:
Also capture from the ticket:
focus so Step 3's triage can prioritize the right errors.If the user supplied both a ticket and a replay URL, prefer the explicit replay URL but still pull ticket context for focus.
devlogEvents takes the identifying fields as individual parameters. Pull them out of the replay URL yourself — the two shapes are:
https://<hostname>/s/<subId>/replay/player/<recordingSessionId>?startTime=<ms>&endTime=<ms>&visitorId=<id>&appId=<id>&accountId=<id>
subId: the segment after /s/recordingSessionId: the segment after /replay/player/ (strip any query string or fragment)startTime, endTime: the startTime and endTime query params, as numbers in milliseconds since epochvisitorId, appId, accountId: pull these from the query string whenever they're present. They're optional for the call, but passing them narrows the aggregation on the Pendo side and makes devlogEvents return noticeably faster — always include the ones you can parse. Only fall back to omitting them if the URL doesn't have them.https://<hostname>/s/<subId>/replay/clip/saved/<clipId>
subId: the segment after /s/clipId: the segment after /clip/saved/ — passing this alone lets devlogEvents resolve appId, visitorId, accountId, recordingSessionId, and the time range internallyIf the URL is malformed or missing startTime/endTime on a player link, ask the user to copy the link again from the Pendo UI — the player URL exported from Pendo always includes the time range. If you can't parse a subId at all (non-standard host), call list_all_applications and confirm the subscription with the user before continuing.
Call devlogEvents with the fields you extracted in Step 1.
For a player URL, pass:
subId, recordingSessionId, startTime, endTime (from Step 1)visitorId, appId, accountId — include every one that was present in the URL's query string. These aren't required, but they prune the search space server-side and make the call materially faster, especially on noisy subscriptions. Omit only the ones the URL didn't contain.logType: ["console", "network"]logLevels: ["error", "warn"]statusCodes: ["4xx", "5xx"]limit: 50For a clip URL, pass:
subId, clipId (from Step 1) — the clip lookup fills in the restlogType, logLevels, statusCodes, and limit as abovedevlogEvents is a slow-running tool. Tell the user you're pulling logs so they know what you're waiting on.
If the call returns no events, don't stop:
logLevels: ["error", "warn", "info"] in case errors were logged at a lower level.statusCodes dropped entirely to see all network traffic.If the call returns exactly limit events (50), you're almost certainly truncated — there may be more events you never saw, and the ones you got are biased toward one edge of the window. Don't just triage what you have; narrow the window and re-fetch:
[startTime, endTime] — e.g. split into halves or focus on the portion the user's focus hint points at (if they said "crash after save", target the last third of the session first).devlogEvents with the narrower startTime/endTime. Keep subId, recordingSessionId, and the other identifiers the same.For clip URLs, the clip lookup supplies a default time range, but you can still pass explicit startTime/endTime to override it — use the same narrow-and-re-fetch loop above. If you don't know the clip's resolved range yet, do one unbounded call first to see the timestamps on the returned events, then shift the window within that span.
Group the devlog events into candidate issues. The goal is a small set of distinct problems, not a dump of every log line.
For each event, capture:
focus points to them.Cluster events that share a root cause: same stack frame, same endpoint, same error message. Rank clusters by:
Filter ruthlessly at this stage. If you surface 20 "issues", the user has to do the triage work themselves.
For the top 1–3 clusters, locate the relevant code in the current working directory.
For JS stack traces:
bundle.min.js:1:4523, you won't get a direct file match. In that case, fall back to searching for the error message string.Grep to search for the error message text (quoted strings are usually copy-pasteable) and for function names from the stack.Glob to locate files by the basename in the stack.For HTTP errors:
/api/orders/:id) in route definitions, controllers, API clients, and fetch/axios calls.When nothing maps:
Once the offending code is located, read enough surrounding context to understand the bug, then propose a targeted fix.
Keep the fix minimal and scoped to the bug. Do not bundle refactors, style cleanup, or unrelated improvements — the user wants to close this ticket, not redesign the module.
Present the proposal before editing:
## Proposed Fix
**Issue**: {one-line description of the root cause}
**File**: {path}:{line}
**Change**: {brief summary — e.g. "Guard against null user before reading user.id"}
{short diff showing only the changed lines, with 2–3 lines of context}
**Why this fixes it**: {one or two sentences tying the change back to the devlog evidence}
Ask the user to confirm before applying the edit. If they approve, use Edit (or Write for new files) to make the change. If they want adjustments, iterate.
After applying the fix:
package.json scripts, pytest, go test, etc.). Don't guess at commands — only run ones you can see in the project config. If nothing is configured, skip this step and say so.create-pr skill is available in their environment, suggest running it; otherwise give a brief gh pr create starter. If the triage started from a ticket, include the ticket reference in the suggested PR title/body so the link is preserved. Do NOT create the PR automatically — the user confirms when they're ready.Structure the final report like this:
## Replay Triage: {sessionId or clipId}
**Session**: [View Replay]({replay_url})
**Devlog events analyzed**: {count} ({console_count} console, {network_count} network)
### Issues Found
1. **{Short title}** — {severity: Critical / Likely Bug / Warning}
- Evidence: {console message or HTTP failure summary, with count if repeated}
- Location: {file:line} (or "Could not locate in current codebase — see notes")
- Fix: {proposed_fix_summary}
2. ...
### Applied Fix
{Only if the user confirmed. Show file(s) changed and a one-line description each.}
### Verification
{Type-check / test results, or a note that no checks were configured.}
### Next Step
Ready to open a PR? {suggest a PR creation skill if available, or a `gh pr create` starter}
Skip sections that don't apply. If no issues were located in the codebase, say so and stop at Step 4 — don't fabricate a fix.
devlogEvents takes identifying fields as individual parameters — extract subId, recordingSessionId, startTime, endTime (or clipId for saved clips) out of the URL and pass them directly. Don't pass the raw URL.gh pr create. Opening a PR is a shared-state action that should always stay with the user.原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。