This skill should be used when the user asks to "debug", "create test script", "analyze replay report", "why isn't my game", "test if", "verify that", "check if", "reproduce bug", "frame-by-frame", or mentions "ncrs", "replay test", "replay debugging", "snap", "assertion", or debugging game behavior via replay scripts.
/plugin marketplace add nethercore-systems/nethercore-ai-plugins/plugin install zx-dev@nethercore-ai-pluginsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
examples/action-setup.ncrsexamples/collision-test.ncrsexamples/jump-test.ncrsexamples/movement-test.ncrsreferences/ncrs-format.mdDebug ZX games using scriptable replay tests. Generate NCRS (Nethercore Replay Script) files that reproduce bugs, capture state snapshots, and verify assertions frame-by-frame.
The replay debugging system enables AI-assisted debugging by:
This transforms debugging from "describe what you see" to "write what should happen, get precise feedback."
Ask clarifying questions if needed:
Generate a minimal .ncrs script:
snap: true on frame 0 to capture initial stateInstruct user to run:
nether replay run test.ncrs --report report.json
When user shares the report, analyze for root cause.
Keep scripts minimal (under 100 frames when possible):
# Basic test structure
console = "zx"
seed = 0
players = 1
frames = [
{ f = 0, p1 = "idle", snap = true }, # Initial state
{ f = 1, p1 = "a", snap = true, assert = "$velocity_y < 0" }, # Action + verify
{ f = 10, p1 = "idle", snap = true }, # After effect
]
Key principles:
Reports contain snapshots showing pre/post state per frame:
{
"snapshots": [
{
"frame": 1,
"input": "a",
"pre": { "$velocity_y": 0, "$on_ground": true },
"post": { "$velocity_y": -8.0, "$on_ground": false },
"delta": { "$velocity_y": -8.0, "$on_ground": "true -> false" }
}
],
"assertions": [
{ "frame": 1, "condition": "$velocity_y < 0", "passed": true, "actual": -8.0 }
]
}
Focus on:
delta - What changed each frame (the key insight)Common diagnosis patterns:
console = "zx" # Required: Console type
seed = 0 # Required: Random seed for determinism
players = 1 # Required: Player count (1-4)
frames = [
{ f = 0, p1 = "idle" },
{ f = 1, p1 = "a", snap = true },
{ f = 2, p1 = "a", assert = "$velocity_y < 0" },
]
| Field | Purpose | Example |
|---|---|---|
f | Frame number | f = 60 |
p1-p4 | Player inputs | p1 = "right+a" |
snap | Capture pre/post state | snap = true |
assert | Pass/fail condition | assert = "$health > 0" |
action | Debug action to invoke | action = "Load Level" |
action_params | Action parameters | action_params = { level = 2 } |
Button names: idle, up, down, left, right, a, b, x, y, l, r, l2, r2, start, select
Combinations: Use + to combine: "right+a", "up+right+b"
Supported: ==, !=, <, >, <=, >=
assert = "$velocity_y < 0" # Negative velocity (jumping up)
assert = "$on_ground == true" # Boolean check
assert = "$health >= 50" # Range check
Games register debug variables with $ prefix. Scan code for debug_register_* calls to find available variables:
// In game init()
debug_register_f32(b"player_x", 8, &PLAYER_X); // -> $player_x
debug_register_f32(b"velocity_y", 10, &VEL_Y); // -> $velocity_y
debug_register_bool(b"on_ground", 9, &ON_GROUND); // -> $on_ground
Common variables:
$player_x, $player_y - Position$velocity_x, $velocity_y - Movement$on_ground - Grounded state$health, $score - Game stateGames can register callable debug actions with parameters. Use these in scripts to skip setup and focus on the bug.
Instead of:
Use:
action = "Load Level" to skip to specific levelsaction = "Set Player Position" to place playeraction = "Spawn Enemy" to create test scenariosgrep -r "debug_action_begin" src/
Example registration in game code:
debug_action_begin(b"Load Level".as_ptr(), 10, b"debug_load_level".as_ptr(), 16);
debug_action_param_i32(b"level".as_ptr(), 5, 1); // param "level", default 1
debug_action_end();
# Skip to level 2 for testing
[[frames]]
f = 0
action = "Load Level"
action_params = { level = 2 }
# Now test from level 2
[[frames]]
f = 1
p1 = "idle"
snap = true
| Action | Parameters | Use Case |
|---|---|---|
| Load Level | { level = N } | Skip to specific level |
| Set Position | { x, y } | Place player for collision tests |
| Set Health | { health = N } | Test low-health scenarios |
| Spawn Enemy | { type, x, y } | Create specific test scenarios |
| Skip Menu | (none) | Bypass title/menu screens |
| God Mode | { enabled = bool } | Isolate mechanics from damage |
# Run script and generate report
nether replay run test.ncrs --report report.json
# Run headlessly (no window, for CI)
nether replay run test.ncrs --headless --report report.json
# Stop on first failed assertion
nether replay run test.ncrs --fail-fast
# Validate script syntax without running
nether replay validate test.ncrs
User: "My player doesn't jump when I press A"
Response:
# jump_test.ncrs - Test jump mechanics
console = "zx"
seed = 0
players = 1
frames = [
{ f = 0, p1 = "idle", snap = true }, # Initial state
{ f = 1, p1 = "a", snap = true, assert = "$velocity_y < 0" }, # Jump frame
{ f = 2, p1 = "a", snap = true }, # Holding jump
{ f = 10, p1 = "idle", snap = true }, # After jump
]
Run: nether replay run jump_test.ncrs --report report.json
Share the report for analysis.
Report shows $velocity_y stayed 0 after pressing A:
The report shows $velocity_y remained 0 after pressing A at frame 1. This indicates the jump is not applying velocity.
Common causes:
input.a_pressed() instead of input.a_just_pressed()Read the jump handling code to identify the specific issue.
Store test scripts in a dedicated directory:
game-project/
└── tests/
└── replay/
├── jump_test.ncrs
├── collision_test.ncrs
└── movement_test.ncrs
For detailed NCRS format specification:
references/ncrs-format.md - Complete format reference with all optionsWorking examples in examples/:
jump-test.ncrs - Jump mechanics debuggingcollision-test.ncrs - Collision detection debuggingmovement-test.ncrs - Movement debuggingaction-setup.ncrs - Using debug actions for test setupdebugging-guide - F4 panel, sync testing, debug registrationtesting-fundamentals (zx-test) - Sync tests, replay regressionUse these slash commands for common operations:
/replay-test [description] - Generate test script from bug description/replay-analyze [path] - Analyze a report.json file/replay-template [type] - Generate template (jump, collision, movement, etc.)This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.