Editor Extra Quality | Renpy Persistent

Even with the best tools, things go wrong. Here is how a quality editor helps you debug.

Problem: Game crashes on launch after editing. Solution: Your editor’s backup manager. Rename persistent.old to persistent and restart. You lose zero progress.

Problem: The editor shows ???? instead of keys. Solution: The game uses a custom encryption or compression. A low-quality tool fails here. An extra-quality tool will either (a) detect encryption and refuse to open (preventing corruption) or (b) ask for a decryption key.

Problem: Changes don’t appear in game. Solution: Your game might have a persistent file in your local install directory and in AppData. Use the editor’s "Search System Wide" function to find all copies.

Before wielding the editor, understand the target. Unlike standard save files (1-1-LT1.save), the persistent file lives in a different location (usually AppData/Roaming/RenPy/GameName/persistent on Windows or ~/Library/RenPy/ on Mac).

It stores:

Editing this file is a double-edged sword. Without a quality editor, you risk breaking the game’s flag system, causing crashes, or losing your original data.

A standalone executable built specifically for this task.

You can access this screen in two ways.

Option A: From the Main Menu Edit screens.rpy inside the screen main_menu:

# Add this button inside the main_menu vbox
textbutton "Mod Editor":
    action Show("persistent_editor_extra")
    style "navigation_button"

Option B: Keyboard Shortcut (Developer Friendly) Add this to your options.rpy or script.rpy: renpy persistent editor extra quality

init python:
    # Press 'P' to open editor anywhere
    config.underlay.append(renpy.Keymap(persistent_editor=Show("persistent_editor_extra")))
    config.keymap['persistent_editor'] = 'p'

A 500-key persistent dictionary is useless without Ctrl+F. Quality editors let you search by key name, value, or even partial strings (e.g., find all entries containing "chapter").

Let’s walk through a real-world scenario: You want to unlock a secret CG gallery that requires finishing three different routes.

Step 1: Locate Your Persistent File

Step 2: Open with Your Quality Editor Launch your chosen tool (e.g., UnRen). Click File > Open Persistent. Navigate to the folder and select the file (note: no file extension).

Step 3: Search for the Variable In the editor’s search bar, type gallery. The tool should highlight keys like: Even with the best tools, things go wrong

persistent.gallery_cg_01 = False
persistent.gallery_cg_02 = False
persistent.route_clear_akira = False

Step 4: Make Type-Safe Edits Click the boolean value False next to route_clear_akira. A dropdown appears. Select True. Do this for all three heroines.

Step 5: Validate Your Changes A quality editor includes a "Validate" button. Click it. The tool checks for orphans or type mismatches.

Step 6: Create Backup & Save The editor will ask: "Create backup 'persistent.old' before saving?" Say Yes. Then click Save.

Step 7: Load Your Game Launch your RenPy game. Navigate to the Extras or Gallery. The entire CG set should be unlocked, and the game will treat you as if you earned it legitimately.

Now we build the visual interface. We will use vpgrid to handle lists of variables and different input types. Editing this file is a double-edged sword

screen persistent_editor_extra():
    # Modal prevents clicking other game elements
    modal True
# Background frame
    frame:
        xsize 800
        ysize 600
        align (0.5, 0.5)
        padding (20, 20)
vbox:
            xfill True
            text "Persistent Data Manager" size 30 xalign 0.5
            null height 20
# Scrollable area for variables
            vpgrid:
                cols 1
                spacing 10
                xfill True
                ysize 450
                scrollbars "vertical"
# Iterate through our whitelisted variables
                for var_id in persistent_edit_whitelist:
$ current_val = get_persistent_value(var_id)
hbox:
                        xfill True
                        box_wrap True
# 1. Variable Name
                        text "[var_id]" min_width 200 size 18 yalign 0.5
# 2. Dynamic Input based on Value Type
                        if isinstance(current_val, bool):
                            # BOOLEAN: Use a toggle button for Quality
                            textbutton "Toggle ([current_val])":
                                action [SetField(persistent, var_id.replace("persistent.", ""), not current_val), 
                                        Function(renpy.save_persistent)]
                                sensitive True
elif isinstance(current_val, int) or isinstance(current_val, float):
                            # NUMBERS: Use a value bar (slider) or Input
                            # For extra quality, we use a slider plus a value display
                            $ temp_key = var_id + "_input"
bar:
                                value FieldValue(persistent, var_id.replace("persistent.", ""), 
                                                  range=1000, step=1, action=Function(renpy.save_persistent))
                                xsize 300
text " [current_val]" size 18 yalign 0.5
else:
                            # STRING / OTHER: Use an Input box
                            default input_val = VariableInputValue(var_id, default=current_val, returnable=False)
input:
                                value input_val
                                xsize 300
                                # On losing focus, save persistent
                                changed renpy.save_persistent
null height 10
            textbutton "Close Editor" action Hide("persistent_editor_extra") xalign 0.5

If you mod a game that updated from RenPy 7 to RenPy 8, the pickle protocol changed. An extra quality editor detects the protocol version (0-5) and adjusts the unpickling process automatically. You can do this by checking the first few bytes of the persistent file.