xdebug-profiling

A guide to using Xdebug in DDEV, a local development environment, to trace PHP requests and measure their performance.

In plain words
What is it for?
It helps create function-call traces for debugging and Cachegrind profiles for finding performance bottlenecks.
Why use it?
It helps show where a PHP error starts and which functions are making a page or request slow.

Skill for Claude CodeCodex

Install

Getting it into your agent

One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.

agentmods
npx agentmods add skills/trebormc/drupal-ai-agents/xdebug-profiling
Any agent
npx skills add trebormc/drupal-ai-agents --skill xdebug-profiling
Clone the repo
git clone --depth 1 https://github.com/trebormc/drupal-ai-agents

Made for: Claude Code, Codex.

Per session 203 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 2,362 The whole file, excluding the scripts and references it only reads on demand.
Security scan C 2 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5 $0.00203 $0.02362
Opus 5 $0.00102 $0.01181
Sonnet 5 $0.00041 $0.00472
Haiku 4.5 $0.00020 $0.00236

Measured 3d ago against content hash 98e97a043ad9, method: parsed. Prices are Anthropic first-party input rates as of 2026-08-30, from the pricing page.

Security

Grade C, and why

xdebug-profiling scanned grade C with 2 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 3d ago.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Recursive force deletehighDestructive command

rm -rf with a variable or a broad path is one typo away from removing the wrong tree.

ssh web rm -rf /tmp/xdebug/*

Makes network callslowCapability

Not a fault in itself. Listed so you know the mod talks to something, and to what.

# Via curl inside web container (or Playwright with ?XDEBUG_TRIGGER=1)
.claude/skills/xdebug-profiling/SKILL.md · 225 lines

How it starts

The opening of the file, as written. The whole thing — 225 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Environment

All commands run via ssh web. Xdebug output is stored inside the web container at /tmp/xdebug/. Use $DDEV_DOCROOT for paths.

Two Modes

Mode Use for Output Analysis
trace Debug errors, trace execution path .xt files (function calls, args, returns) Read trace, find error origin
profile Performance bottlenecks, slow pages cachegrind.out.* files Find slowest/most-called functions

Setup (run once per session)

ssh web mkdir -p /tmp/xdebug

# Verify Xdebug is available — expected output: "xdebug"
ssh web php -m | grep -i xdebug

If the grep output is EMPTY, do not invent paths: ask the user to run ddev xdebug on on the HOST, then re-check.

After EVERY config change below, verify it took effect:

ssh web php -i | grep "xdebug.mode"

Workflow A: Trace Mode (Debug Errors)

Step 1: Enable trace

ssh web bash -c "
  PHP_VER=\$(php -r 'echo PHP_MAJOR_VERSION.\".\".PHP_MINOR_VERSION;')
  cat > /etc/php/\${PHP_VER}/fpm/conf.d/99-xdebug-custom.ini <<'EOF'
xdebug.mode=trace
xdebug.start_with_request=trigger
xdebug.output_dir=/tmp/xdebug
xdebug.trace_format=1
xdebug.collect_return=1
xdebug.collect_assignments=1
xdebug.trace_output_name=trace.%t.%p
EOF
  kill -USR2 \$(pgrep -o php-fpm)
"

Step 2: Trigger the request

# Via curl inside web container (or Playwright with ?XDEBUG_TRIGGER=1)
ssh web curl -s -b 'XDEBUG_TRIGGER=1' 'http://localhost/the-page' -o /dev/null -w '%{http_code}'

Step 3: Analyze the trace

3a. Write the analyzer script ONCE per session (copy this block EXACTLY — the quoted 'EOF' prevents any variable expansion):

ssh web "cat > /tmp/analyze-trace.php" <<'EOF'
<?php
// Usage: php /tmp/analyze-trace.php /tmp/xdebug/trace.XXXX.xt
$lines = file($argv[1]);
$entries = []; $calls = [];
foreach ($lines as $line) {
  $f = explode("\t", trim($line));
  if (count($f) < 5) continue;
  if ($f[2] === '0' && isset($f[5])) {
    $entries[$f[1]] = ['name' => $f[5], 'start' => (float) $f[3], 'file' => $f[8] ?? '', 'line' => $f[9] ?? ''];
  }
  elseif ($f[2] === '1' && isset($entries[$f[1]])) {
    $d = (float) $f[3] - $entries[$f[1]]['start'];
    $n = $entries[$f[1]]['name'];
    if (!isset($calls[$n])) {
      $calls[$n] = ['count' => 0, 'total' => 0, 'file' => $entries[$f[1]]['file'], 'line' => $entries[$f[1]]['line']];
    }
    $calls[$n]['count']++;
    $calls[$n]['total'] += $d;
  }
}
uasort($calls, fn($a, $b) => $b['total'] <=> $a['total']);
printf("%-45s %6s %10s %s\n", 'Function', 'Calls', 'Time(s)', 'Location');
echo str_repeat('-', 90) . "\n";
foreach (array_slice($calls, 0, 25) as $n => $d) {
  printf("%-45s %6d %10.4f %s:%s\n", substr($n, 0, 45), $d['count'], $d['total'], basename($d['file']), $d['line']);
}
EOF

Read the full file on GitHub · 225 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. 3d ago First seen · 225 lines · 203 tokens per session scan C 98e97a043ad9

Subscribe to this mod's changes

xdebug-profiling is a skill published in the GitHub repository trebormc/drupal-ai-agents (10 stars, last pushed 1mo ago), licensed Apache-2.0. It adds 203 tokens to every session and 2,362 once invoked, about $0.0010 per session on Opus 5. A static security scan graded it C with 2 findings (recursive force delete, makes network calls). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.

Related

Other skills, from other repositories

laravel-actions

Build, refactor, and troubleshoot Laravel Actions using lorisleiva/laravel-actions. Use when implementing reusable action classes (object/controller/job/listener/command), converting service classes/controllers/jobs into actions, orchestrating workflows via faked actions, or debugging action entrypoints and wiring.

coollabsio/coolify · 62 tokens

laravel-specialist

Build and configure Laravel 10+ applications, including creating Eloquent models and relationships, implementing Sanctum authentication, configuring Horizon queues, designing RESTful APIs with API resources, and building reactive interfaces with Livewire. Use when creating Laravel models, setting up queue workers…

Jeffallan/claude-skills · 86 tokens

laravel-best-practices

Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code. This includes creating or modifying controllers, models, migrations, form requests, policies, jobs, scheduled commands, service classes, and Eloquent queries. Triggers for N+1 and query performance issues, caching strategies, authorization…

laravel/boost · 114 tokens

routes

Generate route configuration for CatchAdmin module.

JaguarJack/catch-admin · 10 tokens

create-powergrid-plugin

Create a complete PowerGrid plugin from scratch, including PHP class, Column macro, Blade view, Alpine.js component, and registration.

Power-Components/livewire-powergrid · 31 tokens

create-module

Scaffold a new Marko module — a self-contained Composer package with composer.json, namespaced src/, and Pest tests. Use this skill whenever the user asks to create, add, or scaffold a new Marko module or package. Concrete triggers: 'create a module named payment', 'scaffold an acme/blog package', 'add a new module…

marko-php/marko · 120 tokens