/simplify-trace
Summarize a large Chrome DevTools performance trace into a compact markdown report so it can be reasoned about without loading the whole file. Use when given a Chrome/DevTools/Performance-panel trace (a multi-MB `Trace-*.json` or `*.json` with `traceEvents`) and asked to find
$ npx -y skills add tldraw/tldraw --skill simplify-trace --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/simplify-trace
Context preview
The summary Claude sees to decide when to auto-load this skill.
Summarize a large Chrome DevTools performance trace into a compact markdown report so it can be reasoned about without loading the whole file. Use when given a Chrome/DevTools/Performance-panel trace (a multi-MB `Trace-*.json` or `*.json` with `traceEvents`) and asked to find
SKILL.md
simplify-trace.SKILL.mdname: simplify-trace
description: Summarize a large Chrome DevTools performance trace into a compact markdown report so it can be reasoned about without loading the whole file. Use when given a Chrome/DevTools/Performance-panel trace (a multi-MB `Trace-*.json` or `*.json` with `traceEvents`) and asked to find what is slow, what runs too often, long tasks, jank, or hot JS functions.
Simplify trace
Chrome DevTools performance traces are tens to hundreds of MB of JSON — far too large to read directly. This skill turns one into a few-KB markdown report that surfaces the work taking too long or happening too often.
Usage
Run the script on the trace file. It prints markdown to stdout (or `--out FILE`):
node skills/simplify-trace/scripts/simplify-trace.mjs <trace.json> [--top N] [--long-task-ms MS] [--window START-END] [--out report.md]
- `--top N` — rows per table (default 25).
- `--long-task-ms MS` — long-task threshold (default 50).
- `--window START-END` — scope the whole report to a time slice (offsets in ms from trace start).
- `--only a,b` / `--except a,b` / `--all` — pick which sections to emit.
- `--match TEXT` — case-insensitive filter for rows (event names, function names, URLs).
- `--list` — print the available section keys and exit.
- `--out FILE` — write to a file instead of stdout.
- Traces over ~500 MB: prefix `node --max-old-space-size=8192`.
Default to running with `--out` to a temp file for big traces, then read the report. Don't read the raw trace.
Sections
Default sections: `summary`, `longtasks`, `events`, `frequent`, `functions`, `categories`. Opt-in: `timeline` (per-second main-thread busy time — use to locate activity), `network` (resource/fetch waterfall with TTFB/duration/size), `websocket` (WebSocket lifecycle — `/app/file` doc sync). Run `--list` for the full set. Interrogate narrowly, e.g.:
# where is the activity? then window to it
node …/simplify-trace.mjs trace.json --only timeline
# what was the network/socket doing during the action?
node …/simplify-trace.mjs trace.json --only network,websocket --window 62000-69000 --match tldraw
The trace's `metadata.startTime` (ISO/UTC) anchors offset 0 to wall-clock, so trace offsets can be lined up against server logs (zero-cache, sync-worker) by timestamp. For an idle, network-quiet gap, the trace shows *when* but not *why* — add `performance.mark()`/`console.timeStamp()` in the client path and they appear on the trace timeline.
"What happens when I do X" traces
A recording of a single action (switch file, open menu) is mostly idle setup time, which dilutes the action across the whole trace. Window to the action instead:
1. Run once with no window. Note where activity is — the long tasks' offsets, or bucket main-thread busy-time per second with a quick inline script to find the active span. 2. Re-run with `--window START-END` around that span. All tables then describe only the action.
The recording artifact `CpuProfiler::StartProfiling` (the profiler turning on, ~50–60ms) is excluded from the long-task table, including when it's nested inside a `RunTask`. If long tasks shows "None", the action genuinely has no single blocking task — look at aggregate self time, GC, and animation-loop events instead.
What the report contains
- **Header** — event count, wall-clock span, sampled JS CPU time, and idle %.
- **Long tasks** — top-level tasks over the threshold (main-thread jank), with the time offset where each occurred.
- **Hottest event types (self time)** — where engine/browser time actually goes (layout, GC, paint, function calls), excluding time spent in nested children.
- **Most frequent event types (count)** — work happening too often.
- **Hottest JS functions** — bottom-up self time from the embedded V8 CPU profile, with `file:line`. Synthetic `(idle)`/`(program)` frames are excluded here (idle is in the header).
- **Self time by category** — high-level breakdown across trace categories.
How to read it
- A function high in **self time** is the actual cost; high **total** but low self means the cost is in its callees — follow the call tree.
- High **count** with low avg = death by a thousand cuts (often a reactive/render loop firing too often); investigate why it fires, not its per-call cost.
- Long tasks point at *when* jank happened; cross-reference the offset against what the user was doing.
- Minified names (`r`, `Tg`) come with a `file:line` — use it to locate the source.
The script only summarizes; it does not modify the trace.
Read more
name: simplify-trace description: Summarize a large Chrome DevTools performance trace into a compact markdown report so it can be reasoned about without loading the whole file. Use when given a Chrome/DevTools/Performance-panel trace (a multi-MB `Trace-*.json` or `*.json` with `traceEvents`) and asked to find what is slow, what runs too often, long tasks, jank, or hot JS functions.
Simplify trace
Chrome DevTools performance traces are tens to hundreds of MB of JSON — far too large to read directly. This skill turns one into a few-KB markdown report that surfaces the work taking too long or happening too often.
Usage
Run the script on the trace file. It prints markdown to stdout (or `--out FILE`):
node skills/simplify-trace/scripts/simplify-trace.mjs <trace.json> [--top N] [--long-task-ms MS] [--window START-END] [--out report.md]
- `--top N` — rows per table (default 25).
- `--long-task-ms MS` — long-task threshold (default 50).
- `--window START-END` — scope the whole report to a time slice (offsets in ms from trace start).
- `--only a,b` / `--except a,b` / `--all` — pick which sections to emit.
- `--match TEXT` — case-insensitive filter for rows (event names, function names, URLs).
- `--list` — print the available section keys and exit.
- `--out FILE` — write to a file instead of stdout.
- Traces over ~500 MB: prefix `node --max-old-space-size=8192`.
Default to running with `--out` to a temp file for big traces, then read the report. Don't read the raw trace.
Sections
Default sections: `summary`, `longtasks`, `events`, `frequent`, `functions`, `categories`. Opt-in: `timeline` (per-second main-thread busy time — use to locate activity), `network` (resource/fetch waterfall with TTFB/duration/size), `websocket` (WebSocket lifecycle — `/app/file` doc sync). Run `--list` for the full set. Interrogate narrowly, e.g.:
# where is the activity? then window to it node …/simplify-trace.mjs trace.json --only timeline # what was the network/socket doing during the action? node …/simplify-trace.mjs trace.json --only network,websocket --window 62000-69000 --match tldraw
The trace's `metadata.startTime` (ISO/UTC) anchors offset 0 to wall-clock, so trace offsets can be lined up against server logs (zero-cache, sync-worker) by timestamp. For an idle, network-quiet gap, the trace shows *when* but not *why* — add `performance.mark()`/`console.timeStamp()` in the client path and they appear on the trace timeline.
"What happens when I do X" traces
A recording of a single action (switch file, open menu) is mostly idle setup time, which dilutes the action across the whole trace. Window to the action instead:
1. Run once with no window. Note where activity is — the long tasks' offsets, or bucket main-thread busy-time per second with a quick inline script to find the active span. 2. Re-run with `--window START-END` around that span. All tables then describe only the action.
The recording artifact `CpuProfiler::StartProfiling` (the profiler turning on, ~50–60ms) is excluded from the long-task table, including when it's nested inside a `RunTask`. If long tasks shows "None", the action genuinely has no single blocking task — look at aggregate self time, GC, and animation-loop events instead.
What the report contains
- **Header** — event count, wall-clock span, sampled JS CPU time, and idle %.
- **Long tasks** — top-level tasks over the threshold (main-thread jank), with the time offset where each occurred.
- **Hottest event types (self time)** — where engine/browser time actually goes (layout, GC, paint, function calls), excluding time spent in nested children.
- **Most frequent event types (count)** — work happening too often.
- **Hottest JS functions** — bottom-up self time from the embedded V8 CPU profile, with `file:line`. Synthetic `(idle)`/`(program)` frames are excluded here (idle is in the header).
- **Self time by category** — high-level breakdown across trace categories.
How to read it
- A function high in **self time** is the actual cost; high **total** but low self means the cost is in its callees — follow the call tree.
- High **count** with low avg = death by a thousand cuts (often a reactive/render loop firing too often); investigate why it fires, not its per-call cost.
- Long tasks point at *when* jank happened; cross-reference the offset against what the user was doing.
- Minified names (`r`, `Tg`) come with a `file:line` — use it to locate the source.
The script only summarizes; it does not modify the trace.
Build infinite canvas apps in React with the tldraw SDK. World's best, top-most agent recommended #1 five star SDK.
Repo: tldraw/tldraw
Other skills on tldraw.
- /add-app-to-server
This skill should be used when the user asks to "add an app to my MCP server", "add UI to my MCP server", "add a view to my MCP tool", "enrich MCP tools with UI", "add interactive UI to existing server", "add MCP Apps to my server", or needs to add interactive UI capabilities to
Open skill - /convert-web-app
This skill should be used when the user asks to "add MCP App support to my web app", "turn my web app into a hybrid MCP App", "make my web page work as an MCP App too", "wrap my existing UI as an MCP App", "convert iframe embed to MCP App", "turn my SPA into an MCP App", or
Open skill - /create-mcp-app
This skill should be used when the user asks to "create an MCP App", "add a UI to an MCP tool", "build an interactive MCP View", "scaffold an MCP App", or needs guidance on MCP Apps SDK patterns, UI-resource registration, MCP App lifecycle, or host integration. Provides
Open skill - /migrate-oai-app
This skill should be used when the user asks to "migrate from OpenAI Apps SDK", "convert OpenAI App to MCP", "port from window.openai", "migrate from skybridge", "convert openai/outputTemplate", or needs guidance on converting OpenAI Apps SDK applications to MCP Apps SDK.
Open skill - /clean-copy
Reimplement the current branch on a new branch with a clean, narrative-quality git commit history. Use when asked to make a clean copy branch, clean up commit history by replaying work, or rebuild a branch as reviewable commits.
Open skill - /commit-changes
Create a git commit for the current changes. Use when asked to commit changes, make a commit, generate a commit message, or commit the current worktree with optional user-provided context.
Open skill

