Agent skill

Editor Perf

by gridaco in gridaco/grida

Guides performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer, Immer, React hooks).

Apache-2.0Auto-check: notesFrontend & Design

Install Editor Perf

skills CLI
$ npx skills add gridaco/grida --skill editor-perf -a claude-code

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

GitHub CLI
$ gh skill install gridaco/grida editor-perf --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/gridaco/grida.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/editor-perf .claude/skills/editor-perf && 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
editor-perf
GitHub stars
2.7k
Token cost
~5.3k tokens
SKILL.md length
1,958 words
Files
1
Skills in repo
29
Repo updated
First seen
Licence
Apache-2.0

At a glance

Guides performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer, Immer, React hooks).

  • Works in 9 steps: Baseline → Implement → Measure → …
  • Profiling reducer dispatch cost
  • SKILL.md covers When to Use This Skill, Pick your measurement tool, How to Orient Yourself and The Architecture…, plus 6 more sections
  • Calls pnpm

What it does

Editor Perf is an agent skill from gridaco/grida. Guides performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer, Immer, React hooks). Use when profiling reducer dispatch cost, diagnosing slow interactions (drag, resize, color change), writing or running editor benchmarks, instrumenting with PerfObserver, or optimizing the JS-side state management pipeline.

Its SKILL.md is about 5.3k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Frontend & Design, covering State management and React components. It works with React and TypeScript. The licence is Apache-2.0.

When your agent uses it

  • Profiling reducer dispatch cost
  • Diagnosing slow interactions (drag
  • Running editor benchmarks
  • Instrumenting with PerfObserver

Example prompts

  • “Use the editor-perf skill to guide performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer…”
  • “/editor-perf”

Workflow steps

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

  1. Baseline
  2. Implement
  3. Measure
  4. Regression check
  5. Accept or iterate
  6. Measure first
  7. Classify the bottleneck
  8. Implement incrementally
  9. Add a benchmark if one doesn't exist

What it can do on your machine

Read from SKILL.md and the folder at commit 165496f. 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

    Shell commands in SKILL.md call:

    • pnpm

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

  • Network

    Links to these hosts (documentation or services it may open):

    • github.com

    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

Editor Perf loads about 5.3k tokens when it runs. Until then it costs about 94 tokens; SKILL.md has 1,958 words of instructions outside code blocks.

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

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: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:245
    UBLIC_GRIDA_PERF=1  # Browser / Next.js (.env.local)

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 gridaco/grida at commit 165496f, republished under its Apache-2.0 licence (© gridaco). 1,958 words, ~5,341 tokens.

Download SKILL.mdSave it as .claude/skills/editor-perf/SKILL.md (or your agent's skills folder).
name
editor-perf
description
Guides performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer, Immer, React hooks). Use when profiling reducer dispatch cost, diagnosing slow interactions (drag, resize, color change), writing or running editor benchmarks, instrumenting with PerfObserver, or optimizing the JS-side state management pipeline.

Grida Canvas Editor — Performance Development

Workflow and reasoning framework for performance work on the TypeScript editor pipeline — the reducer, Immer state management, React subscription layer, and headless benchmarks.

Scope boundary: This skill covers the JS/TS editor pipeline (editor/grida-canvas/). For the Rust rendering engine (the grida crate), use the engine repo's render-perf skill: https://github.com/gridaco/nothing/blob/main/.agents/skills/render-perf/SKILL.md. The two pipelines are connected — a dispatch in JS may trigger a WASM re-render — but they are profiled with different tools, in different repos.

Maintaining this document: If you notice a section that has gone stale (e.g. a workflow step no longer matches the code, a discovery query returns nothing, or a pitfall has been resolved), update this SKILL.md as part of your current task. Keep it high-level — reference patterns and categories rather than specific function names or measured numbers, which change frequently.

When to Use This Skill

  • Benchmarking or profiling editor reducer operations
  • Diagnosing slow interactions (drag, resize, color picker, opacity slider)
  • Investigating Immer overhead or state cloning costs
  • Instrumenting code with PerfObserver spans
  • Writing or running the editor bench
  • Optimizing queries, snap targets, hover resolution
  • Reducing React re-render cost from editor state subscriptions

Pick your measurement tool

Performance work starts with the right signal. The three tools below are complementary — do not skip the browser trace if the user offers one, do not open a browser for a reducer-only regression.

ToolUse whenWhat it catchesWhat it misses
Browser trace (Chrome DevTools Performance)User provided a .json.gz trace, or the symptom is interaction-level (drag/nudge feels laggy). This is the truth.Everything on the main thread: React, selector cost, paint, compositor, GC, WASM, reducer, Immer, RAF.Not reproducible without the user's session
editor-bench (automated)Default for proactive investigation and A/B of a reducer / encode / WASM change. No user input needed.PerfObserver span table, per-scene (1K / 10K). Deterministic and comparable across runs.React render cost, DOM overlays, real RAF
Node CPU profileA bench span points at a hotspot but you need function-level detail inside it, or microtask timing.Function self-time and call chains within a single Node process.Browser-only code paths
Decision rules
  1. If the user provides a browser trace, start there. It already has React, DevTools, and WASM on the same timeline — quote actual numbers from the trace rather than guessing. Parse it as JSON (see "Reading a browser trace" below).
  2. Otherwise run the bench first. No user input needed — it covers every scenario at 1K and 10K and emits a PerfObserver span table that's directly comparable across runs.
  3. Once bench points at a span, drill with a Node CPU profile. Use the withCpuProfile() helper in _utils.ts, or run node with --cpu-prof. Open the resulting .cpuprofile in Chrome DevTools (Performance → Load profile) for a function-level flame graph inside the span.

How to Orient Yourself

Before touching any code, build context by reading these sources in order:

  1. Read editor/grida-canvas/__tests__/bench/README.md — benchmark catalog, run instructions, and the authoritative list of PerfObserver spans with a "when to trust the numbers" guide.
  2. Read editor/grida-canvas/perf.ts — the PerfObserver API. Understand start(), measure(), report(), dump().
  3. Skim editor/grida-canvas/editor.ts — the EditorDocumentStore class, specifically the dispatch() method. This is the single entry point for all state mutations.
  4. Skim editor/grida-canvas/reducers/index.ts — the root reducer that wraps everything in Immer produceWithPatches.
  5. Browse the bench files (perf-editor.test.ts, perf-per-node-sync.test.ts) to see what operations are already measured and at what scale.
Key discovery queries
What you needHow to find it
All instrumented perf spansgrep "__perf_" --include="*.ts" in editor/grida-canvas/
The dispatch entry pointSearch for dispatch( in editor/grida-canvas/editor.ts
Root reducer + Immer produceRead the top-level reducer() function in editor/grida-canvas/reducers/index.ts
Gesture transform hot pathSearch for self_update_gesture_transform in editor/grida-canvas/reducers/methods/
Document query helpersRead editor/grida-canvas/query/index.ts
React hook subscribersgrep "useEditorState" --include="*.ts" in editor/grida-canvas-react/
Action type definitionsRead editor/grida-canvas/action.ts
Existing benchmark filesls editor/grida-canvas/__tests__/bench/

The Architecture (Performance-Relevant)

Dispatch Pipeline

Every user interaction flows through this pipeline:

User action (click, drag, keystroke)
  → dispatch(action, recording)
    → Immer produceWithPatches(state, draft => { ... })
      → sub-reducers (document, event-target, surface)
      → tracked-Graph wrapper emits sync_links / delete_node ops
    → appendPatchOps(patches, buffer) lifts document.nodes patches
      into replace_node / delete_node ops
    → history.record(patches)
    → postDispatchHooks
    → emit(action, patches, opLog)
      → __wasm_on_document_change applies opLog 1:1 to WASM
      → React selectors + equality checks

The op-log produced during the recipe is the single WASM-sync channel. Structural edges come from the tracked-Graph wrapper; node-property changes are lifted from Immer patches via appendPatchOps. The subscriber applies ops directly (Scene.replaceNode / Scene.deleteNode / Scene.syncLinks) or falls back to a full re-encode only when the batch contains a full_resync op.

Performance-Sensitive Operation Categories

Gesture-bound (hot loop) — fires on every frame while the user drags a handle, slider, or object. These must complete within ~16ms (60fps budget) per frame:

  • Property sliders (color picker, opacity, font size)
  • Drag translate (moving nodes)
  • Resize / scale (corner handles)
  • Rotate

Discrete (single shot) — fires once per user click or toggle:

  • Select, rename, visibility toggle
  • Delete, insert
  • Gesture start / end (snapshot cost)
  • Pointer hover / raycast
Cost Scaling

Costs scale linearly with total node count due to Immer proxy finalization walking the entire state tree on every dispatch — even when only a single property on one node changes. This is the fundamental scaling wall for the current architecture.

Run the benchmarks to get current numbers. The perf.report() output shows exactly which spans dominate at any given scale.

Bottleneck Categories

Use GRIDA_PERF=1 to identify which category applies:

CategoryHow to recognizeWhere to look
Immer overheadreducer.immer_produce dominates; cost grows with node count regardless of what changedRoot reducer, consider structural sharing or targeted produce
O(N) tree queriesTree-traversal spans are hot in the breakdownquery/index.ts — check if lookups can use pre-built index maps
Deep clone / snapshotsnapshot span dominates gesture starteditor.i.ts — consider storing only what the gesture needs
Compute-heavy reducer logicSpecific spans (snap, hover, transform) dominateThe relevant reducers/tools/ or reducers/methods/ file
React re-renderNot visible headless; visible in Chrome DevTools ProfilerSelector breadth, equality comparators, virtualization

The Benchmark System

The single source of truth is perf-editor.test.ts in editor/grida-canvas/__tests__/bench/. It uses Editor.mountHeadless() with the real WASM raster backend — every dispatch runs through the same __wasm_on_document_change subscriber the browser installs. Spans under dispatch.wasm.* are end-to-end identical to the browser; spans under reducer.* are pure JS and track within ~10% of browser V8.

sh
# Default — runs every scenario at 1K synthetic + bench.grida (10K) scales
GRIDA_PERF=1 pnpm vitest run editor/grida-canvas/__tests__/bench/perf-editor.test.ts

# With CPU profile capture (delete scenarios)
GRIDA_PERF=1 GRIDA_PERF_CPUPROFILE=1 pnpm vitest run \
  editor/grida-canvas/__tests__/bench/perf-editor.test.ts

# Large fixtures need more heap
NODE_OPTIONS="--max-old-space-size=8192" GRIDA_PERF=1 \
  pnpm vitest run editor/grida-canvas/__tests__/bench/perf-editor.test.ts
Which spans to read

After a bench run, perf.report() prints a table per scene. The bench README has the authoritative catalog — read it there. Read the table in category order rather than by specific name:

  1. Total dispatch — your ceiling per action.
  2. Reducer + Immer — pure JS cost. Watch p95 on gesture scenarios (drag / resize per-frame) — median can be microseconds while p95 spikes into hundreds of ms as the tree grows.
  3. Document snapshot — deep-clone at gesture boundaries; pays twice per gesture (start + end).
  4. WASM sync (full reload vs. op-apply) — compare dispatch.wasm.sync_document (full reload) against dispatch.wasm.op_apply (per-op replay). If the full reload fires for every dispatch and op_apply rarely fires, too many actions are routing through the slow path — usually a missing observation channel that forces full_resync (e.g. a mutation under document.* outside document.nodes[id] that no tracked channel covers).
  5. Gesture / query compute — snap targets, hover ray, tree traversal. Usually small but can dominate at high selection count.

Prefer bench ratios over absolute numbers in commits and memory — absolutes shift with machine and node version; ratios stay meaningful.

Show full SKILL.md (803 more words)Show less
Adding a new benchmark

Extend BENCH_SCENARIOS in perf-editor.test.ts. Use the bench() helper from _utils.ts for per-frame gestures and runAndTime() (or similar) for single-shot discrete actions:

ts
const result = await bench(() => {
  h.ed.doc.dispatch({ type: "...", ... } as Action, { recording: "silent" });
}, { iterations: 10 });
logBench("my operation", result);

If you need a one-off CPU profile of a specific operation, use withCpuProfile() from _utils.ts — it wraps the call in node:inspector and writes a .cpuprofile to fixtures/local/perf/cpuprofile/ (gated by GRIDA_PERF_CPUPROFILE=1).


PerfObserver (perf.ts)

Opt-in instrumentation layer. Zero cost when disabled (returns a shared NOOP function).

Enable
sh
GRIDA_PERF=1              # Node.js / headless tests
NEXT_PUBLIC_GRIDA_PERF=1  # Browser / Next.js (.env.local)

Or programmatically:

ts
import { perf } from "@/grida-canvas/perf";
perf.enable();
Instrument new code

Use the __perf_ prefix for all perf variables:

ts
import { perf } from "@/grida-canvas/perf";

function myHotFunction() {
  const __perf_end = perf.start("myHotFunction");
  // ... work ...
  __perf_end();
}

// For functions with multiple return paths, use try/finally:
function myComplexFunction() {
  const __perf_end = perf.start("myComplexFunction");
  try {
    if (earlyExit) return null;
    return result;
  } finally {
    __perf_end();
  }
}

// For wrapping a synchronous call:
const result = perf.measure("expensiveClone", () => doExpensiveWork());
Read results
ts
perf.report(); // prints formatted table to console
perf.summarize(); // returns PerfSummaryEntry[] (for programmatic use)
perf.dump(); // returns raw PerfSample[]
perf.reset(); // clears all samples
Finding existing spans

Instrumented spans are discoverable via grep:

sh
grep "__perf_" --include="*.ts" -r editor/grida-canvas/

The span labels use dot-notation hierarchy (dispatch.reducer, dispatch.emit, etc.) so the perf.report() table reads naturally.


Reading a browser trace

Chrome DevTools exports traces as .json.gz. They are plain JSON after decompression, so analyze them with a short Python script rather than opening DevTools by hand.

Key signals to extract:

SignalHow to find it
React component renders (count per name)Events with cat == "blink.user_timing" and ph == "b". Each render emits one; counting them per name shows re-renders.
Hot JS functions (self-time)ProfileChunk events contain cpuProfile.nodes + samples + timeDeltas. Accumulate timeDeltas per sample id.
Long interactionsFunctionCall events with name == "dispatchContinuousEvent" (or dispatchDiscreteEvent) — filter by dur > 20000 (µs).
What happened inside one long interactionFilter ProfileChunk samples by their cumulative timestamp falling inside the FunctionCall window.

The trace includes React DevTools overhead when the extension is installed. measureInstance @ installHook.js is the React DevTools profiler — it can easily account for ~10% of CPU and inflates render counts. Ask the user to disable the extension for "clean" traces, or subtract it out when reading.

py
# Minimal trace reader — extract events and CPU profile nodes
import json, gzip
from collections import defaultdict, Counter
data = json.load(gzip.open("logs/Trace-....json.gz"))
events = data["traceEvents"] if isinstance(data, dict) else data

# Component renders by name
renders = Counter()
for e in events:
    if e.get("cat") == "blink.user_timing" and e.get("ph") == "b":
        renders[e.get("name","")] += 1

# CPU self-time by function
nodes_by_id = {}
self_time = defaultdict(int)
for e in events:
    if e.get("name") == "ProfileChunk":
        cp = e["args"]["data"].get("cpuProfile", {})
        for n in cp.get("nodes", []):
            nodes_by_id[n["id"]] = n
        for sid, dt in zip(cp.get("samples", []),
                           e["args"]["data"].get("timeDeltas", [])):
            self_time[sid] += dt

Node CPU profiles

When an editor-bench run flags a span but you need function-level detail, capture a .cpuprofile:

sh
# Via the bench harness (preferred — uses withCpuProfile wrapper)
GRIDA_PERF=1 GRIDA_PERF_CPUPROFILE=1 pnpm vitest run \
  editor/grida-canvas/__tests__/bench/perf-editor.test.ts
# → writes fixtures/local/perf/cpuprofile/*.cpuprofile

# Or wrap a specific call in code:
import { withCpuProfile } from "./_utils";
await withCpuProfile("my-scenario", async () => { ... });

Open the resulting .cpuprofile in Chrome DevTools (Performance → Load profile) or VS Code for an interactive flame graph.

For microtask-level detail, start Node with --cpu-prof --cpu-prof-interval=100 (µs between samples). For trace events / async task timing, --trace-events-enabled captures a chrome://tracing-compatible JSON. Both are Node built-ins — no extra tooling required.


The Verification Workflow

Every performance change follows this sequence.

Step 1: Baseline

Run the bench BEFORE any changes. Save the output.

sh
GRIDA_PERF=1 pnpm vitest run editor/grida-canvas/__tests__/bench/perf-editor.test.ts

If the user provided a browser trace, also record its pre-change numbers (render counts and hot-function self-times) — these are the only way to verify React-side wins.

Step 2: Implement

Make the change. After each logical step, verify:

sh
pnpm vitest run grida-canvas/__tests__/headless/
pnpm turbo typecheck --filter=editor
Step 3: Measure

Run the same benchmarks AFTER the change. Compare.

Step 4: Regression check

An optimization for one operation must not regress others. Run the full bench suite at both 1K and 10K scales, not just the target operation — many improvements that help 10K scenes add constant overhead that hurts 1K.

Step 5: Accept or iterate
CriterionRequired?
Target operation measurably fasterYes
Non-target operations within 10% of baselineYes
All headless tests passYes
No new TypeScript errorsYes

How to Design an Optimization

1. Measure first

Run benchmarks to quantify the problem. Use GRIDA_PERF=1 to get the internal span breakdown. Identify which span dominates.

2. Classify the bottleneck

See the "Bottleneck Categories" table above. The perf.report() output directly tells you which category you're dealing with.

3. Implement incrementally

Each step should compile, pass existing tests, produce a measurable improvement in the target benchmark, and not regress other benchmarks.

4. Add a benchmark if one doesn't exist

If optimizing an operation that has no bench coverage, extend BENCH_SCENARIOS in perf-editor.test.ts first. Measure before and after.


Pitfalls

Immer makes everything O(N)

Immer's produceWithPatches walks the entire proxy tree during finalization regardless of how many properties changed. This is the fundamental scaling wall — even a no-op dispatch has a cost proportional to total node count.

Gesture start can freeze the UI

Gesture start may deep-clone the entire document state for undo snapshots. At scale this causes multi-second freezes and high memory pressure. Check how snapshot data is captured when investigating gesture-start lag.

Bench omits React cost — that is intentional

The bench measures the reducer + emit + WASM pipeline, not the React subscription layer. If the complaint is about interaction feel (a pointer move stalls, a panel re-renders too often), bench will not see it. Use a browser trace for that; see "Pick your measurement tool" above.

WASM geometry adds memory pressure

The WASM raster backend allocates a real scene in memory. At 10K+ nodes, running full gesture benchmarks may OOM at default heap size. Use NODE_OPTIONS="--max-old-space-size=8192".

Gesture-bound operations vary wildly

Drag translate can be orders of magnitude slower than resize at the same node count because translate triggers snap-target computation (tree queries per selection item) while single-node resize skips that path. Always bench the specific gesture type, not just "gesture" generically.

recording: "silent" skips history

Benchmarks use { recording: "silent" } to avoid history stack growth during repeated dispatches. This correctly isolates reducer cost but skips the history recording path. Use { recording: "on" } when specifically benchmarking history overhead.

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

Files

Just SKILL.md in .agents/skills/editor-perf of gridaco/grida.

Open the folder on GitHubat commit 165496f

Compare with similar skills

Editor Perf 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.

Editor Perf compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Editor Perf this skillgridaco/grida2.7k—~5.3kAutomated safety check: NotesApache-2.0
Dify Component Writing Guidelanggenius/dify158k—~626Automated safety check: PassCustom licence
Frontend Typescript Rulesshinpr/ai-coding-project-boilerplate232—~1.7kAutomated safety check: PassMIT
Dokan Frontend Devgetdokan/dokan288—~1.9kAutomated safety check: PassNone
React ExpertJeffallan/claude-skills12k—~1.4kAutomated safety check: PassMIT
React Idiomsirahardianto/awesome-agv157—~3.8kAutomated safety check: PassMIT

Similar skills

  • Use when implementing or refactoring React/TypeScript components and the task requires decisions about component ownership, feature boundaries, state, data…

    158k GitHub stars~626 tokensUpdated today
    Frontend & DesignAuto-check passed
  • Frontend Typescript Rules

    shinpr/ai-coding-project-boilerplate

    Applies React/TypeScript type safety, component design, and state management rules.

    232 GitHub stars~1.7k tokensUpdated 4 days ago
    Frontend & DesignAuto-check passed
  • Dokan Frontend Dev

    getdokan/dokan

    Add or modify Dokan frontend code (React, TypeScript, Vue, Tailwind).

    288 GitHub stars~1.9k tokensUpdated today
    Frontend & DesignAuto-check passed
  • React Expert

    Jeffallan/claude-skills

    Builds React 19 components in TypeScript with Server Components, useActionState forms, custom hooks and state libraries, checked with tsc and React Testing Library.

    12k GitHub stars~1.4k tokensUpdated 4 days ago
    Frontend & DesignAuto-check passed
  • React Idioms

    irahardianto/awesome-agv

    React 19+ patterns: custom hooks, Suspense boundaries, state management, component composition, and web performance.

    157 GitHub stars~3.8k tokensUpdated 3 days ago
    Frontend & DesignAuto-check passed
  • Typescript Rules

    shinpr/claude-code-workflows

    React/TypeScript frontend development rules including type safety, component design, state management, and error handling.

    691 GitHub stars~1.8k tokensUpdated 6 days ago
    Frontend & DesignAuto-check passed

More from gridaco/grida

All 29 skills in this repo
  • Desktop

    gridaco/grida

    Grida Desktop Electron shell and release-impact work: BrowserWindow, preload, window.grida, menus, protocol/deep links, file associations, Forge, path-scoped bridge security, Electron-only UI bugs…

    2.7k GitHub stars~3.2k tokensUpdated today
    Auto-check: notes
  • Io Figma

    gridaco/grida

    Guides work on the Figma I/O package (@grida/io-figma, packages/grida-canvas-io-figma/).

    2.7k GitHub stars~2.2k tokensUpdated today
    Auto-check: notes
  • Opt Library

    gridaco/grida

    Set up, download, verify, and seed the optional Grida Library developer corpus into local Supabase.

    2.7k GitHub stars~1.4k tokensUpdated today
    Auto-check passed
  • Vision

    gridaco/grida

    Query images with a local Ollama vision model without loading the image into the main agent context.

    2.7k GitHub stars~1.5k tokensUpdated today
    Auto-check passed
  • AI Models

    gridaco/grida

    Research, compare, and update shared AI model JSON for TypeScript, web, and Rust consumers.

    2.7k GitHub stars~5.7k tokensUpdated today
    Auto-check passed
  • Agent System

    gridaco/grida

    Grida AI agent system work: @grida/daemon (DaemonServer, loopback HTTP perimeter, files/workspaces, secrets store, daemon discovery) and @grida/agent (the agent tenant: sessions, providers/BYOK…

    2.7k GitHub stars~3.4k tokensUpdated today
    Auto-check passed

Works with

Questions about Editor Perf

What does Editor Perf do?

Guides performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer, Immer, React hooks). Editor Perf is an agent skill from gridaco/grida. Guides performance investigation, benchmarking, and optimization of the Grida Canvas web editor (TypeScript reducer, Immer, React hooks).

When should I use Editor Perf?

Editor Perf fits situations like: profiling reducer dispatch cost; diagnosing slow interactions (drag; running editor benchmarks; instrumenting with PerfObserver.

How do I install Editor Perf in Claude Code?

Run `npx skills add gridaco/grida --skill editor-perf -a claude-code`. Or copy the skill folder (.agents/skills/editor-perf in gridaco/grida) into .claude/skills/editor-perf in your project. Claude Code loads it when a task matches its description.

How do I install Editor Perf in Codex?

Run `npx skills add gridaco/grida --skill editor-perf -a codex`. Or copy the skill folder (.agents/skills/editor-perf in gridaco/grida) into .agents/skills/editor-perf in your project. Codex loads it when a task matches its description.

Can I use Editor Perf 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 gridaco/grida --skill editor-perf -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/editor-perf, .gemini/skills/editor-perf, .github/skills/editor-perf and .opencode/skills/editor-perf in your project.

What does Editor Perf need to run?

Going by SKILL.md and its folder, Editor Perf needs the command-line tools its instructions call (pnpm).

Does Editor Perf access the network?

SKILL.md names 1 domain. As links in the text: github.com. This is read from the text; nothing was executed.

Is Editor Perf safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.

What licence does Editor Perf use?

Editor Perf is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Editor Perf use?

About 5.3k tokens (SKILL.md is roughly 21k 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 Editor Perf?

Skills that share tags, products or a category with Editor Perf: Dify Component Writing Guide (langgenius/dify, 158k stars), Frontend Typescript Rules (shinpr/ai-coding-project-boilerplate, 232 stars), Dokan Frontend Dev (getdokan/dokan, 288 stars) and React Expert (Jeffallan/claude-skills, 12k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Editor Perf?

gridaco (a GitHub organization) maintains it in gridaco/grida, which has 2,659 GitHub stars. The repository holds 29 skills in this directory. The repository was last updated on October 7, 2026.

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