AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Metal Gpu Debug

skill-rudybear-metal-ai-skill-metal-gpu-debug · by rudybear

>

No reviews yet
0 installs
33 views
0.0% view→install

Install

$ agentstack add skill-rudybear-metal-ai-skill-metal-gpu-debug

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-rudybear-metal-ai-skill-metal-gpu-debug)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
6mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Metal Gpu Debug? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Metal GPU Debugging & Profiling Skill

Overview

This skill enables Metal GPU profiling, debugging, and shader analysis on macOS using Apple's command-line toolchain. The primary tools are:

  • xctrace — CLI for Instruments; records Metal System Traces, exports GPU data as XML
  • xcrun metal — Metal shader compiler toolchain (compile, archive, link)
  • Metal environment variables — validation layers, Performance HUD, programmatic capture
  • log — macOS unified logging for Metal HUD and validation output
  • parse_gputrace.py — CLI tool for extracting buffer/texture data from .gputrace captures

Prerequisites

Before any Metal debugging, verify the environment:

# Check Xcode is installed (full Xcode, not just Command Line Tools)
xcode-select -p
# Expected: /Applications/Xcode.app/Contents/Developer

# Check xctrace is available
xcrun xctrace version

# Check Metal compiler
xcrun -sdk macosx metal --version

# List available GPU devices (requires a Swift/ObjC helper or Python)
system_profiler SPDisplaysDataType | grep -A5 "Chipset\|Metal"

IMPORTANT: xctrace and Metal tools require full Xcode, not just Command Line Tools.

1. Automated Session Lifecycle

Every Metal debugging session follows a strict pipeline: Doctor → Record → Export → Parse → Analyze → Report → Cleanup. Claude should execute this pipeline autonomously, not just suggest commands.

Step 0: Doctor — Verify environment

Run this FIRST before any debugging session. If any check fails, stop and tell the user what's missing.

# Create working directories
mkdir -p ./traces/analysis

# Verify toolchain
xcode-select -p                          # Must show Xcode.app path, NOT CommandLineTools
xcrun xctrace version                    # Must succeed
xcrun -sdk macosx metal --version        # Must succeed
system_profiler SPDisplaysDataType | grep -i "metal\|chipset"  # GPU info

# For iOS: check connected devices
xcrun xctrace list devices 2>/dev/null   # List all available targets

# Check parse helper is available
python3 -c "import xml.etree.ElementTree" 2>/dev/null && echo "XML parser OK"

If xcode-select -p returns /Library/Developer/CommandLineTools, tell the user:

Xcode Command Line Tools is installed but full Xcode is required.
Install from: https://developer.apple.com/xcode/
Then run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

Step 1: Record — Capture a Metal System Trace

Choose the right recording mode based on the user's request:

# MODE A: Launch and profile (most common)
xcrun xctrace record \
  --template 'Metal System Trace' \
  --time-limit 10s \
  --no-prompt \
  --output ./traces/capture.trace \
  --launch -- /path/to/app [args...]

# MODE B: Attach to running process
xcrun xctrace record \
  --template 'Metal System Trace' \
  --attach  \
  --time-limit 10s \
  --no-prompt \
  --output ./traces/capture.trace

# MODE C: With validation enabled (for debugging errors)
xcrun xctrace record \
  --template 'Metal System Trace' \
  --env MTL_DEBUG_LAYER=1 \
  --env MTL_SHADER_VALIDATION=1 \
  --time-limit 10s \
  --no-prompt \
  --output ./traces/capture.trace \
  --launch -- /path/to/app

# MODE D: iOS device (over USB)
xcrun xctrace record \
  --template 'Metal System Trace' \
  --device '' \
  --attach  \
  --time-limit 10s \
  --no-prompt \
  --output ./traces/capture.trace

Decision guide:

  • User says "profile my app" → Mode A
  • User says "it's already running" → Mode B
  • User says "I'm getting errors" or "something is wrong" → Mode C
  • User mentions iPhone/iPad → Mode D

IMPORTANT: Always use --no-prompt for automation. Always use --time-limit (default 10s, adjust if user specifies). Always use --output with explicit path.

Step 2: Export — Extract structured data from trace

First discover what's in the trace, then export the relevant tables.

# 2a. Get table of contents (ALWAYS do this first)
xcrun xctrace export --input ./traces/capture.trace --toc \
  > ./traces/analysis/toc.xml

# 2b. Show available schemas to decide what to export
grep 'schema=' ./traces/analysis/toc.xml

# 2c. Export Metal GPU driver events (primary data source)
xcrun xctrace export --input ./traces/capture.trace \
  --output ./traces/analysis/gpu_events.xml \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="metal-driver-event-intervals"]'

# 2d. Export GPU hardware counters (if available — Apple Silicon)
xcrun xctrace export --input ./traces/capture.trace \
  --output ./traces/analysis/gpu_counters.xml \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="gpu-counter-intervals"]' \
  2>/dev/null || echo "No GPU counter data in this trace"

# 2e. Export Metal GPU execution intervals (if available)
xcrun xctrace export --input ./traces/capture.trace \
  --output ./traces/analysis/gpu_intervals.xml \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="metal-gpu-intervals"]' \
  2>/dev/null || echo "No GPU interval data in this trace"

Schema availability varies by Xcode version, template, and GPU. Always check the TOC first and export what's there. Don't fail if a schema is missing — report what was found.

Step 3: Parse — Convert XML to structured data

Use the parse_trace.py helper (included in this repo) or inline Python to extract actionable data.

# Summary of what was captured
python3 parse_trace.py ./traces/analysis/gpu_events.xml --summary

# Get structured data as JSON
python3 parse_trace.py ./traces/analysis/gpu_events.xml --format json --limit 50

# Get as TSV for scanning
python3 parse_trace.py ./traces/analysis/gpu_events.xml --format tsv --limit 30

# If parse_trace.py is not available, use inline Python:
python3 16ms = below 60fps, >8ms = below 120fps)
- Large wire memory events (excessive per-frame resource allocation)
- Gaps between GPU submissions (CPU-bound)
- Long shader execution intervals (complex shaders)
- Imbalanced encoder durations (one pass dominating)

**Validation errors:**
- Pattern-match stderr and log output for Metal error codes
- Classify errors: API misuse vs shader bug vs resource issue
- Map errors to specific command encoders via labels

**Shader issues:**
- Compile-time warnings/errors from `xcrun metal`
- Runtime validation errors from `MTL_SHADER_VALIDATION`

### Step 5: Report — Present findings to user

Structure the report as:
1. **Environment**: GPU model, macOS version, device (Mac/iOS)
2. **Summary**: Total events, recording duration, overall health
3. **Key findings**: Sorted by severity (errors → warnings → info)
4. **Specific data**: Relevant numbers, event counts, durations
5. **Recommendations**: Concrete next steps

### Step 6: Cleanup

```bash
# Remove large trace files when analysis is complete
# (only if user doesn't need the raw trace)
rm -rf ./traces/capture.trace

# Keep analysis outputs for reference
ls -la ./traces/analysis/

Complete automated workflow example

This is what Claude should execute end-to-end when a user says "profile my Metal app":

#!/bin/bash
set -e
APP_PATH="$1"
TRACE_DIR="./traces"
ANALYSIS_DIR="$TRACE_DIR/analysis"

# Doctor
mkdir -p "$ANALYSIS_DIR"
xcode-select -p >/dev/null 2>&1 || { echo "ERROR: Xcode not found"; exit 1; }
xcrun xctrace version >/dev/null 2>&1 || { echo "ERROR: xctrace not available"; exit 1; }

# Record
echo "Recording Metal System Trace (10s)..."
xcrun xctrace record \
  --template 'Metal System Trace' \
  --time-limit 10s \
  --no-prompt \
  --output "$TRACE_DIR/capture.trace" \
  --launch -- "$APP_PATH"

# Export TOC
echo "Exporting trace data..."
xcrun xctrace export --input "$TRACE_DIR/capture.trace" --toc \
  > "$ANALYSIS_DIR/toc.xml"

# Export all available Metal tables
for schema in metal-driver-event-intervals gpu-counter-intervals metal-gpu-intervals; do
  if grep -q "schema=\"$schema\"" "$ANALYSIS_DIR/toc.xml"; then
    echo "Exporting $schema..."
    xcrun xctrace export --input "$TRACE_DIR/capture.trace" \
      --output "$ANALYSIS_DIR/${schema}.xml" \
      --xpath "/trace-toc/run[@number=\"1\"]/data/table[@schema=\"$schema\"]"
  fi
done

# Parse and summarize
echo "Analyzing..."
for xml in "$ANALYSIS_DIR"/*.xml; do
  [ "$xml" = "$ANALYSIS_DIR/toc.xml" ] && continue
  echo "=== $(basename "$xml") ==="
  python3 parse_trace.py "$xml" --summary 2>/dev/null || \
    python3 -c "
import xml.etree.ElementTree as ET
tree = ET.parse('$xml')
rows = tree.getroot().findall('.//row')
print(f'  Rows: {len(rows)}')
"
done

echo "Done. Analysis files in $ANALYSIS_DIR/"

Parallel workflows: Validation + Profiling + Logs

Claude can run multiple debugging streams simultaneously for maximum signal:

# Record trace with all validation layers AND HUD logging in one shot
xcrun xctrace record \
  --template 'Metal System Trace' \
  --env MTL_DEBUG_LAYER=1 \
  --env MTL_SHADER_VALIDATION=1 \
  --env MTL_HUD_ENABLED=1 \
  --env MTL_HUD_LOGGING_ENABLED=1 \
  --time-limit 10s \
  --no-prompt \
  --output ./traces/full_debug.trace \
  --launch -- /path/to/app 2> ./traces/analysis/stderr.log &

TRACE_PID=$!

# Simultaneously capture Metal logs from unified log
log stream --predicate 'subsystem == "com.apple.Metal"' \
  --timeout 15 > ./traces/analysis/metal_log.txt 2>/dev/null &

LOG_PID=$!

# Wait for trace to finish
wait $TRACE_PID

# Give log stream a moment then stop it
sleep 2
kill $LOG_PID 2>/dev/null

# Now analyze ALL data sources:
echo "=== Validation Errors (stderr) ==="
grep -i "error\|warning\|invalid\|fault" ./traces/analysis/stderr.log || echo "None"

echo "=== Metal Log Entries ==="
wc -l  \
  --time-limit 5s \
  --output trace.trace

# Launch and profile
xcrun xctrace record \
  --template 'Metal System Trace' \
  --time-limit 5s \
  --output trace.trace \
  --launch -- /path/to/your/app [args...]

# With environment variables (e.g., enable validation)
xcrun xctrace record \
  --template 'Metal System Trace' \
  --env MTL_DEBUG_LAYER=1 \
  --env MTL_SHADER_VALIDATION=1 \
  --time-limit 5s \
  --output trace.trace \
  --launch -- /path/to/your/app

Key options:

  • --time-limit 5s — auto-stop after duration (supports ms, s, m, h)
  • --attach PID — attach to running process
  • --all-processes — trace all Metal apps system-wide
  • --env VAR=value — set environment variables for launched process
  • --target-stdout - — redirect app stdout to terminal
  • --no-prompt — skip prompts (useful in scripts)

Other useful templates

# List all available templates
xcrun xctrace list templates
# Key Metal-relevant templates:
#   - Metal System Trace    (GPU timeline, driver events, counters)
#   - Game Performance       (Metal + display + thermal)
#   - Counters               (hardware performance counters)
#   - GPU                    (GPU-focused template, if available)

Export trace data as XML

# See what's in the trace (table of contents)
xcrun xctrace export --input trace.trace --toc

# Export Metal driver events (GPU work intervals, wire memory, etc.)
xcrun xctrace export --input trace.trace \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="metal-driver-event-intervals"]'

# Export to file instead of stdout
xcrun xctrace export --input trace.trace \
  --output metal_events.xml \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="metal-driver-event-intervals"]'

# Export GPU counter data
xcrun xctrace export --input trace.trace \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="gpu-counter-intervals"]'

Common Metal table schemas

| Schema | Contains | |--------|----------| | metal-driver-event-intervals | Metal driver events (GPU work, wire memory, resource events) | | gpu-counter-intervals | Hardware GPU performance counters | | metal-gpu-intervals | GPU execution intervals per encoder | | time-profile | CPU time profiling samples |

TIP: Always run --toc first to see available schemas — they vary by template, Xcode version, and GPU.

Parse exported XML

The XML uses a reference system to avoid duplication. Nodes with id attributes are originals; nodes with ref attributes point back to them.

# Quick extraction with xmllint or python
xcrun xctrace export --input trace.trace \
  --xpath '/trace-toc/run[@number="1"]/data/table[@schema="metal-driver-event-intervals"]' \
  | python3 -c "
import sys, xml.etree.ElementTree as ET
tree = ET.parse(sys.stdin)
for row in tree.findall('.//row'):
    print([col.get('fmt', col.text or '') for col in row])
"

4. Metal Validation Layers

Runtime error detection for Metal API misuse and shader bugs.

Enable via environment variables

# API Validation — catches Metal API misuse
export MTL_DEBUG_LAYER=1

# Shader Validation — instruments shaders to detect GPU-side errors
export MTL_SHADER_VALIDATION=1

# Combined: launch app with both
MTL_DEBUG_LAYER=1 MTL_SHADER_VALIDATION=1 /path/to/your/app

Enable via xctrace

xcrun xctrace record \
  --template 'Metal System Trace' \
  --env MTL_DEBUG_LAYER=1 \
  --env MTL_SHADER_VALIDATION=1 \
  --time-limit 10s \
  --output validated.trace \
  --launch -- /path/to/your/app

Read validation errors

Validation errors appear in stderr and in macOS unified log:

# Stream Metal validation errors live
log stream --predicate 'subsystem == "com.apple.Metal"' --level error

# Search recent logs
log show --predicate 'subsystem == "com.apple.Metal"' --last 5m

Programmatic validation log access

If you're writing Metal code, commandBuffer.logs provides structured error info after completion — encoder label, debug location (file + line), and error classification.

5. Metal Performance HUD

Real-time overlay showing FPS, frame time, GPU time, memory usage.

Enable

# Per-process via environment variable
MTL_HUD_ENABLED=1 /path/to/your/app

# System-wide (all Metal apps)
/bin/launchctl setenv MTL_HUD_ENABLED 1
# Disable:
/bin/launchctl unsetenv MTL_HUD_ENABLED

# Enable HUD data logging to syslog
MTL_HUD_ENABLED=1 MTL_HUD_LOGGING_ENABLED=1 /path/to/your/app

Parse HUD log data

When MTL_HUD_LOGGING_ENABLED=1, metrics are logged to the system log:

# Stream HUD metrics
log stream --predicate 'subsystem == "com.apple.Metal" AND category == "HUD"'

# Export recent HUD data
log show --predicate 'subsystem == "com.apple.Metal" AND category == "HUD"' --last 1m

HUD metrics include: FPS, present interval (frame time), GPU time, process memory, GPU memory, display refresh rate, direct vs composited rendering path.

6. Programmatic Frame Capture (.gputrace)

Capture Metal frames to .gputrace files without Xcode attached, then inspect buffer/texture data from CLI.

Via environment variables (MoltenVK / any Metal app)

# For Vulkan apps via MoltenVK:
export METAL_CAPTURE_ENABLED=1
export MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE=2          # 1=device lifecycle, 2=first frame
export MVK_CONFIG_AUTO_GPU_CAPTURE_OUTPUT_FILE=/tmp/capture.gputrace
/path/to/vulkan/app

# For native Metal apps (requires Info.plist MetalCaptureEnabled=true
# or METAL_CAPTURE_ENABLED=1 environment variable):
METAL_CAPTURE_ENABLED=1 /path/to/metal/app

Via MTLCaptureManager (in-app)

For apps you control, add capture support using MTLCaptureManager. See capture_frame.swift for a complete example. The key pattern for adding capture to an existing app:

let captureManager = MTLCaptureManager.shared()
if captureManager.supportsDestination(.gpuTraceDocument) {
    let descriptor = MTLCaptureDescriptor()
    descriptor.captureObject = device
    descriptor.destination = .gpuTraceDocument
    descriptor.outputURL = URL(fileURLWithPath: "./capture.gputrace")
    try captureManager.startCapture(with: descriptor)

    // ... encode and submit Metal work ...

    captureManager.stopCapture()
}

Run with: METAL_CAPTURE_ENABLED=1 ./your_app

Open .gputrace in Xcode


…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [rudybear](https://github.com/rudybear)
- **Source:** [rudybear/metal-ai-skill](https://github.com/rudybear/metal-ai-skill)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.