Agent skill

Profiling Client Performance

by TriliumNext in TriliumNext/Trilium

A skill your agent uses when diagnosing a hard client-side performance problem in Trilium — a stutter while typing, janky dragging, a slow widget, a periodic freeze, "why does this only lag on my…

AGPL-3.0Auto-check passedDevelopment

Install Profiling Client Performance

skills CLI
$ npx skills add TriliumNext/Trilium --skill profiling-client-performance -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install TriliumNext/Trilium profiling-client-performance --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/TriliumNext/Trilium.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/profiling-client-performance .claude/skills/profiling-client-performance && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
profiling-client-performance
GitHub stars
38k
Token cost
~1.9k tokens
SKILL.md length
880 words
Files
2
Skills in repo
22
Repo updated
First seen
Licence
AGPL-3.0

At a glance

A skill your agent uses when diagnosing a hard client-side performance problem in Trilium — a stutter while typing, janky dragging, a slow widget, a periodic freeze, "why does this only lag on my…

  • Works in 2 steps: Find the subsystem: analyze a trace → Measure the cost: debug_perf
  • Diagnosing a hard client-side performance problem in Trilium — a stutter while typing
  • SKILL.md covers 1. Find the subsystem: analyze…, 2. Measure the cost: debug_perf, Interpreting what comes back and Method, plus 2 more sections
  • Runs JavaScript scripts from its folder; calls node, npx and pnpm

What it does

Profiling Client Performance is an agent skill from TriliumNext/Trilium. Use when diagnosing a hard client-side performance problem in Trilium — a stutter while typing, janky dragging, a slow widget, a periodic freeze, "why does this only lag on my real database?". Covers reading a recorded Chrome DevTools trace to find which subsystem is burning the main thread, then the in-app debugperf profiler to measure what a specific operation costs. Includes analyze-trace.mjs; don't write a new trace parser or a throwaway timing harness.

Its SKILL.md is about 1.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 1 other file.

It sits in Development, covering Performance optimization and Browser testing. It works with Chrome DevTools. The repository describes itself as: Build your personal knowledge base with Trilium Notes. The licence is AGPL-3.0.

When your agent uses it

  • Diagnosing a hard client-side performance problem in Trilium — a stutter while typing
  • A periodic freeze
  • Why does this only lag on my real database?

Example prompts

  • “why does this only lag on my real database?”
  • “/profiling-client-performance”

Requirements

  • Node.js

Workflow steps

2 steps, taken from the step headings in SKILL.md.

  1. Find the subsystem: analyze a trace
  2. Measure the cost: debug_perf

What it can do on your machine

Read from SKILL.md and the folder at commit cac2b4f. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships script files (JavaScript), which the agent can run.

    Shell commands in SKILL.md call:

    • node
    • npx
    • pnpm

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npx and pnpm, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Profiling Client Performance loads about 1.9k tokens when it runs. Until then it costs about 123 tokens; SKILL.md has 880 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~123
When it runs · the whole SKILL.md, loaded when a task matches
~1.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from TriliumNext/Trilium at commit cac2b4f, republished under its AGPL-3.0 licence (© TriliumNext). 880 words, ~1,880 tokens.

Download SKILL.mdSave it as .claude/skills/profiling-client-performance/SKILL.md (or your agent's skills folder). This skill also uses 1 other file; get the full folder from GitHub.
name
profiling-client-performance
description
Use when diagnosing a hard client-side performance problem in Trilium — a stutter while typing, janky dragging, a slow widget, a periodic freeze, "why does this only lag on my real database?". Covers reading a recorded Chrome DevTools trace to find which subsystem is burning the main thread, then the in-app `debug_perf` profiler to measure what a specific operation costs. Includes analyze-trace.mjs; don't write a new trace parser or a throwaway timing harness.

Profiling the Trilium client

Two tools, used in order. Skipping the first wastes the second on the wrong subsystem.

readsanswersneeds
analyze-trace.mjsa recorded .json/.json.gz tracewhich subsystem is burning the main threadnothing — works on production builds and traces someone else recorded
debug_perfa live sessionwhat does this specific operation cost, and how oftensource changes + a dev build

1. Find the subsystem: analyze a trace

Ask for a DevTools Performance recording (Performance panel → record → download). Then:

bash
# A 90MB trace needs the bigger heap; the default one dies parsing it.
node --max-old-space-size=8192 .claude/skills/profiling-client-performance/analyze-trace.mjs <trace> summary
node ... analyze-trace.mjs <trace> spikes      # self time inside the long tasks only — usually the answer
node ... analyze-trace.mjs <trace> profile 25  # top self/total time across the whole trace
node ... analyze-trace.mjs <trace> timeline    # ASCII busy-per-bucket, for spotting a beat

spikes is the one to reach for: a stutter is the long tasks, and aggregating self time inside them with a stack attached names the culprit directly. summary prints each long task with the gap from the previous one — a steady gap means a timer or a debounce, an erratic one means the user is driving it.

Two trace-format traps the script already handles, and which will silently mislead a hand-rolled parser:

  • Profiles are numbered per process. Every process starts its Profile/ProfileChunk ids at the same value, so keying on id alone merges the browser process's profile into the renderer's and attributes main-process frames to page code.
  • The GPU process's vsync thread is busy for the whole trace by design. Picking "the busiest thread" hands you 11.5s of nothing. The renderer main thread is CrRendererMain.

Chunk names in a production trace are hashed (board-B_DI2aI3.js). Resolve them by extracting from the installed app rather than guessing:

bash
npx --yes @electron/asar list "<install>/resources/app.asar" | grep <chunk>
# then extract via the node API with path.join("public","src",<chunk>) — the CLI mangles the separators

2. Measure the cost: debug_perf

apps/client/src/services/debug_perf.ts. Nothing calls into it by default — that is deliberate. Add call sites for as long as the investigation takes, then take them back out.

ts
import { perfCount, perfSpan } from "../services/debug_perf";

perfCount("board.card.render");                    // how often
const end = perfSpan("board.getBoardData");        // how long; end() also returns the ms
try { ... } finally { end(); }

Adding the first call site is what pulls the module into the bundle, which is also what puts triliumPerf on window. There is nothing else to arm. Then, in the devtools console:

js
triliumPerf.enable()    // also starts reporting stalls
// ...reproduce the problem...
triliumPerf.report()    // console.table of calls / total / avg / max

Count before you time. A counter is one line and often reframes the problem outright: "4858 card renders" divided by 949 cards is six full redraws, not the one-per-pointer-move that had been assumed, which changes what is worth fixing.

Reproducing against a real database

Most of these only appear at real data volumes. Point a dev build at a copy of the user's data:

powershell
$env:TRILIUM_DATA_DIR = "C:\path\to\a\copy-of-trilium-data"
pnpm desktop:start

Interpreting what comes back

A STALL line is not the cost of an operation. It is the gap between animation frames, so on a saturated main thread it spans every operation that fell inside one contiguous busy period. Two runs are then not comparable — a "regression" from 434ms to 1196ms was two redraws landing in one stall rather than anything getting slower. For "what did this cost", use a span; only its returned duration is per-operation.

Check for saturation first. summary prints it. Above ~60% busy, stall durations stop meaning much and the timeline stops having gaps to read.

Long Tasks are Chromium-only. Firefox has no longtask entry type, and observe({ entryTypes }) drops an unrecognized one with a console warning instead of throwing — so a naive observer reports nothing at all, which reads as "no stalls happened". debug_perf checks supportedEntryTypes and falls back to an animation-frame watchdog, and says which it is using.

To separate JavaScript from layout and paint, close a span in a useLayoutEffect: it runs after Preact has mutated the DOM but before the browser paints. Compare its total against the stall total. Most of the stall inside the span means JS; most of it outside means layout/paint, and no amount of memoization will help.

Dev-build numbers are inflated but proportionate — roughly 1.5× against a production Electron build in practice. Ratios and rankings transfer; absolute figures don't. Firefox's frame-gap watchdog is coarser than Chromium's Long Tasks, so prefer the desktop app for final numbers.

Show full SKILL.md (272 more words)Show less

Method

Measure before predicting, and say which you are doing. Predictions from reading code have a poor record here: "keying the fragment will speed up dragging" (no measurable change), "splitting the context alone will change nothing" (halved the average stall), "the dragover DOM measuring is the hot path" (12ms out of 5655ms). Every change that actually moved a number came from a measurement first. When you must guess, state it as a hypothesis and name the number that would confirm it.

A null result is a result. Land it if it's a correctness fix, say plainly that it bought nothing, and put that in the commit message.

Patterns that keep showing up

  • A context change re-renders every consumer, memo included. A component reading a context that changes often cannot be memoized out of the render path at all. Split volatile state into its own context first; memo() is inert until then.
  • Intl.* constructors are ~30× the cost of using the formatter. Anything constructing one per row per render is the leaf cost. apps/client/src/utils/formatters.ts memoizes on locale + option set; formatters.bench.ts guards it.
  • Change-detection predicates that are broader than they look. LoadResults.getNoteIds() returns every note in the change set whatever changed about it, so a check meaning "did the title change?" also fires on every content autosave.
  • Keys belong on the element the .map() returns. A key on a child inside a returned fragment identifies nothing, and the list reconciles positionally.

When done

Take the call sites out — grep -rn "perfSpan\|perfCount\|perfLog\|perfTime" apps/client/src should return only debug_perf.ts itself. Leaving them behind gathers measurements nobody reads. The module stays; it is the tool, not the measurement.

© TriliumNext, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 1 other file in .claude/skills/profiling-client-performance of TriliumNext/Trilium.

  • SKILL.md
  • analyze-trace.mjs

Open the folder on GitHubat commit cac2b4f

Compare with similar skills

Profiling Client Performance next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Profiling Client Performance compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Profiling Client Performance this skillTriliumNext/Trilium38k—~1.9kAutomated safety check: PassAGPL-3.0
Browser Testing with Chrome DevToolsaddyosmani/agent-skills103k4 repos~3.5kAutomated safety check: WarnMIT
Go Pedantrychromedp/chromedp13k—~3.7kAutomated safety check: PassMIT
Docs AuthoringTracecatHQ/tracecat3.8k—~3.1kAutomated safety check: NotesAGPL-3.0
Extension Puppeteer Debuggingmengxi-ream/read-frog10k—~2kAutomated safety check: NotesGPL-3.0
Enso CdpJ3n5en/EnsoCode119—~1.3kAutomated safety check: PassMIT

Similar skills

  • Connects an agent to a real Chrome instance through the Chrome DevTools MCP server, so it can inspect the DOM, read console errors and profile performance directly.

    103k GitHub starsUsed in 4 repos~3.5k tokens
    Testing & QAAuto-check: warnings
  • Go Pedantry

    chromedp/chromedp

    This skill should be used when the user is writing Go code and needs guidance on Go-specific pedantry: error wrapping with fmt.Errorf and %w, interface design (accept interfaces return structs)…

    13k GitHub stars~3.7k tokensUpdated 2 days ago
    DevelopmentAuto-check passed
  • Docs Authoring

    TracecatHQ/tracecat

    A skill your agent uses when adding or updating documentation pages in an existing docs site.

    3.8k GitHub stars~3.1k tokensUpdated today
    DevelopmentAuto-check: notes
  • Extension Puppeteer Debugging

    mengxi-ream/read-frog

    Debug the built Read Frog extension in real Chrome. An agent skill from mengxi-ream/read-frog.

    10k GitHub stars~2k tokensUpdated today
    DevelopmentAuto-check: notes
  • Enso Cdp

    J3n5en/EnsoCode

    Drive the EnsoCode Electron renderer via Chrome DevTools Protocol on port 9222.

    119 GitHub stars~1.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Steam Cdp

    jinzhongjia/decky-music

    Drive and inspect the running Steam client UI over the Chrome DevTools Protocol (CEF remote debugging, port 8080) — list targets, evaluate JS probes, navigate routes, click elements, dispatch keys…

    122 GitHub stars~1.3k tokensUpdated today
    DevelopmentAuto-check passed

More from TriliumNext/Trilium

All 22 skills in this repo
  • Cutting A Release

    TriliumNext/Trilium

    A skill your agent uses when cutting, preparing, or debugging a Trilium release — bumping the monorepo version, tagging, or diagnosing a failed "Release" workflow run.

    38k GitHub stars~3.2k tokensUpdated today
    Auto-check passed
  • Developing Electron Desktop

    TriliumNext/Trilium

    A skill your agent uses when working on the Trilium Electron desktop app (apps/desktop) — adding or changing an electronApi method / IPC channel, touching preload.ts, main.ts, services/window.ts or…

    38k GitHub stars~5.7k tokensUpdated today
    Auto-check passed
  • Evolving The Data Model

    TriliumNext/Trilium

    A skill your agent uses when adding a DB migration or a new column/field to a Becca entity in Trilium ("add a migration", "new column on notes/attributes", "ALTER TABLE", "add a field to…

    38k GitHub stars~2.1k tokensUpdated today
    Auto-check passed
  • Adding Internal API Route

    TriliumNext/Trilium

    A skill your agent uses when adding, moving, or wiring an internal REST endpoint in Trilium (a new /api/ route) — choosing between a core-shared handler (packages/trilium-core/src/routes/index.ts…

    38k GitHub stars~3.3k tokensUpdated today
    Auto-check passed
  • Adding LLM MCP Tools

    TriliumNext/Trilium

    A skill your agent uses when adding, changing, or reviewing an LLM/MCP tool in Trilium (the defineTools definitions under packages/trilium-core/src/services/llm/tools/ —…

    38k GitHub stars~2.5k tokensUpdated today
    Auto-check passed
  • Ckeditor5 Plugin Development

    TriliumNext/Trilium

    Write, extend, and review CKEditor 5 plugins in the Trilium (TriliumNext Notes) monorepo — the rich-text-note editor under packages/ckeditor5, whose plugins live in src/plugins/.

    38k GitHub stars~4.8k tokensUpdated today
    Auto-check passed

Works with

Questions about Profiling Client Performance

What does Profiling Client Performance do?

A skill your agent uses when diagnosing a hard client-side performance problem in Trilium — a stutter while typing, janky dragging, a slow widget, a periodic freeze, "why does this only lag on my…. Profiling Client Performance is an agent skill from TriliumNext/Trilium.".

When should I use Profiling Client Performance?

Profiling Client Performance fits situations like: diagnosing a hard client-side performance problem in Trilium — a stutter while typing; A periodic freeze; why does this only lag on my real database?.

How do I install Profiling Client Performance in Claude Code?

Run `npx skills add TriliumNext/Trilium --skill profiling-client-performance -a claude-code`. Or copy the skill folder (.claude/skills/profiling-client-performance in TriliumNext/Trilium) into .claude/skills/profiling-client-performance in your project. Claude Code loads it when a task matches its description.

How do I install Profiling Client Performance in Codex?

Run `npx skills add TriliumNext/Trilium --skill profiling-client-performance -a codex`. Or copy the skill folder (.claude/skills/profiling-client-performance in TriliumNext/Trilium) into .agents/skills/profiling-client-performance in your project. Codex loads it when a task matches its description.

Can I use Profiling Client Performance in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add TriliumNext/Trilium --skill profiling-client-performance -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/profiling-client-performance, .gemini/skills/profiling-client-performance, .github/skills/profiling-client-performance and .opencode/skills/profiling-client-performance in your project.

What does Profiling Client Performance need to run?

Going by SKILL.md and its folder, Profiling Client Performance needs JavaScript for the scripts in its folder and the command-line tools its instructions call (node, npx and pnpm). Our summary lists: Node.js.

Does Profiling Client Performance access the network?

SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Profiling Client Performance safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Profiling Client Performance use?

Profiling Client Performance is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Profiling Client Performance use?

About 1.9k tokens (SKILL.md is roughly 7.5k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Profiling Client Performance?

Skills that share tags, products or a category with Profiling Client Performance: Browser Testing with Chrome DevTools (addyosmani/agent-skills, 103k stars), Go Pedantry (chromedp/chromedp, 13k stars), Docs Authoring (TracecatHQ/tracecat, 3.8k stars) and Extension Puppeteer Debugging (mengxi-ream/read-frog, 10k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Profiling Client Performance?

TriliumNext (a GitHub organization) maintains it in TriliumNext/Trilium, which has 38,248 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 8, 2026.

Source: TriliumNext/Trilium on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.