runtime-eval
Execute and inspect C# code live within a running game environment via WebSocket.
Install
mkdir -p .claude/skills/runtime-eval && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/19282" && unzip -o skill.zip -d .claude/skills/runtime-eval && rm skill.zipInstalls to .claude/skills/runtime-eval
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Runtime C# evaluation via HotRepl WebSocket. Use when inspecting live game state, debugging mod behavior, or prototyping fixes without a build cycle.Key capabilities
- →Execute C# code in a running game process
- →Inspect live scene objects and variables
- →Stream game state data via watch commands
- →Trigger hot-reloads of plugins
- →Access Unity API methods at runtime
How it works
It connects to a running game via a WebSocket-based REPL, allowing for real-time code execution and inspection within the game's memory space.
Inputs & outputs
When to use runtime-eval
- →Inspect live game state variables
- →Prototype bug fixes without rebuilding
- →Test rendering changes dynamically
About this skill
Runtime Eval (HotRepl)
Execute C# code inside the running game over WebSocket. Inspect scene state, test rendering changes, and prototype fixes without a build/deploy cycle.
Start a HotRepl session
HotRepl is a BepInEx development dependency for Erenshor. It is not a Lunaris
plugin, and mod launch does not install it. With the game closed, activate
BepInEx, then launch the selected variant through Steam:
uv run erenshor mod activate --loader bepinex
uv run erenshor mod launch
uv run erenshor eval ping
The default variant is main. Pass -V playtest or -V demo before mod and
eval only when that variant is intentional. mod deploy --loader bepinex
also activates BepInEx when deploying a companion mod. Never swap or copy
winhttp.dll by hand.
HotRepl remains installed between sessions. Normal use only requires selecting BepInEx and launching the game. Wait for Steam and the game process to finish starting before treating a failed ping as a loader failure.
Install or update the HotRepl host
HotRepl is maintained in ~/Projects/HotRepl/. The current BepInEx host is a
multi-assembly deployment. Build the host from that checkout:
dotnet build ~/Projects/HotRepl/src/HotRepl.BepInEx --nologo -v q
The deploy source is
src/HotRepl.BepInEx/bin/Debug/netstandard2.1/. Deploy every top-level DLL
from that output into a dedicated BepInEx/plugins/HotRepl/ directory. Replace the
existing HotRepl directory as one unit so every assembly comes from the same
build. The set includes HotRepl.BepInEx.dll, HotRepl.Core.dll,
HotRepl.Protocol.dll, evaluator and Unity-command assemblies, Fleck,
Newtonsoft.Json, and mcs.dll. Ensure no HotRepl DLLs remain at the
BepInEx/plugins/ root because duplicate or partial deployments produce
assembly resolution failures.
Host deployment is an install/update operation, not part of every launch. It
must happen while the game is closed and currently has no erenshor mod
command. Use the complete build output rather than inventing an allowlist.
After starting the game, BepInEx/LogOutput.log should contain
HotRepl v… loaded — REPL on 127.0.0.1:18590.
Eval commands
uv run erenshor eval ping # Check connection
uv run erenshor eval run 'SceneManager.GetActiveScene().name' # Evaluate expression
uv run erenshor eval run --json 'GameData.PlayerControl.transform.position'
uv run erenshor eval reset # Clear REPL state
uv run erenshor eval watch 'GameData.PlayerControl.transform.position' # Stream
uv run erenshor eval complete 'Camera.main.' # Autocomplete
Combat evaluation
For controlled experiments that validate damage, healing, resistance, proc,
resource, or cooldown behavior, use the combat-evaluation skill. Keep this
skill focused on HotRepl commands, evaluator constraints, and runtime access.
C# 7 Limitations
The Mono compiler supports C# 7.x only. These do not work:
async/await, nullable annotations, switch expressions, records, ranges- Anonymous types (
new { foo = 1 }) — compiles to internal classes the REPL's dynamic assembly can't emit. Use tuples or string concatenation instead.
# WRONG — anonymous type fails to compile
uv run erenshor eval run 'objects.Select(o => new { o.name, o.tag }).ToArray()'
# RIGHT — use string formatting
uv run erenshor eval run 'objects.Select(o => o.name + " tag=" + o.tag).ToArray()'
ScriptEngine Cross-Assembly Gotchas
Hot-reloaded mods (deployed via --scripts, reloaded with F6) get timestamp-
suffixed assembly names like AdventureGuide-639098010137845420.
HotRepl auto-resets on hot reload: When a ScriptEngine-style assembly loads, HotRepl detects it and rebuilds the evaluator session, filtering out superseded assemblies. Types resolve to the newest version automatically. REPL variable state is lost on reset (expected — F6 is a code change, not a data continuation).
When auto-reset doesn't help: If you encounter cross-assembly errors
despite auto-reset (e.g., after multiple rapid F6 reloads), use eval reset
manually. The reflection pattern below also works as a fallback for any
cross-assembly access:
# Pattern: find object by string name, reflect through its own type
uv run erenshor eval run '
var ag = Resources.FindObjectsOfTypeAll(typeof(MonoBehaviour))
.First(o => o.GetType().FullName == "AdventureGuide.Plugin");
var bf = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;
var state = ag.GetType().GetField("_state", bf).GetValue(ag);
state.GetType().GetProperty("CurrentZone").GetValue(state)
'
Triggering ScriptEngine hot reload
After uv run erenshor mod deploy --mod <id> --loader bepinex --scripts, trigger
ScriptEngine directly through HotRepl. The deployment activates BepInEx, so
restart the game first if Lunaris was active:
uv run erenshor eval run '
var asm = AppDomain.CurrentDomain.GetAssemblies()
.First(a => a.GetName().Name == "ScriptEngine");
var type = asm.GetType("ScriptEngine.ScriptEngine");
var inst = UnityEngine.Object.FindObjectsOfTypeAll(type).First();
type.GetMethod(
"ReloadPlugins",
System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic)
.Invoke(inst, null);
"reloaded"
'
Why this shape matters:
FindObjectOfType(type)can return null for the ScriptEngine singletonFindObjectsOfTypeAll(type).First()finds theBepInEx_ManagerinstanceReloadPluginsis an instance method, not static
After the reload, check BepInEx/LogOutput.log for:
Script Engine] Reloaded all plugins!- your mod's startup log block
- any reload-time exceptions
HotRepl auto-resets its evaluator session after ScriptEngine reload, so the connection dropping and reconnecting once is expected.
AdventureGuide DebugAPI
For AdventureGuide inspection, prefer DebugAPI over raw reflection. DebugAPI methods are static and resolve correctly after F6 hot reload thanks to HotRepl's auto-reset.
# Mod state overview
uv run erenshor eval run 'AdventureGuide.Diagnostics.DebugAPI.DumpState()'
# Quest details
uv run erenshor eval run 'AdventureGuide.Diagnostics.DebugAPI.DumpQuest("TheQuestDBName")'
# Navigation state (target, waypoint, ground path)
uv run erenshor eval run 'AdventureGuide.Diagnostics.DebugAPI.DumpNav()'
# All quests in current zone
uv run erenshor eval run 'AdventureGuide.Diagnostics.DebugAPI.DumpZoneQuests()'
Performance Profiling
For live runtime timing, use the in-game-performance-profiling skill.
Keep this skill focused on HotRepl usage, evaluation quirks, and inspection.
Move detailed benchmarking patterns, Stopwatch helpers, and profiling workflow
guidance into the profiling skill so runtime-eval stays concise.
Unity API Access
Static Unity methods need the full UnityEngine.Object. prefix:
# WRONG
uv run erenshor eval run 'FindObjectsOfType<Camera>().Length'
# RIGHT
uv run erenshor eval run 'UnityEngine.Object.FindObjectsOfType<Camera>().Length'
Pre-imported namespaces: UnityEngine, UnityEngine.SceneManagement, System.Linq.
REPL State
Variables persist across calls. Use eval reset to clear.
uv run erenshor eval run 'var npcs = NPCTable.LiveNPCs;'
uv run erenshor eval run 'npcs.Count'
uv run erenshor eval run 'npcs.Select(n => n.NPCName).Distinct().OrderBy(x => x).ToArray()'
Timeout
Default: 10 seconds. Override per-call:
uv run erenshor eval run --timeout 3000 'while(true){}' # ms, killed after ~3s
Key Files
| File | Purpose |
|---|---|
~/Projects/HotRepl/ | Standalone HotRepl project |
src/erenshor/application/eval/client.py | Python WebSocket client |
src/erenshor/cli/commands/eval.py | CLI commands |
src/mods/AdventureGuide/src/Diagnostics/DebugAPI.cs | AdventureGuide inspection API |
When not to use it
- →Using async/await or anonymous types in evaluated code
- →Performing heavy benchmarking or profiling
- →Modifying game state without testing in a controlled environment
Prerequisites
Limitations
- →Supports C# 7.x only
- →Anonymous types fail to compile
- →REPL state is lost on hot reload
How it compares
It enables live debugging and prototyping without requiring a full build and deployment cycle for every minor code change.
Compared to similar skills
runtime-eval side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| runtime-eval (this skill) | 0 | 10d | Review | Advanced |
| unity-developer | 142 | 3mo | No flags | Advanced |
| csharp-developer | 43 | 2mo | No flags | Advanced |
| csharp-pro | 9 | 3mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
unity-developer
sickn33
Build Unity games with optimized C# scripts, efficient rendering, and proper asset management. Masters Unity 6 LTS, URP/HDRP pipelines, and cross-platform deployment. Handles gameplay systems, UI implementation, and platform optimization. Use PROACTIVELY for Unity performance issues, game mechanics, or cross-platform builds.
csharp-developer
zenobi-us
Expert C# developer specializing in modern .NET development, ASP.NET Core, and cloud-native applications. Masters C# 12 features, Blazor, and cross-platform development with emphasis on performance and clean architecture.
csharp-pro
sickn33
Write modern C# code with advanced features like records, pattern matching, and async/await. Optimizes .NET applications, implements enterprise patterns, and ensures comprehensive testing. Use PROACTIVELY for C# refactoring, performance optimization, or complex .NET solutions.
performance-benchmark
dotnet
Generate and run ad hoc performance benchmarks to validate code changes. Use this when asked to benchmark, profile, or validate the performance impact of a code change in dotnet/runtime.
bug-fix
mono
Fix bugs in SkiaSharp C# bindings. Structured workflow for investigating, fixing, and testing bug reports. Triggers: Crash, exception, AccessViolationException, incorrect output, wrong behavior, memory leak, disposal issues, "fails", "broken", "doesn't work", "investigate issue", "fix issue", "look at #NNNN", any GitHub issue number referencing a bug. For adding new APIs, use `add-api` skill instead.
dotnet-backend-patterns
wshobson
Master C#/.NET backend development patterns for building robust APIs, MCP servers, and enterprise applications. Covers async/await, dependency injection, Entity Framework Core, Dapper, configuration, caching, and testing with xUnit. Use when developing .NET backends, reviewing C# code, or designing API architectures.