Skip to content
Back to skills

Uloop Hot Reload

ASecurity

Apply C# edits to the running Editor without a compile or domain reload, keeping Play Mode state. Use instead of compile after editing method bodies or adding methods, fields, or new classes.

  • 576 stars
  • 0 votes
  • 0 copies
  • 8 views
  • Added September 12, 2026
toolsgoc#bash

Security analysis

A100/100

Pro scans all 7 files and shows the line behind each finding

Scanned October 6, 2026

npx -y skills add hatayama/unity-cli-loop --skill uloop-hot-reload --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Uloop Hot Reload?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Uloop Hot Reload
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/hatayama-uloop-hot-reload/badge)](https://www.skillsdirectory.com/skills/hatayama-uloop-hot-reload)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: uloop-hot-reload
toolName: hot-reload
description: "Apply C# edits to the running Editor without a compile or domain reload, keeping Play Mode state. Use instead of compile after editing method bodies or adding methods, fields, or new classes."
---

# uloop hot-reload

Replaces method bodies in the running Editor (EditMode or PlayMode) directly from edited
project source files — no domain reload, no attributes, no source markers. Private/internal
member access, static methods, return values, async methods, and iterators all work within
the limits below, including private access inside async, iterator, lambda, local-function,
and LINQ-query bodies. Methods that cannot be patched are reported as `Skipped` or `Failed`;
one unpatchable method never aborts the rest of the run.

## Usage

```bash
uloop hot-reload --files Assets/Scripts/Enemy.cs
uloop hot-reload --files Assets/Scripts/Enemy.cs,Assets/Scripts/Boss.cs
uloop hot-reload
uloop hot-reload --files Assets/Scripts/Enemy.cs --compile-on-skip off
uloop hot-reload --revert-all
```

Multiple files are one comma-separated value (or a JSON array); array options
consume exactly one value token.

A script under a brand-new `.asmdef` cannot be hot-reloaded before its first import: Unity
has not created that assembly yet. Run `uloop compile` once, then iterate with hot reload.
A new file under an existing `.asmdef` can be hot-reloaded, but it is never selected
automatically — pass it with `--files`.

## Parameters

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `--files` | array | - | Project-relative `.cs` paths to hot-reload (method bodies, added members, and new top-level types). When omitted or empty on apply, selects compiled snapshot sources only — those whose bytes changed since the last compile snapshot, capped at 50 changed files per assembly with a warning when the cap trims the list; a file that has never been compiled is never selected and must be passed explicitly, except an introduced type's file after Play Mode entry or `--revert-all`, which is selected again; run `uloop compile` first when no snapshot exists, or pass explicit paths when no changed source is found |
| `--revert-all` | flag | - | Remove every active hot-reload patch and added member and clear the ledger; introduced types stay loaded until the next domain reload. When set, `--files` is ignored |
| `--status` | flag | - | Lists the currently active changes (patched methods, added members, and introduced types) without applying or reverting anything. |
| `--compile-on-skip` | enum | `auto` | When edits stay unapplied (Skipped/Failed methods, Failed types; a re-bound sibling's Skipped rows aside), run `uloop compile` in this command: `auto` only in Edit Mode (never stops a Play session), `on` always unless Unity holds compiles until Play ends, `off` never. The response's `CompileFallback` says which; when the compile ran, `Compile` carries its result and `Success` is the compile's. |

## Status

`uloop hot-reload --status` lists the currently active changes; it cannot be combined with
`--files` or `--revert-all`. Every change is static Editor state, so after a domain reload
it reports zero. Each `Active`/`Added` row's `InvocationCount` counts calls
into its body since it was applied — a reachability signal only while the code is
being driven.

## How It Works

The edited files are grouped by the compiled assembly they belong to. Per group an
out-of-process Roslyn worker rewrites every editable body into a static shim, the shims
compile into one shim assembly and load into the Editor domain, and each original method is
patched with a Harmony transpiler. Because a group shares one shim assembly, a body edited in
one file can call a member added in another edited file of the same assembly. Re-running after
a real edit replaces the patch; an unchanged file reports `AlreadyActive` and changes nothing
unless a sibling of the same assembly is in the reload, in which case it is re-applied so every
active patch binds to the newest shim. With a compile-time baseline only bodies that actually
changed are patched (`UnchangedTotal` counts the rest).

## Scope in Brief

- Patched: ordinary method bodies and property getters with a body.
- Added members: new methods, fields, and supported properties apply as `Added` rows
  (supported field-like events of a class are listed in `AddedFields`),
  visible to edited code of the same reload within the same assembly (pass the declaring
  file and its callers together), and gone on any compile or domain reload.
- New types: a top-level class, struct, enum, or interface declared in an edited
  file is introduced by that reload and listed in `IntroducedTypes`; other valid shapes are
  refused with a `Warnings` line naming the reason. Use from another assembly or from files
  outside the reload, reflection, serialization, and Unity message discovery still need
  `uloop compile`.
- Signature changes: a return-type change is `Skipped` unless this or an earlier reload
  patched every live compiled caller, none in another assembly; a rename or parameter change
  applies as an added method and warns about call sites left on the old signature.
- Constructors, operators, struct methods, compiled setter/init/indexer accessors, and event
  accessors are `Skipped`; finalizers and interface members are silently not applied.
- A reload applies each file all-or-nothing: a `Failed` method leaves that file unapplied,
  a `Failed` type leaves every file of its assembly unapplied.

## Workflow

Treat hot reload as the exploration phase and `uloop compile` as the landing phase:
keep edits inside the edited files, collect structural changes, and compile once —
every compile drops all patches and pause points and resets the PlayMode session (the compile response's Warning says how many).
While hot-reload changes are active, `AutoRefreshHeld` is true so returning focus does not
recompile; `uloop compile` releases the hold, and `--revert-all` only when no introduced type
remains.
One-shot methods (`Awake`, `Start`, init helpers) patch but show no effect on the call that
already ran; the response marks them with `LifecycleNote`. To re-run an edited compiled
`OnEnable`, set `enabled = false` with `execute-dynamic-code`, reload, then set it back to `true`
(Unity calls the old `OnDisable`, then the patched `OnEnable`). An edited `OnDisable` runs the
next time the component is disabled; to run it now, toggle `enabled` after the reload.
To tune a value while playing, expose a static property getter instead of a `const`; its
body is patched on compiled and introduced types alike.

## Reference Guides

All files live in `references/` beside this skill; read the one whose trigger matches:

- `references/scope-and-limits.md` — full scope rules: added members, signature changes, `Skipped`/`Failed` tables, source baselines, one-shot code, tunable getters.
- `references/mechanism-and-lifecycle.md` — patch mechanism, convergence, what survives which reload, Editor-code iteration without PlayMode.
- `references/troubleshooting.md` — `Patched` but no behavior change, JIT inlining, `--status`, stack frames without lines.
- `references/pause-point-interaction.md` — how patches re-target or suppress armed pause points; one-way reachability checks.
- `references/introduced-types.md` — types a reload can introduce: supported shapes, internal access, refusal wording, identity and lifetime, why a new file is never selected automatically.
- `references/added-field-wiring.md` — putting a value into an added field without a compile.
- `references/output.md` — every response field: `ErrorCode`, `NextActions`, `Methods` rows, `Warnings`, totals.

Files in this skill

  • SKILL.md7.8 KB
  • references/introduced-types.md5.2 KB
  • references/mechanism-and-lifecycle.md4.1 KB
  • references/output.md11.1 KB
  • references/pause-point-interaction.md2.9 KB
  • references/scope-and-limits.md21.4 KB
  • references/troubleshooting.md3.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.