editor-main-thread
Skill3 starsChanged 4 months agoMITView on GitHub
Rules for C# bridge code that runs on the Unity editor main thread (heartbeat, request pump, transport, scenario ticks) — the bridge must be invisible in the editor, so no sleeping, no unbounded blocking I/O, and fallback-over-wait on contention.
In this repository7 other files it gives its agents.
- AGENTS.mdAGENTS.md
- llms.txtllms.txt
- atomic-ipc-filesSkill
- cross-platform-pythonSkill
- cross-platform-shellSkill
- release-ci-guardrailsSkill
- safe-process-managementSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 26
All periodic work goes through the interval gates in XUUnityLightMcpBridgeBootstrap.OnUpdate (heartbeat/pump intervals from bridge config) …
≈ “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
Editor Main-Thread Guidelines
Everything the bridge does per tick runs on the editor main thread: XUUnityLightMcpBridgeBootstrap subscribes to EditorApplication.update and drives the heartbeat (2 s), the request pump (0.5 s), lifecycle and scenario ticks. Any blocking call there is a frame stall the user feels as editor lag. The bridge being invisible in the editor is a product requirement, not an optimization.
1. Never Sleep on the Main Thread
Thread.Sleep in tick-reachable code is forbidden. A sleep-based retry converts rare contention into periodic frame stalls (a 5×20 ms retry loop in the atomic writer stalled heartbeats whenever the host poller held bridge_state.json — caught in user review, 2026-07-11). On contention, fall back instead of waiting: immediate retries, then degrade to the legacy behavior the host side already tolerates (see atomic-ipc-files skill rule 3).
tests/test_atomic_ipc_contract.py::test_no_main_thread_sleeps_in_editor_package sweeps the whole package; XUUnityLightMcpGameViewUtility (on-demand screenshot settling) is the single allowlisted pre-existing exception — do not widen the allowlist without the same on-demand-only justification, and prefer converting it to a frame-deferred capture.
2. Blocking I/O Needs a Bound
- Synchronous socket sends from the main thread must set a send timeout first:
TcpClient.SendTimeoutbefore writing a response (TryWriteResponseuses 5000 ms) — a dead peer with a full send buffer otherwise freezes the editor until the OS-level TCP timeout. - Blocking accepts/reads belong on a dedicated background thread (
AcceptLooppattern), never in a tick. - File I/O in ticks is bounded by design: one small-file write per heartbeat, one directory scan of a normally-empty inbox per pump.
3. Ticks Are Throttled and Early-Out
- All periodic work goes through the interval gates in
XUUnityLightMcpBridgeBootstrap.OnUpdate(heartbeat/pump intervals from bridge config) — never do per-frame work directly onEditorApplication.update. - The single ungated call is
XUUnityLightMcpEditorQuitScheduler.Tick(), first inOnUpdate: a static-flag early-out, so an armed quit runs on the first update after its response. - Tick bodies must early-out cheaply when idle (
LifecycleMonitor.Tick, scenario scheduler). New tick work needs the same shape: field checks first, I/O only when something is actually pending.
4. No delayCall on Request Paths
EditorApplication.delayCall does not run while the editor is unfocused in Edit Mode: Unity's native timer skips it unless the editor is the active app, in unpaused Play Mode, or attached to a remote or debugger, while EditorApplication.update keeps ticking. Hosts open editors in the background, so deferred work on a request path must run from the bridge's update tick (XUUnityLightMcpEditorQuitScheduler is the reference shape: arm state in SessionState, early-out tick, expiry). tests/test_atomic_ipc_contract.py keeps EditorApplication.delayCall out of Editor/.
5. Keep the Hot Path Allocation-Light
Per-tick allocations add up at editor frame rates. Resolve once and cache what cannot change within a domain (WriteHeartbeat caches the editor pid instead of allocating Process.GetCurrentProcess() every heartbeat); expensive probes are memory-cached and refreshed on invalidation, not per tick (XUUnityLightMcpHealthProbe.EnsureCurrentReport).
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.

