Unity-agent-skills jahro-migration
git clone https://github.com/jahro-console/unity-agent-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/jahro-console/unity-agent-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jahro-migration" ~/.claude/skills/jahro-console-unity-agent-skills-jahro-migration && rm -rf "$T"
skills/jahro-migration/SKILL.mdJahro Migration
Help users migrate from custom debug tools to Jahro. Analyze existing code, classify what to replace/keep/adapt, and generate migrated code incrementally.
Migration Decision Guide
When the user shares their existing debug code, classify each component:
| What are you migrating? | Jahro Replacement | Action |
|---|---|---|
IMGUI debug buttons ( + ) | + Visual Mode | Replace — Visual Mode provides a better button UI |
| Canvas-based debug UI | + Visual Mode | Replace — eliminates UI maintenance |
| Custom command parser (string → command) | + Text Mode | Replace — Jahro handles parsing and type conversion |
| Cheat code system (dictionary/registry) | with groups | Replace — typed parameters, auto-discovery |
| Custom Debug.Log wrapper | Remove or keep | Jahro intercepts automatically — wrapper often unnecessary |
| Performance HUD (FPS, memory overlay) | groups | Replace — Watcher provides organized monitoring |
| File-based logger | Keep | Jahro doesn't write to files — keep if file logging is needed |
| Custom Inspector/Editor tools | Evaluate | May complement Jahro — keep if Editor-only tools |
| Analytics-based logging | Keep | Different purpose — Jahro is for debugging, not analytics |
Migration Workflow
- User shares existing debug code — ask to see the files or point to the classes
- Classify each component using the decision guide above
- Generate a migration plan: what to replace, what to keep, what to adapt, effort estimate
- Generate migrated code — file by file, side by side with original
- Support incremental migration — old and new can coexist
- VERIFY at each step — "Enter Play Mode, confirm migrated commands appear in Jahro"
Pattern: IMGUI Debug Menu → Jahro Commands
Before (IMGUI)
public class DebugMenu : MonoBehaviour { private bool showMenu; void OnGUI() { if (GUI.Button(new Rect(10, 10, 100, 30), "Toggle")) showMenu = !showMenu; if (!showMenu) return; if (GUI.Button(new Rect(10, 50, 150, 30), "God Mode")) Player.GodMode = true; if (GUI.Button(new Rect(10, 90, 150, 30), "Add 1000 Gold")) Player.Gold += 1000; if (GUI.Button(new Rect(10, 130, 150, 30), "Skip Level")) LevelManager.SkipToNext(); GUI.Label(new Rect(10, 170, 200, 30), $"FPS: {1f/Time.deltaTime:F0}"); GUI.Label(new Rect(10, 200, 200, 30), $"Health: {Player.Health}"); } }
After (Jahro)
using JahroConsole; using UnityEngine; public class DebugCommands : MonoBehaviour { [JahroCommand("god-mode", "Cheats", "Enable god mode")] public static void GodMode() => Player.GodMode = true; [JahroCommand("add-gold", "Cheats", "Add 1000 gold")] public static void AddGold() => Player.Gold += 1000; [JahroCommand("skip-level", "Game", "Skip to next level")] public static void SkipLevel() => LevelManager.SkipToNext(); [JahroWatch("FPS", "Performance")] public static string FPS => (1f / Time.unscaledDeltaTime).ToString("F0"); [JahroWatch("Health", "Player")] public static int Health => Player.Health; }
What changed:
actions →GUI.Button
static methods[JahroCommand]
monitors →GUI.Label
static properties[JahroWatch]
class can be deleted after migrationOnGUI- Visual Mode replaces the custom button UI — no IMGUI maintenance
- No
needed since everything is staticRegisterObject
Parameterized version
If the original had user input (e.g., text field for gold amount):
[JahroCommand("add-gold", "Cheats", "Add gold to player")] public static void AddGold(int amount) => Player.Gold += amount;
Visual Mode auto-generates an input field; Text Mode accepts
add-gold 500.
Pattern: Custom Logger → Jahro (Usually Remove)
Before
public static class GameLogger { public static void Log(string category, string message) => Debug.Log($"[{category}] {message}"); public static void LogWarning(string category, string message) => Debug.LogWarning($"[{category}] {message}"); public static void LogError(string category, string message) => Debug.LogError($"[{category}] {message}"); }
After
No migration needed. Jahro automatically intercepts all
Debug.Log, Debug.LogWarning, and Debug.LogError calls. The logs appear in Jahro's console with filtering and search.
Decision:
- If the wrapper only formats messages → remove it (Jahro shows full messages)
- If the wrapper adds categorization you rely on → keep it (Jahro still captures the output)
- If the wrapper writes to files → keep it (Jahro doesn't do file logging)
There is no
Jahro.Log() API — Jahro works by intercepting Unity's logging system.
Pattern: Cheat Command System → Jahro Commands
Before
public class CheatManager { private Dictionary<string, Action<string[]>> cheats = new(); public void RegisterCheat(string name, Action<string[]> handler) => cheats[name] = handler; public void Execute(string input) { var parts = input.Split(' '); if (cheats.TryGetValue(parts[0], out var handler)) handler(parts[1..]); } } // Registration: // mgr.RegisterCheat("god", _ => Player.GodMode = true); // mgr.RegisterCheat("gold", args => Player.Gold += int.Parse(args[0])); // mgr.RegisterCheat("tp", args => Player.Teleport( // float.Parse(args[0]), float.Parse(args[1]), float.Parse(args[2])));
After (attribute-based)
using JahroConsole; using UnityEngine; public class Cheats : MonoBehaviour { [JahroCommand("god-mode", "Cheats", "Enable god mode")] public void GodMode() => Player.GodMode = true; [JahroCommand("add-gold", "Cheats", "Add gold")] public void AddGold(int amount) => Player.Gold += amount; [JahroCommand("teleport", "Cheats", "Teleport to position")] public void Teleport(Vector3 position) => Player.Teleport(position); void OnEnable() => Jahro.RegisterObject(this); void OnDisable() => Jahro.UnregisterObject(this); }
After (dynamic registration, if keeping runtime flexibility)
void Start() { Jahro.RegisterCommand("god-mode", "Cheats", "Enable god mode", () => Player.GodMode = true); Jahro.RegisterCommand<int>("add-gold", "Cheats", "Add gold", amount => Player.Gold += amount); Jahro.RegisterCommand<float, float, float>("teleport", "Cheats", "Teleport to X Y Z", (x, y, z) => Player.Teleport(new Vector3(x, y, z))); }
What changed:
- String-based
→ typed parameters (Action<string[]>
,int
,float
)Vector3 - Manual
+string.Split
→ Jahro handles type conversionint.Parse - Dictionary registry → attribute discovery or
RegisterCommand - Custom input UI → Jahro's Text Mode (autocomplete) and Visual Mode (forms)
class can be removed after migrationCheatManager
Pattern: Performance HUD → Jahro Watcher
Before
void OnGUI() { GUI.Label(new Rect(10, 10, 200, 30), $"FPS: {1f/Time.deltaTime:F0}"); GUI.Label(new Rect(10, 40, 200, 30), $"Memory: {GetMemoryMB():F1} MB"); GUI.Label(new Rect(10, 70, 200, 30), $"Objects: {FindObjectsOfType<GameObject>().Length}"); }
After
public static class PerfMonitor { [JahroWatch("FPS", "Performance", "Frames per second")] public static string FPS => (1f / Time.unscaledDeltaTime).ToString("F0"); [JahroWatch("Memory", "Performance", "Managed memory usage")] public static string Memory => $"{GC.GetTotalMemory(false) / 1024f / 1024f:F1} MB"; [JahroWatch("Object Count", "Performance", "Active GameObjects")] public static int ObjectCount => Object.FindObjectsOfType<GameObject>().Length; }
Advantage: Watcher only reads values when the tab is open — the
OnGUI version runs every frame. For expensive queries like FindObjectsOfType, consider caching.
Incremental Migration
Old and new systems can coexist during transition:
- Add Jahro commands alongside existing debug UI
- Verify commands work in Jahro console
- Remove old UI code for the migrated features
- Repeat until all features are migrated
- Remove the old debug system classes when done
This avoids a big-bang migration and lets the team validate each step.
Migration Effort Estimates
| Component | Effort | Notes |
|---|---|---|
| IMGUI buttons → JahroCommand | Low | One attribute per button, remove OnGUI |
| Canvas debug UI → JahroCommand | Low-Medium | Remove UI prefab + code, add attributes |
| Custom command parser → JahroCommand | Medium | Rewrite registrations with typed params |
| Performance HUD → JahroWatch | Low | Replace labels with watch attributes |
| Custom logger → (remove) | Very Low | Just remove, Jahro intercepts Debug.Log |
| Cheat system with persistence | Medium | Migrate commands, keep save/load logic separately |
Contextual Awareness
| Pattern in code | Suggestion |
|---|---|
with debug buttons or labels | Migrate to JahroCommand + JahroWatch |
| Custom command dictionary/registry | Migrate to JahroCommand attributes |
wrapper class | Explain auto-interception, suggest removal |
| Performance overlay (FPS, memory) | Migrate to JahroWatch |
| Custom input field for commands | Replace with Jahro Text Mode |
Verification
After each migration step:
Verify: Enter Play Mode → press ~ → confirm migrated commands appear in the Commands tab and migrated watchers appear in the Watcher tab. Test executing a command. Then verify the old debug UI can be removed without breaking anything.
If migrated features don't appear, check the jahro-troubleshooting skill.