Editing a Godot save file from outside the editor: what actually breaks A developer built Save Value Editor, a Godot tool that edits save and config files by recording the byte span of each changed literal and replacing only that span, leaving the rest of the file byte-identical. The tool avoids the data corruption of naive JSON round trips, which turn 1.0 into 1, -0.0 into 0, and lose integers above 2^53, and it preserves Object(InputEventKey,...) lines, BOMs and CRLF endings that INI re-serialisation strips. It ships as a CLI with distinct exit codes for agents and as an in-editor dock for Godot 4.4+, verified against files written by Godot 4.4.1 through 4.7.2. An agent Codex, Claude Code, a CI job can run a shell command, but it cannot click inside the Godot editor. So when the task is "put the game into this state" — progress/stage = 7 , tutorial done = true , audio/master = 0.42 — the agent ends up editing the save file directly. The editor itself can do the same thing through a dock; a terminal cannot. The naive way is json.load → change → json.dump . On a Godot project that quietly changes data you did not ask to change. Below is what actually moved in the files I measured, and what an edit has to preserve to be safe. JSON.parse string returns every JSON number as a float. A test file: {"level":3,"big int":9007199254740993,"float one":1.0,"exp":1e10,"neg zero":-0.0,"imprecise":0.30000000000000004,"tiny":1.0000000000000002e-300,"long i64":9223372036854775807} Any round trip through a float parser turns 1.0 into 1 , 1e10 into 10000000000 , -0.0 into 0 , and 9007199254740993 2^53+1 into a neighbour. 9223372036854775807 does not survive at all. A game that compares -0.0 , prints a value back, or hashes its own save will notice the difference. The safe rule: read numbers as source literals text , not as floats, and write back the literals you did not touch. ConfigFile.save writes sections and ; comments, but if the file is project.godot with an input map it also contains whole Object InputEventKey,... values. Measured: a 1040-byte project.godot with two input events. An INI library re-serialises the file without those Object ... lines, and the project no longer opens in the editor. A 73-byte ConfigFile with a UTF-8 BOM, CRLF line endings and a ; comment: od -c starts with 357 273 277 and every line ends \r\n . Parsers that normalise newlines or strips the BOM change lines you never selected. Keep them or the diff is a lie. var to bytes files and .res are not text. An agent should refuse them, not "repair" them. The tool I built opens the file with the engine's own parser to get labels and types, records the byte span of the literal being changed , and replaces exactly that span. Everything else is copied through untouched. Measured on the packaged build: 9007199254740993 → 1 , "Player One" → "ニュー 名前" , rest of the file byte-identical. project.godot with an input map: 1040 → 1038 bytes, both Object InputEventKey,... lines byte-identical afterwards, editor opened the project with no error. --restore --write : original SHA-256 back, exactly. Exit codes that separate the failure modes, so the agent can branch instead of guessing from prose: 0 wrote or dry run OK , 2 missing or unreadable binary file, 3 label missing, null leaf, or a type change, 4 file is read-only. --write then produces exactly those bytes. I checked that equality on Godot 4.4.1, 4.5.2, 4.6.3 and 4.7.2 with files that each engine wrote itself. .sve.bak only on a real write, and no second backup when re-running the same edit no change . --json output. Note: the engine banner is the first line of stdout, so read the --quiet is not a workaround because it takes the JSON with it. godot --headless --path