For the complete documentation index, see llms.txt. This page is also available as Markdown.

luciq-debug

The luciq-debug skill investigates a crash, hang, bug, or APM issue end to end, mapping Luciq data to your repo and proposing a cited fix.

Investigate a Luciq production signal end to end — crash, hang, user-reported bug, or APM performance issue — using the Luciq MCP server for context and the user's local repository for the code mapping. Form a hypothesis, propose a fix, cite the evidence.

Use this skill when

  • The user describes a crash, hang, or bug. "Why is this happening", "investigate this", "what broke".

  • The user pastes a stack trace, exception, or fingerprint and asks for a diagnosis.

  • The user references a specific Luciq crash ID, bug ID, or hang ID.

  • The user asks "what's regressing in version X" or "compare crashes between versions".

  • The user flags an APM performance issue: a slow endpoint, a latency or p95 spike, an apdex drop, a network failure-rate spike, slow app launch, UI jank (frozen or slow frames), slow screen loading, user-flow drop-off, a throughput change, or "what got slower or flakier since version X".

What the agent learns

luciq-debug turns the agent into an evidence-based debugger across crash, hang, bug, and APM signals:

  • Signal-typed methodology. Different decision trees for crashes, hangs, bug reports, and APM signals, each weighted by the evidence that matters for that signal.

  • MCP tool sequencing. Which Luciq MCP tool to call when, in the right order, with the right filters, without over-fetching.

  • APM coverage across all five metrics. Network endpoints, app launch, user flows, screen loading, and frame drop — the agent knows how to enter each signal, which APM views to pull, and how to localize a regression to a cohort or span.

  • Metric reference material. Before quoting an APM number, the agent reads that metric's reference files, covering units, coverage and account gating, stage boundaries, and the conditions that make a number misleading. Populated for network and app launch across iOS, Android, React Native, and Flutter.

  • Local code mapping. Translating a top stack frame or APM group name from production into a Read + Grep against the user's repo so the fix lands in real code.

  • Evidence-cited hypotheses. Every claim the agent makes cites the MCP tool result that produced it. No fabrication, no guessing.

  • Pattern library. Known mobile failure modes (Swift Concurrency races, Android ANRs, OOMs, network failures, APM latency regressions, failure-rate spikes) the agent recognizes and reaches for the right Luciq context to confirm.

Install

The fastest path is the plugin install. Add the marketplace and install:

Works in Claude Code and Cursor. The plugin install also wires up the Luciq MCP server in one step (this skill needs it).

After install, the skill is available as /luciq-skills:luciq-debug.

For other agents, install via npm:

Or copy SKILL.md from the public repo to ~/.claude/skills/luciq-debug/SKILL.md (user-global) or .claude/skills/luciq-debug/SKILL.md (project-local). The full SKILL.md is reproduced in the expandable below.

📋 Click to expand the full SKILL.md

Prerequisites

  • The Luciq MCP server is configured and authenticated. The luciq-setup skill wires this for first-time projects.

  • The user has access to the Luciq application and environment they want to investigate.

  • The agent is running inside a project repository so it can map stack frames and APM groups to local source.

If the MCP server isn't connected, the skill stops and points the user to Setup by IDE before continuing.

How the agent investigates

The skill runs the agent through a small, predictable loop. Every step is gated on evidence. If a step doesn't return data, the agent says so rather than filling in plausible-looking guesses.

Step 1. Identify the entry point

What kind of signal are we debugging?

Entry point
Required input
First MCP tool call

Crash group

Crash number, fingerprint, or pasted stack trace

crash_details (or list_crashes to find it)

Specific occurrence of a crash

Crash number + ULID

get_occurrence_details

App hang / ANR

Hang number, or "recent UI hangs"

list_app_hangs

User-reported bug

Bug number

bug_details

Regression between versions

Two version numbers

list_crashes filtered by version, then crash_patterns with pattern_key: app_versions

Review / rating signal

Date range + version

list_reviews filtered by rating + app_version

APM performance regression

"what got slower/flakier since X", two versions; which metric

apm_list_groups for the matching metric sorted by apdex_change, then apm_group_view with dimensions

Worst APM group

The signal: slow endpoint/launch/screen, jank, flow drop-off

apm_list_groups for that metric sorted by its pain key (p95, failure_rate, frozen_frames_percent, dissat_count), then apm_group_view

Throughput spike / drop

Group + window

apm_group_view with throughput_chart for the group

If the user doesn't specify the signal type, the agent asks. It doesn't pick one at random.

Step 2. Pull MCP context

Once the entry point is known, the agent calls Luciq MCP tools in a deliberate order:

  • Crashes: list_crashes, crash_details, crash_patterns, then list_occurrences_tokens and get_occurrence_details for one or more sessions.

  • Hangs: list_app_hangs filtered to the recent window.

  • Bug reports: list_bugs then bug_details. The response includes URLs to compressed logs (network, console, session profiler) when available.

  • Regressions: filter list_crashes by the two versions, diff the result, then call crash_patterns with pattern_key: app_versions for the highest-impact new groups.

  • Review signals: list_reviews filtered to low ratings, then correlate with crash and hang activity in the same window.

  • APM regression: choose the metric for the signal, then apm_list_groups sorted by apdex_change (signed delta) across the two app_version values, take the most-degraded groups, then apm_group_view with dimensions to localize each regression to a cohort (OS, device, country, version), then apm_occurrence with selector: worst for a concrete worst case to reason over.

  • APM group deep dive: apm_list_groups for the metric sorted by its pain key to find the group, then apm_group_viewsummary for the headline metrics, then the view that matches the pain: spans_table (or stages_breakdown for launch/screen loading) for a slow segment, outliers for the tail driving p95 (not on frame_drop), or the failure_rate view for a failing network group, then apm_occurrence for the worst-failed request when the pain is failures, not the slowest.

  • Reference material: before interpreting a metric's numbers, the agent reads that metric's reference files. Coverage gating, stage boundaries, and the conditions that make a number misleading aren't visible in the raw figure.

If an APM tool returns a 403 or 501, the agent skips that step and reports the reason. It does not infer "no regression" from a tool error.

The agent does not invent metrics that the Luciq MCP doesn't expose.

Step 3. Symbolicate if the trace is obfuscated (crash / hang track)

If the top frame is a hex address, an obfuscated symbol, or a <unknown> marker, the build is missing its symbol artifact:

  • iOS: dSYM upload.

  • Android: R8 / ProGuard mapping.

  • Flutter: split-debug-info.

  • React Native: source map.

The agent points the user at Luciq's symbol upload flow rather than reasoning over hex addresses.

Step 4. Map to local source

Crash / hang track — map the top frame:

  • Grep the symbol (class + method) across the project.

  • Read the matched file with a small window around the offending line (10 lines above and below).

  • For multi-platform projects (KMP, RN, Flutter), prefer the platform-specific source set first (iosMain/, androidMain/).

APM track — map the endpoint or span to the call site:

The APM group name is the request signature (method + URL path template, e.g. GET /v2/orders/{id}). The agent maps it to the code that issues or handles it:

  • Grep the path template, the host, or the path segments across the project. For a client SDK, that's the request-building call site. For a server repo, it's the route/handler registration.

  • When spans_table localized the cost to one segment (a DB span, a downstream call, a serialization span), grep that segment's operation name — the bottleneck is usually inside that call, not in the request setup.

  • Use the dimensions breakdown to constrain the hypothesis: a regression confined to one OS version or device tier points at a different cause than one uniform across cohorts.

If the symbol or endpoint doesn't exist locally, the agent surfaces that fact rather than guessing at a fix.

Step 5. Form a hypothesis

Crash / hang track:

APM track:

Confidence is honest, not optimistic. Three corroborating MCP sources is high. Reasoning from the top frame or a single number alone is low. A latency figure with no cohort breakdown and no span decomposition is a symptom, not a root cause.

Step 6. Propose a fix

The agent shows a diff, explains how the fix addresses the root cause, and flags side effects. It does not apply the diff without user confirmation.

Pattern library

The skill carries a library of mobile failure patterns. Each pattern is a reference the agent reaches for when it sees the corresponding signature in the MCP data.

Swift Concurrency issues (iOS)

When the top frame involves async, await, an actor, or a Sendable violation:

  • Check whether the crash is a Swift runtime: Fatal error: ... rather than a typical exception. That's a concurrency-safety check firing.

  • Confirm the OS distribution from crash_patterns with pattern_key: oses. Swift 6 strict-concurrency checks behave differently across iOS versions.

  • Look at the session profiler from get_occurrence_details for hop-to-@MainActor patterns near the crash time.

  • Don't recommend slapping @MainActor on a class to silence the error. Treat that as a smell, not a fix.

Android ANRs (ANDROID_FATAL_HANG)

When list_app_hangs returns an Android hang:

  • The crash_cause field tells you where the main thread was blocked, but not always what blocked it. Pull a few get_occurrence_details to see recent main-thread activity and pending I/O.

  • Check pattern_key: app_versions to see whether the ANR is a regression or a long-tail issue.

  • Common offenders: synchronous network calls on the main thread, large SharedPreferences.commit() writes, blocking Lock acquisitions, work scheduled on the wrong dispatcher.

iOS UI hangs (FATAL_UI_HANG)

  • The hang exception summary indicates duration class.

  • Pull the occurrence to confirm what the user was doing. The current_view and app_status (foreground / background) fields disambiguate.

  • Common offenders: synchronous Core Data on NSManagedObjectContext.viewContext, file I/O on the main queue, expensive layout work in viewDidLayoutSubviews.

Out-of-memory crashes

  • OOMs surface as terminations, not classic crashes. Check crash_type and the exception name.

  • Pull the occurrence's state.memory and state.storage fields from get_occurrence_details for the resource state at termination.

  • Look at pattern_key: devices. OOMs concentrate on lower-RAM devices and surface a device-tier story the agent should call out.

Network failure correlated crashes

  • For crashes with a stack frame in networking code, pull the occurrence's logs URL from get_occurrence_details (compressed log archive).

  • Cross-reference with bug reports in the same window via bug_details. The state.logs.network_log URL often shows the failed request that preceded the crash.

  • Don't assume timeout vs DNS failure vs server error without the log evidence. The categories matter for the fix.

APM latency regression

When apm_list_groups sorted by apdex_change shows a group degrading between versions:

  • Before trusting the apdex, the agent sanity-checks threshold_ms against 50th_percentile_ms, then weighs it against the endpoint's business role: a list/read call should be near-real-time, a few hundred ms; a heavy export doesn't need to be. A target set for the wrong role is a config fix, not a code fix.

  • Confirm with absolute numbers: pull apm_group_view summary for 50th_percentile_ms and 95th_percentile_ms before and after.

  • Always run dimensions to localize. A regression confined to one OS version or device tier is a different bug than one uniform across cohorts.

  • Use spans_table to attribute the time. The fix targets the dominant span. Chasing the request-setup code when the cost is in a DB span wastes effort.

  • Use outliers when p95/p99 moved but the median didn't — the tail requests carry the signature.

APM app launch

When apm_list_groups flags a launch group (metric: launch):

  • Segment by type first. Cold, warm, and hot launches measure different windows, so aggregating across them — or across platforms — produces a meaningless number.

  • Attribute with stages_breakdown, not spans_table. The dominant stage maps to code via the platform's optimization-targets table; on React Native and Flutter, a dominant native stage means the cause isn't in JS or Dart.

  • Use dimensions with pattern_key: first_screen to find which entry screen carries the cost, and outliers when p95 moved but p50 didn't.

  • The agent validates the number before quoting it — several conditions can make a launch total mean something other than "the app is slow," and they aren't visible in the number itself.

APM network

When apm_list_groups flags a network group (metric: network):

  • Coverage comes first. Capture isn't automatic on Android or Flutter, so the agent checks the codebase before reading absence as a measurement.

  • There's no stages_breakdown view for network. The agent attributes with spans_table and uses apm_occurrence for one request's stage detail.

  • The list row gives latency_p95_ms and failure_rate only — no p50, no occurrence count. Those come from summary or dimensions.

  • The agent segments on radio before comparing latency, and accounts for what the measured window excludes — the app's own queueing and interceptors aren't in it.

APM failure-rate spike

When apm_list_groups sorted by failure_rate flags a group:

  • Split total_failure_rate into client_failure_rate vs server_failure_rate. Client failures (4xx, timeouts, cancellations) point at the app; server failures (5xx) point at the backend. They lead to opposite fixes.

  • Both native platforms distort the client-side rate, in opposite directions, so the agent applies the platform-specific correction before quoting it.

  • Filter the group by failure_name / failure_type to see whether it's one error class or many.

  • Cross-reference the window with list_crashes and bug_details — a failure-rate spike that coincides with a crash spike on the same call path is usually one root cause, not two.

APM throughput change

When throughput_chart shows a spike or drop:

  • A drop in throughput with flat latency often means callers stopped calling — a client-side gating change, a feature flag, a rollout — not a performance defect. Check dimensions by app_version and correlate with a release.

  • A spike with rising latency is load-driven; the fix is usually capacity or backpressure, not a code path. Say which the evidence supports.

Honest about what's out of scope

The skill is grounded in what Luciq MCP exposes today. It deliberately does not:

  • Compute crash-free session rate or any metric the MCP doesn't return.

  • Reason about App Store rating drops as a primary investigation entry point. list_reviews is correlation, not causation.

  • Pretend to have data it doesn't have. If a query returns nothing, the agent surfaces that fact and stops.

When Luciq MCP grows new tools (release comparison, session replay context), this skill grows with them.

When to reach for it

  • A new crash spikes in production and you want a triage and a candidate fix without leaving your IDE.

  • A user-reported bug has reproduction steps but you don't know which screen they were on or what network call failed. The agent pulls that from bug_details and points you at the file.

  • You're cutting a release and want a quick diff of new crashes between versions. The agent runs the comparison via list_crashes and crash_patterns.

  • You're handed a crash by a teammate with just a number. The agent investigates from the number alone.

  • You saw an apdex drop or a p95 spike on an endpoint since the last release. The agent finds the worst-affected group, decomposes the time via spans_table, and maps the bottleneck to local source.

Last updated