gpui-cache-aware
Skill651 starsChanged 7 days agoMITView on GitHub
Use this skill when reviewing or changing Con UI performance, especially when a view feels janky, expensive, or unexpectedly re-renders during unrelated updates. Keep Con visually rich without paying repeated GPUI layout/render cost for work that could be cached or isolated. Cache at the cheapest correct layer first. Order of preference: Do not jump straight to view caching. For any slow UI path, inspect these in order: Preferred fix: Preferred fix: Preferred fix: Use AnyView::cached(...) only if all of these…
In this repository8 other files it gives its agents.
- AGENTS.mdAGENTS.md
- changelog-release-notesSkill
- con-cli-e2eSkill
- con-terminalSkill
- native-surface-coverageSkill
- releaseSkill
- terminal-agent-benchmarkSkill
- terminal-agent-improvement-loopSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
25 rules. About 0 are common, 18 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈18
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 3
Use this skill when reviewing or changing Con UI performance, especially when a view feels janky, expensive, or unexpectedly re-renders …
- Distinctive: line 7
Keep Con visually rich without paying repeated GPUI layout/render cost for work that could be cached or isolated.
- Very specific: line 18
Use GPUI AnyView::cached(...) only when the subtree has a stable size contract.
- Distinctive: line 20
Do not jump straight to view caching.
- Very specific: line 34
add data-layer caches on parsed document/block/cell/message structs
- Distinctive: line 45
keep decorative element composition for UI chrome and short content only
- Very specific: line 55
keep mutation paths explicit so only that entity gets notify()
- Very specific: line 59
Use AnyView::cached(...) only if all of these are true:
- Distinctive: line 76
If a cached view causes overlap, clipping, or stale layout, the cache boundary is wrong.
- Distinctive: line 80
If there are many repeated items, consider virtualization before micro-optimizing item chrome.
- Distinctive: line 81
If the item count is small but each item is expensive, focus on item-level caches instead.
- Distinctive: line 87
Prefer parsed markdown caches on the message/document model.
- Distinctive: line 90
Avoid per-token flex trees for long replies.
- Distinctive: line 95
Do not hide/fold long replies as the primary performance fix.
- Distinctive: line 100
Keep terminal surfaces and heavy side panels isolated.
- Distinctive: line 101
Avoid reading terminal runtime state during ordinary render unless already cached.
- Distinctive: line 103
Check GPU composition bounds as well as CPU caches.
- Very specific: line 114
Do not return a child's layout ID from a presentation wrapper and then call prepaint_as_root on that same child.
- Distinctive: line 118
Test hitbox positions against visible geometry, not merely whether a click at the hitbox's reported (possibly wrong) position invokes its …
- Very specific: line 127
When observing scroll endpoints after layout, request a follow-up frame only when visibility changes.
- Very specific: line 150
If a view needs .on_hover(...), call .id(stable_id) first.
- Distinctive: line 159
After a cache-related change:
- Distinctive: line 162
run targeted tests if the subsystem has them
- Distinctive: line 166
if touching Windows/Linux-only view code from macOS, note that local checks are partial unless the target toolchain is installed
- Distinctive: line 180
If the only way a change feels fast is by degrading rendering fidelity, treat that as an incomplete fix and keep going.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
GPUI Cache-Aware Review
Use this skill when reviewing or changing Con UI performance, especially when a view feels janky, expensive, or unexpectedly re-renders during unrelated updates.
Goal
Keep Con visually rich without paying repeated GPUI layout/render cost for work that could be cached or isolated.
Core Rule
Cache at the cheapest correct layer first.
Order of preference:
- Cache parsed / normalized data.
- Cache expensive text-run or highlight transforms.
- Isolate expensive subtrees behind stable entity boundaries.
- Use GPUI
AnyView::cached(...)only when the subtree has a stable size contract.
Do not jump straight to view caching.
Review Checklist
For any slow UI path, inspect these in order:
1. Parse / transform churn
- Is the code reparsing markdown / JSON / syntax / layout input on every render?
- Is the code rebuilding
SharedString,Vec<TextRun>, highlighted runs, or table cell text on every render? - Can the expensive transform be retained on the model object and invalidated only on real content change?
Preferred fix:
- add data-layer caches on parsed document/block/cell/message structs
- invalidate only when source text or theme-dependent key changes
2. Render-tree cardinality
- Is the renderer producing many tiny
div()children for content that could be oneStyledText? - Are inline chips, per-token wrappers, nested flex rows, or deep container stacks used for long-form content?
Preferred fix:
- collapse long-form prose to text-first rendering
- keep decorative element composition for UI chrome and short content only
3. Entity boundaries
- Is a very large subtree being rebuilt because the parent panel rerendered for unrelated state?
- Can the subtree live in its own
Entity<V>with a narrower invalidation surface?
Preferred fix:
- split large stable regions into their own render entities
- keep mutation paths explicit so only that entity gets
notify()
4. GPUI cached view suitability
Use AnyView::cached(...) only if all of these are true:
- the subtree size is externally constrained or stable
- the cached style can describe the layout contract correctly
- reusing previous layout/paint is actually valid for the subtree
Good fits:
- panes that fill known bounds
- fixed-size or externally-sized tool panels
- stable canvases / editors / native-host surfaces
Bad fits:
- intrinsic-height rich text documents
- content whose height depends on wrapping and dynamic width unless that width/height contract is explicitly handled
If a cached view causes overlap, clipping, or stale layout, the cache boundary is wrong.
5. Lists and scrolling surfaces
- If there are many repeated items, consider virtualization before micro-optimizing item chrome.
- If the item count is small but each item is expensive, focus on item-level caches instead.
Con-Specific Guidance
Markdown and chat surfaces
- Prefer parsed markdown caches on the message/document model.
- Cache inline text-run generation for paragraphs, headings, and table cells.
- Cache syntax-highlight runs for code blocks.
- Avoid per-token flex trees for long replies.
- For long assistant replies, isolate each markdown block behind a stable
Entityand reuse that entity across parent renders. Keep per-block UI state such as table scroll handles on that entity, not inside parsed markdown data that is produced off the UI thread. - Do not hide/fold long replies as the primary performance fix. Folding can be a UX affordance, but the expanded state must remain responsive.
Terminal-adjacent UI
- Keep terminal surfaces and heavy side panels isolated.
- Avoid reading terminal runtime state during ordinary render unless already cached.
- Be cautious with transparency, animation, and resize interactions; measure before adding visual layers.
- Check GPU composition bounds as well as CPU caches. In the pinned Metal renderer, paths are copied from an intermediate texture over their bounds. A viewport-sized path with a hole can still require a large blit. For canvas gutters, use narrow quads and separately cached, corner-sized paths; test that they never paint over terminal pixels and keep their bounds small.
- For hover affordances that only need cursor feedback, prefer a tiny overlay /
hitbox and
cursor_pointer()over repainting terminal text. Keep the overlay state bounded to the hovered link/range.
GPUI interaction gotchas
- Do not return a child's layout ID from a presentation wrapper and then call
prepaint_as_rooton that same child. The node is still parented in Taffy; GPUI's absolute-origin lookup can count the parent offset again. Give the wrapper its own layout node and lay out the child as an independent root. Test hitbox positions against visible geometry, not merely whether a click at the hitbox's reported (possibly wrong) position invokes its callback. - Caption
.occlude()targets can block an ancestor's wheel listener. Forward wheel events from the real occluded target to its shared scroll handle, and include occlusion in the interaction test fixture. A plain layout fixture can pass while the native caption cannot scroll. - Component popover triggers need mouse-down to reach their wrapper. Apply native-caption occlusion outside the whole popover, not to its inner button; retain mouse-down consumption on ordinary caption buttons.
- When observing scroll endpoints after layout, request a follow-up frame only
when visibility changes. An unconditional
on_next_framefrom prepaint creates idle frame demand even when no animation is running. - Recheck the pinned view-cache key before animating an ancestor's opacity. The current key includes bounds, content mask and text style, but not inherited opacity. Keep such a subtree uncached while its opacity changes, and restore caching at the fully opaque endpoint. A changing clip can invalidate the cache, but rounded pixel bounds are not a reliable opacity invalidation mechanism.
- Native-surface overlays cannot rely on an opaque GPUI fill hiding a drop shadow's interior. If elevation is needed, paint only exterior content-mask strips, never a shadow-only full-surface div over terminal glass. The pinned Metal shadow vertex stage uses clip distances for these masks. Verify both the content's unchanged appearance and the masked geometry; do not infer a frame-rate improvement from a smaller painted region alone.
- A pane's undecorated/single-pane path must still run native clip prepaint. A native scroll host also needs its own backing layer before a layer mask can work; a Metal-backed descendant does not imply parent backing. Reusing its terminal after closing a sibling can otherwise retain a split mask even though its view frame has expanded. Test the real rendering path, not just the native mask setter in isolation.
.hover(|style| ...)is a style hook onDiv;.on_hover(...)is an enter/exit listener and requires aStateful<Div>.- If a view needs
.on_hover(...), call.id(stable_id)first. Use a stable id such as the pane'sFocusHandle, not a changing row/index. - For platform-selected files (
ghostty_view.rs,windows_view.rs,linux_view.rs), a macOScargo check -p cononly checks the macOS path. Validate the touched platform path on its target or wait for portable CI before treating the fix as closed.
Validation
After a cache-related change:
- verify
cargo check -p con - run targeted tests if the subsystem has them
- confirm there is no layout regression
- confirm the cache invalidates on real content/theme changes
- confirm the cache does not hide stale data
- if touching Windows/Linux-only view code from macOS, note that local checks are partial unless the target toolchain is installed
Anti-Patterns
- caching a view because it "seems expensive" without proving its size contract is stable
- keeping old cached output after source text changed
- using collapsed/default-hidden UI as the main performance strategy
- replacing high-fidelity rendering with degraded output when a correct cache boundary exists
Deliverable Standard
The final fix should preserve UX quality first, then reduce repeated work structurally.
If the only way a change feels fast is by degrading rendering fidelity, treat that as an incomplete fix and keep going.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

