
Mobile Debugging
- 133 installs
- 353 repo stars
- Updated August 2, 2026
- jamditis/claude-skills-journalism
Diagnose crashes, layout bugs, and network failures in iOS or Android news apps during pre-release QA and staged rollout validation.
About
Mobile debugging skill tailored to journalism apps that systematically reproduces client defects, reads platform diagnostics, isolates networking and rendering failures, and recommends targeted fixes before readers hit production builds.
- Repro steps across OS versions and form factors
- Interprets crash logs and ANR traces
- Checks API, cache, and offline edge cases
- Guides simulator versus device strategies
- Prioritizes blockers versus cosmetic issues
Mobile Debugging by the numbers
- 133 all-time installs (skills.sh)
- +7 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #219 of 596 Debugging skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/jamditis/claude-skills-journalism --skill mobile-debuggingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 133 |
|---|---|
| repo stars | ★ 353 |
| Last updated | August 2, 2026 |
| Repository | jamditis/claude-skills-journalism ↗ |
What it does
Diagnose crashes, layout bugs, and network failures in iOS or Android news apps during pre-release QA and staged rollout validation.
Files
Mobile debugging methodology
Patterns for accessing JavaScript console and debugging web pages on mobile devices without traditional desktop DevTools.
Quick-start: Inject console on any page
Eruda bookmarklet (recommended)
Add this as a bookmark on your mobile browser, then tap it on any page:
javascript:(function(){var script=document.createElement('script');script.src='https://cdn.jsdelivr.net/npm/eruda';document.body.append(script);script.onload=function(){eruda.init();}})();vConsole bookmarklet
javascript:(function(){var script=document.createElement('script');script.src='https://unpkg.com/vconsole@latest/dist/vconsole.min.js';document.body.append(script);script.onload=function(){new VConsole();}})();In-page console tools
Eruda setup
Eruda provides a full DevTools-like experience in a floating panel. Eruda 3.x (3.4.3 current as of 2026-05) is the right baseline; it ships ES2020 syntax and assumes a modern mobile browser.
<!-- CDN (development only) -->
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>
<!-- Conditional loading (recommended for production) -->
<script>
(function() {
var src = 'https://cdn.jsdelivr.net/npm/eruda';
// Only load when ?eruda=true or localStorage flag set
if (!/eruda=true/.test(window.location) &&
localStorage.getItem('active-eruda') !== 'true') return;
var script = document.createElement('script');
script.src = src;
script.onload = function() { eruda.init(); };
document.body.appendChild(script);
})();
</script>// NPM installation
// npm install eruda --save-dev
import eruda from 'eruda';
// Initialize with options
eruda.init({
container: document.getElementById('eruda-container'),
tool: ['console', 'elements', 'network', 'resources', 'info'],
useShadowDom: true,
autoScale: true
});
// Add custom buttons
eruda.add({
name: 'Clear Storage',
init($el) {
$el.html('<button>Clear All Storage</button>');
$el.find('button').on('click', () => {
localStorage.clear();
sessionStorage.clear();
console.log('Storage cleared');
});
}
});
// Remove when done
eruda.destroy();Eruda features:
- Console (logs, errors, warnings)
- Elements (DOM inspector)
- Network (XHR/fetch requests)
- Resources (localStorage, cookies, sessionStorage)
- Sources (page source code)
- Info (page/device information)
- Snippets (saved code snippets)
vConsole setup
Lighter weight alternative, official tool for WeChat debugging.
<!-- CDN -->
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
var vConsole = new VConsole();
</script>// NPM
// npm install vconsole
import VConsole from 'vconsole';
// Initialize with options
const vConsole = new VConsole({
theme: 'dark',
onReady: function() {
console.log('vConsole is ready');
},
log: {
maxLogNumber: 1000
}
});
// Dynamic configuration
vConsole.setOption('log.maxLogNumber', 5000);
// Destroy when done
vConsole.destroy();vConsole features:
- Log panel (console.log, info, warn, error)
- System panel (device info)
- Network panel (XHR, fetch)
- Element panel (DOM tree)
- Storage panel (cookies, localStorage)
Comparison: Eruda vs vConsole
| Feature | Eruda | vConsole |
|---|---|---|
| Size | ~100KB | ~85KB |
| DOM Editing | Yes | View only |
| Network Details | Full | Basic |
| Plugin System | Yes | Yes |
| Dark Theme | Via plugin | Built-in |
| Best For | Full debugging | Quick logging |
Native remote debugging
Chrome DevTools (Android)
# 1. Enable USB debugging on Android
# Settings → Developer Options → USB Debugging = ON
# 2. Connect via USB to computer
# 3. Open Chrome on computer, navigate to:
# chrome://inspect#devices
# 4. Enable "Discover USB devices"
# 5. Accept debugging prompt on Android device
# 6. Click "Inspect" next to the page you want to debugPort forwarding for localhost:
# In chrome://inspect, click "Port forwarding"
# Add: localhost:3000 → localhost:3000
# Now Android Chrome can access your dev server at localhost:3000Android 11+ wireless debugging (no USB needed):
# 1. On the Android device:
# Settings → Developer Options → Wireless debugging = ON
# Tap "Pair device with pairing code"
# Note the IP:PORT and 6-digit code shown
# 2. On the computer (Android Platform Tools 30.0.0+):
adb pair <DEVICE_IP>:<PAIRING_PORT>
# Enter the 6-digit code when prompted
# 3. Connect to the debug port (different from pairing port):
adb connect <DEVICE_IP>:<DEBUG_PORT>
# 4. Verify and proceed to chrome://inspect#devices as usual:
adb devicesWireless debugging persists across reboots once paired, but the adb connect step is needed each session.
Safari Web Inspector (iOS)
# 1. On iPhone/iPad:
# Settings → Safari → Advanced → Web Inspector = ON
# 2. On Mac:
# Safari → Preferences → Advanced → "Show Develop menu" = ON
# 3. Connect device via USB (or enable Wi-Fi debugging)
# 4. Open Safari on Mac:
# Develop → [Device Name] → [Page to debug]
# Wireless debugging (after initial USB setup):
# Develop → [Device] → Connect via NetworkFirefox Remote Debugging (Android)
# 1. On Android Firefox:
# Settings → Advanced → Remote debugging = ON
# 2. On Desktop Firefox:
# Open about:debugging
# 3. Connect Android via USB
# 4. Enable USB devices in about:debugging
# 5. Click "Connect" next to your deviceiOS debugging without Mac
Using ios-webkit-debug-proxy
# Install on Windows (via Scoop)
scoop bucket add extras
scoop install ios-webkit-debug-proxy
# Install on Linux
sudo apt-get install ios-webkit-debug-proxy
# Install on Mac
brew install ios-webkit-debug-proxy
# Run the proxy
ios_webkit_debug_proxy -f chrome-devtools://devtools/bundled/inspector.html
# Connect to http://localhost:9221 to see connected devicesCommercial: Inspect.dev
Inspect.dev provides iOS debugging from Windows/Linux with a familiar DevTools interface.
# Download from https://inspect.dev/
# 1. Install application
# 2. Connect iOS device via USB
# 3. Enable Web Inspector on iOS
# 4. Inspect.dev auto-detects pages
# 5. Click to open DevTools interfaceCloud testing platforms
LambdaTest (freemium)
# LambdaTest provides real device cloud with console access
# Free tier: 100 minutes/month
import requests
# LambdaTest REST API for automation
LAMBDATEST_API = "https://api.lambdatest.com/automation/api/v1"
# For manual testing:
# 1. Go to https://www.lambdatest.com/
# 2. Select device/browser
# 3. Enter URL
# 4. DevTools available in toolbar
# Selenium/Playwright integration for automated console capture
from playwright.sync_api import sync_playwright
def test_on_lambdatest():
with sync_playwright() as p:
# Connect to LambdaTest
browser = p.chromium.connect(
f"wss://cdp.lambdatest.com/playwright?capabilities="
f"{{\"browserName\":\"Chrome\",\"platform\":\"android\"}}"
)
page = browser.new_page()
# Capture console logs
logs = []
page.on('console', lambda msg: logs.append(msg.text()))
page.goto('https://example.com')
browser.close()
return logsBrowserStack
# BrowserStack: $29/month+, 10,000+ real devices
# Selenium 4 removed DesiredCapabilities — pass capabilities via Options instead.
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def get_browserstack_driver():
"""Create BrowserStack WebDriver with console logging."""
options = Options()
bstack_options = {
'deviceName': 'Samsung Galaxy S21',
'osVersion': '11.0',
'realMobile': 'true',
'consoleLogs': 'verbose', # Capture console logs
'networkLogs': 'true',
'userName': 'YOUR_USERNAME',
'accessKey': 'YOUR_KEY'
}
options.set_capability('bstack:options', bstack_options)
options.set_capability('browserName', 'chrome')
driver = webdriver.Remote(
command_executor='https://hub-cloud.browserstack.com/wd/hub',
options=options
)
return driver
# After test, retrieve logs from BrowserStack dashboard or APIProgrammatic console capture
Playwright console capture
const { chromium, devices } = require('playwright');
async function captureConsoleLogs(url) {
const browser = await chromium.launch();
// Emulate mobile device. Playwright ships an updated devices map per
// release; iPhone 15 / Pixel 8 are reasonable 2026 baselines. List with
// `npx playwright devices` if you need an exact name.
const context = await browser.newContext({
...devices['iPhone 15']
});
const page = await context.newPage();
// Capture all console messages
const logs = [];
page.on('console', msg => {
logs.push({
type: msg.type(),
text: msg.text(),
location: msg.location(),
timestamp: new Date().toISOString()
});
});
// Capture page errors
const errors = [];
page.on('pageerror', error => {
errors.push({
message: error.message,
stack: error.stack,
timestamp: new Date().toISOString()
});
});
// Capture failed requests
const failedRequests = [];
page.on('requestfailed', request => {
failedRequests.push({
url: request.url(),
failure: request.failure().errorText,
timestamp: new Date().toISOString()
});
});
await page.goto(url);
await page.waitForLoadState('networkidle');
await browser.close();
return { logs, errors, failedRequests };
}
// Usage
captureConsoleLogs('https://example.com')
.then(result => console.log(JSON.stringify(result, null, 2)));Puppeteer console capture
const puppeteer = require('puppeteer');
async function debugMobilePage(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Set mobile viewport
await page.setViewport({
width: 375,
height: 812,
isMobile: true,
hasTouch: true
});
// Mobile user agent
await page.setUserAgent(
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) ' +
'AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1'
);
// Console capture with full details
page.on('console', async msg => {
const args = await Promise.all(
msg.args().map(arg => arg.jsonValue().catch(() => arg.toString()))
);
console.log(`[${msg.type().toUpperCase()}]`, ...args);
// Get source location
const location = msg.location();
if (location.url) {
console.log(` at ${location.url}:${location.lineNumber}`);
}
});
// Unhandled promise rejections
page.on('pageerror', err => {
console.error('[PAGE ERROR]', err.message);
});
await page.goto(url, { waitUntil: 'networkidle0' });
// Execute JavaScript and capture result
const result = await page.evaluate(() => {
// Check for common mobile issues
return {
viewportWidth: window.innerWidth,
devicePixelRatio: window.devicePixelRatio,
touchSupport: 'ontouchstart' in window,
errors: window.__capturedErrors || []
};
});
console.log('Page info:', result);
await browser.close();
}Error monitoring services
Sentry integration
// npm install @sentry/browser
// Sentry SDK v8+ uses functional integrations; class-based
// `new Sentry.BrowserTracing()` / `new Sentry.Replay()` were
// deprecated in v8 and removed in v9.
import * as Sentry from '@sentry/browser';
Sentry.init({
dsn: 'YOUR_SENTRY_DSN',
environment: 'production',
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration() // Session replay for debugging
],
// Sample rates
tracesSampleRate: 0.1,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
beforeSend(event) {
// Filter or modify events
return event;
}
});
// Manual error capture
try {
riskyOperation();
} catch (error) {
Sentry.captureException(error);
}
// Add context (also functional in v8+)
Sentry.setUser({ id: 'user123' });
Sentry.setTag('page', 'checkout');LogRocket for session replay
// npm install logrocket
import LogRocket from 'logrocket';
LogRocket.init('your-app/your-project');
// Identify user
LogRocket.identify('user123', {
name: 'Test User',
email: 'user@example.com'
});
// Console logs automatically captured
console.log('This appears in LogRocket');
// Manual logging
LogRocket.log('Custom event', { data: 'value' });
// Track errors
LogRocket.captureException(new Error('Something went wrong'));Android screen mirroring with Scrcpy
# Install scrcpy
# Windows: scoop install scrcpy
# Mac: brew install scrcpy
# Linux: apt install scrcpy
# Basic mirroring
scrcpy
# With specific options
scrcpy --max-size 1024 --bit-rate 2M
# Wireless connection (after initial USB)
adb tcpip 5555
adb connect <device-ip>:5555
scrcpy
# Record session
scrcpy --record session.mp4
# Turn off device screen while mirroring
scrcpy --turn-screen-offMobile debugging workflow
┌─────────────────────────────────────────────────────────────────┐
│ MOBILE DEBUGGING DECISION TREE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Q: Do you have physical access to the device? │
│ │ │
│ ├─ YES: Can you connect via USB? │
│ │ │ │
│ │ ├─ Android: Use Chrome DevTools Remote │
│ │ │ chrome://inspect#devices │
│ │ │ │
│ │ └─ iOS: Have a Mac? │
│ │ │ │
│ │ ├─ YES: Use Safari Web Inspector │
│ │ │ │
│ │ └─ NO: Use Inspect.dev or │
│ │ ios-webkit-debug-proxy │
│ │ │
│ └─ NO USB: Inject Eruda/vConsole via bookmarklet │
│ │
│ Q: Remote/production debugging? │
│ │ │
│ ├─ Add conditional Eruda loading │
│ │ (?eruda=true parameter) │
│ │ │
│ └─ Set up Sentry/LogRocket for error monitoring │
│ │
│ Q: Automated testing? │
│ │ │
│ ├─ Playwright/Puppeteer with mobile emulation │
│ │ │
│ └─ Cloud platforms (LambdaTest, BrowserStack) │
│ │
└─────────────────────────────────────────────────────────────────┘Common mobile debugging issues
Touch events not firing
// Check if touch events are supported
eruda.init();
console.log('Touch support:', 'ontouchstart' in window);
console.log('Pointer events:', 'onpointerdown' in window);
// Debug touch events
document.addEventListener('touchstart', e => {
console.log('touchstart', e.touches.length, 'touches');
}, { passive: true });
document.addEventListener('click', e => {
console.log('click at', e.clientX, e.clientY);
});Viewport issues
// Log viewport information
console.log('Viewport:', {
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
outerWidth: window.outerWidth,
outerHeight: window.outerHeight,
devicePixelRatio: window.devicePixelRatio,
orientation: screen.orientation?.type
});
// Check meta viewport
const viewport = document.querySelector('meta[name="viewport"]');
console.log('Viewport meta:', viewport?.content);Performance debugging
// Check performance timing
const perf = performance.getEntriesByType('navigation')[0];
console.log('Page load timing:', {
dns: perf.domainLookupEnd - perf.domainLookupStart,
tcp: perf.connectEnd - perf.connectStart,
request: perf.responseStart - perf.requestStart,
response: perf.responseEnd - perf.responseStart,
domParsing: perf.domInteractive - perf.responseEnd,
domComplete: perf.domComplete - perf.domInteractive,
total: perf.loadEventEnd - perf.navigationStart
});
// Check memory (Chrome only)
if (performance.memory) {
console.log('Memory:', {
usedJSHeapSize: (performance.memory.usedJSHeapSize / 1048576).toFixed(2) + ' MB',
totalJSHeapSize: (performance.memory.totalJSHeapSize / 1048576).toFixed(2) + ' MB'
});
}Platform comparison
| Tool | Cost | Platforms | Setup Difficulty | Best For |
|---|---|---|---|---|
| Eruda | Free | All browsers | Easy (bookmarklet) | Quick debugging |
| vConsole | Free | All browsers | Easy | WeChat apps |
| Chrome Remote | Free | Android only | Medium | Full DevTools |
| Safari Inspector | Free | iOS only | Easy (Mac required) | Full DevTools |
| Inspect.dev | Paid | iOS from any OS | Easy | iOS without Mac |
| LambdaTest | Freemium | All | Easy | Cloud testing |
| BrowserStack | Paid | All | Easy | Real devices |
| Sentry | Freemium | All | Medium | Error monitoring |