Skip to content
Back to skills

Godot Refactor

ASecurity

Use when Godot project has code-created objects, tight coupling via direct references, monolithic scripts over 150 lines, or needs scene-first architecture with signals and composition. Orchestrates all 5 code quality mini-skills: extract-to-scenes, split-scripts, add-signals, extract-resources, and clean-conflicts. Each operation runs independently with git commits and validation.

  • 666 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added February 8, 2026
developmentgobashnodetestingdebuggingrefactoringgitperformance

Security analysis

A100/100

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill godot-refactor --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Godot Refactor?

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

Security grade badge for Godot Refactor
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-godot-refactor/badge)](https://www.skillsdirectory.com/skills/majiayu000-godot-refactor)

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: godot-refactor
version: 3.0.0
displayName: "Godot Refactoring Orchestrator"
description: >
  Use when Godot project has code-created objects, tight coupling via direct references,
  monolithic scripts over 150 lines, or needs scene-first architecture with signals and
  composition. Orchestrates all 5 code quality mini-skills: extract-to-scenes, split-scripts,
  add-signals, extract-resources, and clean-conflicts. Each operation runs independently
  with git commits and validation.
author: "Asreonn"
license: MIT
category: game-development
type: agent
difficulty: intermediate
audience: [developers, teams]
keywords:
  - godot
  - refactoring
  - code-quality
  - scene-architecture
  - signals
  - composition
  - gdscript
  - clean-code
  - godot4
platforms: [macos, linux, windows]
repository: https://github.com/asreonn/godot-superpowers
homepage: https://github.com/asreonn/godot-superpowers#readme
filesystem:
  read:
    - "${PROJECT_ROOT}/**/*.gd"
    - "${PROJECT_ROOT}/**/*.tscn"
    - "${PROJECT_ROOT}/project.godot"
    - "${PROJECT_ROOT}/**/*.tres"
  write:
    - "${PROJECT_ROOT}/**/*.gd"
    - "${PROJECT_ROOT}/**/*.tscn"
    - "${PROJECT_ROOT}/components/**"
    - "${PROJECT_ROOT}/resources/**"
  deny:
    - "**/.env*"
    - "**/secrets*"
    - "**/*.key"
    - "**/*.pem"
behavior:
  timeout: 600
  retry: 3
  cache: true
  interactive: true
use_cases:
  - "Building new features and code uses .new() instead of scenes"
  - "Scripts are over 150 lines and do too many things"
  - "Code has get_node() chains creating tight coupling"
  - "Game data is hardcoded in const arrays"
  - "Need clean architecture for team collaboration"
  - "Preparing code for review or testing"
  - "Want full project refactoring with all operations"
outputs: "Component library, split scripts, signal architecture, resource files, git commits per operation"
requirements: "Git repository, Godot 4.x, bash tools (grep, find, awk)"
execution: "Fully automatic with user approval after Phase 1 analysis"
auto_rollback: "Yes - auto-reverts on validation test failure"
integration: "Orchestrates: godot-extract-to-scenes, godot-split-scripts, godot-add-signals, godot-extract-resources, godot-clean-conflicts"
---

# Godot Refactor Orchestrator

**This orchestrator runs 5 code quality mini-skills in sequence. For individual operations, invoke mini-skills directly.**

## Core Principle: Scene-First, Signal-Based, Component Composition

**Iron Law**: NO functional or visual changes during refactoring. Period.

This skill automatically refactors Godot projects to cleaner, more modular architecture while preserving exact behavior. Every operation creates a git commit. Rollback is always available.

---

## UPON INVOCATION - START HERE

When this skill is invoked, IMMEDIATELY execute the following sequence:

### 1. Verify Godot Project (5 seconds)

```bash
# Check if this is a Godot project
ls project.godot 2>/dev/null && echo "✓ Godot project detected" || echo "✗ Not a Godot project"
```

**If NOT a Godot project:**
- Inform user this skill only works on Godot projects
- Ask if they want to navigate to the correct directory
- STOP here

**If IS a Godot project:**
- Proceed to step 2

### 2. Begin Phase 1: Analysis & Baseline (AUTOMATIC)

**Do NOT ask "What would you like me to do?" - Start analyzing immediately.**

Execute these commands in parallel:

```bash
# Detect code-created objects
grep -rn "\.new()" --include="*.gd" . | grep -E "(Node|Timer|Area|Sprite|Control|Collision)" | wc -l

# Detect monolithic scripts
find . -name "*.gd" -exec wc -l {} + | awk '$1 > 150' | wc -l

# Detect tight coupling
grep -rn "get_node\|has_method" --include="*.gd" . | wc -l

# Detect inline data
grep -rn "^[[:space:]]*const.*\[" --include="*.gd" . | wc -l
```

### 3. Present Findings (30 seconds)

Show the user:
```
=== Godot Refactoring Analysis ===

Project: [project name from project.godot]

Anti-patterns detected:
- Code-created objects: X
- Monolithic scripts: X
- Tight coupling: X
- Inline data: X
- Conflicting operations: (will be detected after refactoring)

Total: X anti-patterns found

Refactoring includes:
✓ Automatic testing after each operation
✓ Auto-rollback on test failure
✓ Git commit per operation
✓ Push to remote on demand

Would you like me to:
1. Proceed with automatic refactoring (recommended)
2. Show detailed breakdown first
3. Cancel
```

### 4. Wait for User Choice

- **If 1 (Proceed):** Start Phase 2 immediately
- **If 2 (Details):** Show detailed file-by-file breakdown, then offer to proceed
- **If 3 (Cancel):** Exit skill

**CRITICAL**: Do NOT stop after loading the skill. Do NOT ask "What would you like me to do?" Start with step 1 immediately.

---

## When to Use This Skill

Use this skill when you detect ANY of these symptoms:

**Code-Created Objects:**
- `.new()` calls in `_ready()`, `_process()`, or other lifecycle methods
- `add_child()` with programmatically created nodes
- Timers, Areas, Sprites created in code

**Monolithic Scripts:**
- Scripts >150 lines
- Multiple unrelated responsibilities in one file
- God objects that do everything

**Tight Coupling:**
- `get_node()` chains to access other nodes
- `has_method()` checks before calling
- Direct property access across nodes
- Parent-child dependencies for behavior

**Inline Data:**
- `const` arrays with game data
- Hardcoded configuration in scripts
- Data that should be resources

**Deep Inheritance:**
- More than 2 levels of script inheritance
- Inheritance used for code reuse instead of composition

### Decision Flowchart

```
User mentions Godot project
    ↓
Does it have ANY of the above symptoms?
    ↓ YES                    ↓ NO
Use this skill              Regular development
    ↓
Run Phase 1: Analysis
    ↓
Anti-patterns found?
    ↓ YES                    ↓ NO
Run Phases 2-4              Document clean state
```

---

## The Four Phases

### Phase 1: Analysis & Baseline (Automatic)

**Purpose**: Detect all anti-patterns and create safety baseline.

**Steps:**

1. **Scan Project Files**
```bash
# Find all Godot script files
find . -name "*.gd" -type f

# Find all scene files
find . -name "*.tscn" -type f
```

2. **Detect Anti-Patterns**

Use detection patterns from `anti-patterns-detection.md`:

```bash
# Code-created objects
grep -rn "\.new()" --include="*.gd" .

# Monolithic scripts (>150 lines)
find . -name "*.gd" -exec wc -l {} + | awk '$1 > 150 {print $2 " (" $1 " lines)"}'

# Tight coupling
grep -rn "get_node\|get_parent\|has_method" --include="*.gd" .

# Inline data
grep -rn "^[[:space:]]*const.*\[" --include="*.gd" .
```

3. **Create Git Baseline**

```bash
# Save current branch
current_branch=$(git branch --show-current)

# Create baseline tag
git tag baseline-$(date +%Y%m%d-%H%M%S)

# Initial commit if there are uncommitted changes
git add .
git commit -m "Baseline: Pre-refactoring state (on $current_branch)"
```

4. **Generate Refactoring Manifest**

Create a priority-ordered list:

| Priority | Anti-Pattern | File | Lines | Operation |
|----------|-------------|------|-------|-----------|
| 1 | Inline data | enemy_data.gd | 45-78 | Extract to .tres |
| 2 | Code-created Timer | laser_beam.gd | 38-45 | Extract to .tscn |
| 3 | Tight coupling | base_station.gd | 92 | Signal decoupling |
| 4 | Monolithic script | player_movement.gd | 287 lines | Split script |

**Phase 1 Output:**
- ✓ Baseline git commit/tag created
- ✓ Anti-patterns detected and prioritized
- ✓ Manifest table generated
- ✓ Ready for automatic refactoring

---

### Phase 2: Automatic Refactoring (Five Operations)

Process anti-patterns in priority order: Data → Scenes → Signals → Scripts → Conflicts

**CRITICAL - After Each Operation:**
1. Git commit the changes
2. **Run automatic validation test**
3. If test fails: Auto-revert and report error
4. If test passes: **Continue automatically to next operation**
5. No user prompt unless test fails or user confirmation needed

**Automatic Testing Procedure:**
```bash
# Quick validation test (runs after each git commit)
echo "Running validation test..."
godot --headless --quit-after 5 project.godot 2>&1 | tee test_output.log

# Check for errors
if grep -q "ERROR\|SCRIPT ERROR\|Parse Error" test_output.log; then
    echo "⚠️  Tests failed - reverting operation"
    git reset --hard HEAD~1
    echo "❌ Operation reverted. Error details:"
    grep "ERROR\|SCRIPT ERROR\|Parse Error" test_output.log
    # STOP and report to user
else
    echo "✓ Tests passed - continuing"
    rm test_output.log
    # CONTINUE to next operation automatically
fi
```

**Note:** If test fails, STOP workflow and report to user. Otherwise, continue automatically through all operations.

#### Operation A: Extract Code-Created Objects to Modular Components

**Target**: Any `.new()` calls that create nodes

**Enhanced Process:**

1. **Detect and Analyze**
   - Find `.new()` calls for node types
   - Extract 30 lines of context (properties, methods, signals)
   - Analyze variable names, properties, methods
   - Consult `node-selection-guide.md` decision trees
   - Calculate confidence score for node type
   - Select optimal node from `godot-node-reference.md`

2. **Check Component Library**
   - Does `components/{category}/` exist? (e.g., `components/timers/`)
   - If YES: Reuse base component, skip to Step 4
   - If NO: Generate full component structure (Steps 2-3)

3. **Generate Component (First Time Only)**
   - Create `{type}_config.gd` (Resource class with @export properties)
   - Create `configurable_{type}.gd` (Script that extends node, applies config)
   - Create `configurable_{type}.tscn` (Base scene with script)
   - Creates modular, reusable foundation

4. **Generate Preset Resource**
   - Extract properties from analyzed code
   - Create `presets/{preset_name}.tres` (specific configuration)
   - Each detected instance gets unique preset
   - Presets reference the base component

5. **Update Parent Scene**
   - Add ext_resource entries for base scene and preset
   - Instance base component with preset resource
   - Same scene reused, different presets = ZERO duplication

6. **Update Parent Script**
   - Add @onready reference to component instance
   - Keep signal connections
   - Remove .new(), add_child(), static property assignments
   - Configuration now comes from preset resource

7. **Git Commit & Validate**
   - Commit all component files and parent changes
   - Run validation test
   - Ensure behavior unchanged

**Example Transformation:**

Before (Code-Created):
```gdscript
func _ready():
    _damage_timer = Timer.new()
    _damage_timer.wait_time = 0.5
    _damage_timer.one_shot = false
    add_child(_damage_timer)
    _damage_timer.timeout.connect(_on_damage)

    _cooldown_timer = Timer.new()
    _cooldown_timer.wait_time = 2.0
    _cooldown_timer.one_shot = true
    add_child(_cooldown_timer)
    _cooldown_timer.timeout.connect(_on_cooldown)
```

After (First Timer - Full Component Created):
```
Files created:
✓ components/timers/timer_config.gd (resource class)
✓ components/timers/configurable_timer.gd (reusable script)
✓ components/timers/configurable_timer.tscn (reusable base scene)
✓ components/timers/presets/damage_timer.tres (configuration preset)

parent.gd:
@onready var _damage_timer: ConfigurableTimer = $DamageTimer

func _ready():
    _damage_timer.timeout.connect(_on_damage)
```

After (Second Timer - Reuses Base):
```
Files created:
✓ components/timers/presets/cooldown_timer.tres (NEW preset only!)

parent.gd:
@onready var _damage_timer: ConfigurableTimer = $DamageTimer
@onready var _cooldown_timer: ConfigurableTimer = $CooldownTimer

func _ready():
    _damage_timer.timeout.connect(_on_damage)
    _cooldown_timer.timeout.connect(_on_cooldown)
```

**Key Benefits:**

- ✅ Intelligent node selection (no arbitrary choices)
- ✅ Modular components (reusable across project)
- ✅ Zero duplication (same base, different presets)
- ✅ Inspector-configurable (edit presets in editor)
- ✅ Automatic library building (grows organically)
- ✅ Signal connections preserved
- ✅ Behavior unchanged (Iron Law maintained)

**Success Criteria:**
- Component structure created (if first of type)
- Preset resource created with extracted values
- Parent scene instances component with preset
- Parent script has @onready reference
- Signal connections work
- Old code removed
- Behavior unchanged

---

#### Operation B: Split Monolithic Scripts

**Target**: Scripts >150 lines with multiple responsibilities

**Detection:**
```bash
find . -name "*.gd" -exec wc -l {} + | awk '$1 > 150'
```

**For each detected script:**

1. **Analyze script structure**
   - Identify logical sections (look for comment headers, function groups)
   - Find responsibilities (input, physics, abilities, UI, etc.)
   - Determine dependencies between sections

2. **Plan split**
   - Main script keeps core responsibility
   - Extract secondary responsibilities to components
   - Define signal interface between components

3. **Create component scripts**

   Example: Split `player_movement.gd` (287 lines)

   Extract to `player_abilities.gd`:
   ```gdscript
   extends Node
   class_name PlayerAbilities

   signal ability_used(ability_name: String)
   signal cooldown_started(duration: float)

   # Ability-related functions moved here
   ```

4. **Update main script**
   ```gdscript
   @onready var abilities: PlayerAbilities = $Abilities

   func _ready():
       abilities.ability_used.connect(_on_ability_used)
   ```

5. **Implement signal communication**
   - Replace direct function calls with signals
   - Connect signals in _ready()
   - Remove tight coupling

6. **Git commit**
   ```bash
   git add player_movement.gd player_abilities.gd
   git commit -m "Refactor: Split abilities from player_movement.gd"
   ```

7. **Run automatic test** (see Phase 2 header for test procedure)

**Success criteria:**
- Main script <150 lines
- Component scripts focused (80-120 lines optimal)
- Signal-based communication
- No direct dependencies
- Behavior unchanged

---

#### Operation C: Implement Signal-Based Decoupling

**Target**: Direct coupling via get_node(), has_method(), direct calls

**Detection:**
```bash
grep -rn "get_node\|has_method" --include="*.gd" .
```

**For each detected coupling:**

1. **Identify the relationship**
   - What is being accessed?
   - What information is being exchanged?
   - Is this event-based or state query?

2. **Create/use Events autoload**

   If not exists, create `events.gd`:
   ```gdscript
   extends Node
   # Global event bus

   signal player_entered_safe_zone(zone: Node2D)
   signal enemy_spawned(enemy: Node2D)
   signal score_changed(new_score: int)
   ```

   Add to project settings: Project → Project Settings → Autoload

3. **Replace direct coupling with signals**

   Before:
   ```gdscript
   func _on_body_entered(body):
       if body.has_method("set_beam_enabled"):
           body.set_beam_enabled(false)
   ```

   After (emitter):
   ```gdscript
   func _on_body_entered(body):
       if body.is_in_group("player"):
           Events.player_entered_safe_zone.emit(self)
   ```

   After (receiver):
   ```gdscript
   func _ready():
       Events.player_entered_safe_zone.connect(_on_safe_zone)

   func _on_safe_zone(zone):
       set_beam_enabled(false)
   ```

4. **Remove coupling code**
   - Delete get_node() calls
   - Delete has_method() checks
   - Delete direct property access

5. **Git commit**
   ```bash
   git add events.gd base_station.gd player_movement.gd
   git commit -m "Refactor: Decouple base_station from player via signals"
   ```

6. **Run automatic test** (see Phase 2 header for test procedure)

**Success criteria:**
- No get_node() for behavior access
- No has_method() checks
- Events.gd exists and is used
- Signal connections established
- Behavior unchanged

---

#### Operation D: Extract Data to .tres Resources

**Target**: `const` declarations with game data

**Detection:**
```bash
grep -rn "^[[:space:]]*const.*\[" --include="*.gd" .
```

**For each detected data constant:**

1. **Analyze data structure**
   ```gdscript
   const ENEMY_TYPES = [
       {"type": "basic", "health": 100, "speed": 200},
       {"type": "fast", "health": 50, "speed": 400}
   ]
   ```

2. **Create Resource class**

   Create `enemy_type_data.gd`:
   ```gdscript
   extends Resource
   class_name EnemyTypeData

   @export var type_name: String
   @export var health: int
   @export var speed: float
   ```

3. **Generate .tres files**

   Create `enemy_types/basic.tres`:
   ```ini
   [gd_resource type="EnemyTypeData" load_steps=2 format=3]

   [ext_resource type="Script" path="res://enemy_type_data.gd" id="1"]

   [resource]
   script = ExtResource("1")
   type_name = "basic"
   health = 100
   speed = 200.0
   ```

4. **Update script to use resources**
   ```gdscript
   @export var enemy_types: Array[EnemyTypeData]

   # In scene, assign resources via inspector
   ```

5. **Remove const declaration**

6. **Git commit**
   ```bash
   git add enemy_type_data.gd enemy_types/*.tres enemy_spawner.gd
   git commit -m "Refactor: Extract enemy data to .tres resources"
   ```

7. **Run automatic test** (see Phase 2 header for test procedure)

**Success criteria:**
- Resource class created
- .tres files generated with correct data
- Script updated to use resources
- Const declaration removed
- Behavior unchanged

---

#### Operation E: Clean Conflicting/Ineffective Operations

**Target**: Code that runs without errors but has no effect or conflicts with other code

**IMPORTANT**: This operation runs **after** Operations A-D are complete, as refactoring may introduce or remove conflicts.

**Detection:**
```bash
# Run comprehensive conflict detection
bash << 'EOF'
echo "=== Detecting Conflicting Operations ==="

# Self-assignments
echo "Self-assignments:"
grep -rn "position\s*=\s*position\|scale\s*=\s*scale\|rotation\s*=\s*rotation" --include="*.gd" .

# Redundant defaults
echo "Redundant defaults:"
grep -rn "modulate\s*=\s*Color\.WHITE\|scale\s*=\s*Vector2\.ONE" --include="*.gd" .

# Duplicate property assignments (common properties)
echo "Checking for duplicate assignments..."
for prop in "scale" "position" "rotation" "modulate" "visible"; do
    grep -rn "\.$prop\s*=" --include="*.gd" . | \
    awk -F: -v prop="$prop" '{
        file=$1; line=$2;
        if (file==prev_file && line-prev_line<20) {
            print file":"prev_line" and "line" - Duplicate "prop
        }
        prev_file=file; prev_line=line
    }'
done

# Conflicting tweens
echo "Conflicting tweens:"
grep -n "tween_property" --include="*.gd" -r . | \
awk -F: '{
    file=$1; line=$2;
    if (match($0, /tween_property.*"([^"]+)"/, arr)) {
        prop=arr[1];
        key=file":"prop;
        if (key in seen && line-seen[key]<15) {
            print file":"seen[key]" and "line" - Conflicting tweens on "prop
        }
        seen[key]=line
    }
}'

# Code after queue_free
echo "Code after queue_free:"
grep -A2 "queue_free()" --include="*.gd" . | grep -v "^--$"

EOF
```

**For each detected conflict:**

1. **Auto-fix** (no user input):
   - Self-assignments: Remove entirely
   - Code after `queue_free()`: Move code before queue_free
   - Obvious redundant defaults: Remove

2. **User confirmation** (ask user):
   - Duplicate assignments: Which value to keep?
   - Conflicting tweens: Which to keep or chain?
   - Multiple process calls: Final intended state?

3. **Example fixes:**

   **Self-assignment:**
   ```gdscript
   # Before
   position = position

   # After (remove line)
   ```

   **Duplicate assignment:**
   ```gdscript
   # Before
   sprite.scale = Vector2(2, 2)  # Line 45
   sprite.scale = Vector2(1, 1)  # Line 52

   # After (keep last)
   sprite.scale = Vector2(1, 1)  # Line 52
   ```

   **Conflicting tweens (user chose "chain"):**
   ```gdscript
   # Before
   var tween1 = create_tween()
   tween1.tween_property(self, "scale", Vector2(2,2), 1.0)
   var tween2 = create_tween()
   tween2.tween_property(self, "scale", Vector2(0.5,0.5), 1.0)

   # After
   var tween = create_tween()
   tween.tween_property(self, "scale", Vector2(2,2), 1.0)
   tween.tween_property(self, "scale", Vector2(0.5,0.5), 1.0)
   ```

4. **Git commit**
   ```bash
   git add <modified files>
   git commit -m "Refactor: Clean conflicting/ineffective operations

   - Removed self-assignments
   - Fixed duplicate property assignments
   - Resolved conflicting tweens
   - Cleaned up redundant operations

   No functional changes - code cleanup only"
   ```

5. **Run automatic test** (see Phase 2 header for test procedure)

**Success criteria:**
- No self-assignments remain
- No obvious duplicate assignments
- Conflicting tweens resolved
- Code after queue_free() moved
- Behavior unchanged

**Note:** See `conflicting-operations-detection.md` for comprehensive detection patterns and `refactoring-operations.md` Operation E for detailed procedures.

---

### Phase 3: Git Commits (Automatic)

**After each operation**, commit with clear message:

```bash
# Template
git add <files>
git commit -m "Refactor: <Operation> in <file> - <specific change>"

# Examples
git commit -m "Refactor: Extract Timer to scene in laser_beam.gd"
git commit -m "Refactor: Split abilities from player_movement.gd (287→142 lines)"
git commit -m "Refactor: Decouple base_station from player via signals"
git commit -m "Refactor: Extract enemy data to .tres resources"
git commit -m "Refactor: Clean conflicting/ineffective operations"
```

**After all operations:**
```bash
git tag refactor-complete-$(date +%Y%m%d)
```

**Commit history should show:**
- Baseline commit
- One commit per refactoring operation (A, B, C, D, E)
- Clear, descriptive messages
- Easy to review
- Easy to rollback individual changes

**Push on Demand:**

After all operations complete, ask user:
```
=== Refactoring Complete ===

All operations completed successfully!
5 operations performed, X commits created on current branch.

Would you like to push to remote?
1. Yes, push now
2. No, I'll push manually later
3. Show me the commit log first

Choice [1-3]:
```

**If user chooses 1 (push now):**
```bash
# Push to current branch's remote
git push origin $(git branch --show-current)
```

**If user chooses 3 (show log first):**
```bash
git log --oneline --graph baseline-*..HEAD
# Then ask again: Push now? [y/n]
```

**If user says "push" or "push et" at ANY time during the workflow:**
```bash
# Immediately push current branch
git push origin $(git branch --show-current)
echo "✓ Pushed to remote"
```

---

### Phase 4: Final Verification (Minimal, Automatic)

**Purpose**: Ensure no functional or visual regressions.

**Steps:**

1. **Open project in Godot**
   ```bash
   godot --editor path/to/project.godot
   ```

2. **Check for errors**
   - No red errors in console
   - No yellow warnings about missing nodes
   - All scenes load successfully

3. **Visual verification**
   - Run main scene
   - Quick visual check (30 seconds)
   - Compare against expected behavior

4. **Play test checklist** (from `verification-checklist.md`):
   - [ ] Player movement works
   - [ ] Abilities trigger correctly
   - [ ] Enemies spawn and behave normally
   - [ ] UI updates properly
   - [ ] No crashes or errors

5. **Performance baseline** (optional):
   ```bash
   # Compare FPS before/after
   # Should be identical ±2 FPS
   ```

**If verification fails:**

```bash
# Rollback procedure
git reset --hard baseline-YYYYMMDD-HHMMSS
git tag refactor-failed-$(date +%Y%m%d-%H%M%S)

# Report what broke
# Debug with systematic-debugging skill
```

**If verification succeeds:**

Report summary:
```
✓ Refactoring complete
✓ 8 operations performed
✓ 287 lines reduced to 142 across 3 files
✓ 4 .tscn scenes created
✓ 2 .tres resources created
✓ Signal-based architecture established
✓ No functional changes
✓ All tests passing
```

---

## Supporting Files

This skill uses modular reference files:

- **anti-patterns-detection.md**: All grep/find patterns for detection
- **refactoring-operations.md**: Detailed step-by-step procedures
- **godot-best-practices.md**: Clean patterns reference
- **tscn-generation-guide.md**: .tscn file format templates
- **verification-checklist.md**: Testing procedures

Read these files for detailed implementation guidance.

---

## Red Flags - STOP

These thoughts mean you're rationalizing away discipline:

| Rationalization | Reality | Fix |
|----------------|---------|-----|
| "While I'm here, let me add this feature" | Feature creep breaks Iron Law | Refactor only, no features |
| "This behavior is wrong, I'll fix it now" | Bug fixes are separate work | Note bug, refactor only |
| "I don't need to test this change" | Untested = broken | Always verify |
| "I'll commit after a few more changes" | Loses granularity | Commit per operation |
| "This .tscn format looks close enough" | Invalid scenes crash | Use exact format |
| "The user won't notice this visual change" | Iron Law has no exceptions | Revert and fix |
| "Signals are overkill for this" | Coupling creeps back | Use signals anyway |
| "I'll manually test later" | Later never comes | Test now |
| "This script is fine at 160 lines" | Arbitrary exceptions grow | Split at 150 |
| "I understand the pattern, no need to read" | Assumptions create bugs | Read the guide |

---

## Quick Reference: Anti-Pattern → Clean Pattern

| Anti-Pattern | Clean Pattern | Tool |
|-------------|---------------|------|
| `Timer.new()` in code | .tscn scene with Timer | Operation A |
| `get_node("../Player")` | Signal via Events | Operation C |
| `if has_method("take_damage"):` | Signal listener | Operation C |
| 287-line script | Split to 3 focused scripts | Operation B |
| `const WEAPONS = [...]` | .tres resources | Operation D |
| `add_child(sprite)` | Scene composition | Operation A |
| Direct method calls | Signal emit/connect | Operation C |
| Deep inheritance | Component composition | Operations A+B |

---

## File Operation Flow

```
1. Data Extraction
   .gd with const → Resource class .gd + .tres files

2. Scene Extraction
   .gd with .new() → .gd with @onready + new .tscn

3. Signal Decoupling
   .gd with get_node() → events.gd + updated .gd files

4. Script Splitting
   Large .gd → Multiple focused .gd files with signals
```

---

## Godot Naming Conventions

**Scenes (.tscn):**
- PascalCase for node names: `DamageTimer`, `AbilitySystem`
- snake_case for file names: `damage_timer.tscn`, `ability_system.tscn`

**Scripts (.gd):**
- snake_case for files: `player_movement.gd`, `enemy_spawner.gd`
- PascalCase for class_name: `class_name PlayerMovement`

**Resources (.tres):**
- snake_case for files: `enemy_types/basic.tres`
- PascalCase for Resource class: `class_name EnemyTypeData`

**Signals:**
- snake_case: `signal ability_used`, `signal player_entered_safe_zone`
- Past tense for events: `signal enemy_spawned` (not `enemy_spawn`)

**@onready variables:**
- snake_case with type hint: `@onready var _damage_timer: Timer = $DamageTimer`
- Private with underscore: `_damage_timer`, `_ability_system`

---

## Common Mistakes

| Mistake | Consequence | Fix |
|---------|-------------|-----|
| Invalid .tscn format | Scene won't load in Godot | Use exact template format |
| Missing node type in .tscn | Godot can't parse scene | Always specify `type="Timer"` |
| Forgetting @onready | Null reference at runtime | Add @onready for all node refs |
| Wrong signal signature | Connection fails silently | Match parameter types exactly |
| Removing necessary .new() | Some objects SHOULD be created | Only refactor scene nodes |
| Not testing after each op | Compounding errors | Test after every commit |
| Coupling through globals | Different coupling, same problem | Use Events for decoupling only |
| Over-splitting scripts | Too many tiny files | 80-120 lines is optimal |
| Async signals without checks | Race conditions | Verify node existence |
| Changing behavior "slightly" | Iron Law violation | Revert immediately |

---

## Signal Architecture Patterns

**Event Bus (Events.gd):**
```gdscript
# Use for global events
signal player_died
signal level_completed(level_num: int)
signal score_changed(new_score: int)
```

**Direct Node Signals:**
```gdscript
# Use for parent-child communication
signal health_depleted
signal ability_activated(ability_name: String)
```

**When to use which:**
- Events.gd: Cross-tree communication, global state changes
- Node signals: Parent-child, local behavior

---

## Real-World Impact

Expected improvements after refactoring:

**Code Quality:**
- 30-50% reduction in total lines of code
- Scripts average 80-120 lines (down from 150-300)
- Zero direct node dependencies
- Signal-based architecture throughout

**Maintainability:**
- Changes isolated to single files
- Components reusable across scenes
- Testing individual components possible
- New developers onboard faster

**Performance:**
- Identical to baseline (±2 FPS)
- Scene loading slightly faster
- Memory usage unchanged

---

## Execution Strategy

This skill runs **fully automatically**:

1. User invokes skill on Godot project
2. Phase 1: Scan and report findings
3. User approves refactoring
4. Phases 2-3: Execute all operations with commits on current branch
5. Phase 4: Verify and report results

**User input required:**
- Initial invocation
- Approval after Phase 1 analysis
- Final verification check (30 seconds)

**Everything else is automatic:**
- Anti-pattern detection
- .tscn file generation
- Script modifications
- Git commits on current branch
- Testing

---

## Success Criteria

Refactoring is complete when:

- ✓ Zero `.new()` calls for scene nodes
- ✓ All scripts <150 lines
- ✓ Signal-based architecture established
- ✓ No `get_node()` for behavior access
- ✓ Data in .tres resources
- ✓ Clean git history with descriptive commits on current branch
- ✓ All scenes load without errors
- ✓ Behavior identical to baseline
- ✓ Visual appearance unchanged
- ✓ Performance within ±2 FPS

---

## Post-Refactoring

After successful refactoring:

1. **Continue development**
   - Changes are already on current branch
   - Push to remote if not already pushed
   - Continue normal development workflow

2. **Document architecture**
   - Create architecture diagram
   - Document signal flows
   - List component responsibilities

3. **Establish standards**
   - Use this clean architecture as template
   - Apply patterns to new code
   - Prevent anti-pattern regression

4. **Consider further improvements** (separate tasks):
   - Add unit tests (use TDD skill)
   - Optimize performance (profile first)
   - Add new features (use brainstorming skill)

---

**Remember**: Refactoring changes HOW code works internally, not WHAT it does externally. The Iron Law is absolute.

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.