diff --git a/devTools/sugarcube.d.ts b/devTools/sugarcube.d.ts
index e24730b925d5e1512cd86b7d6cba86169c7ed0c5..644ea40581dde3220c8516d4e4653c353bdfd9a8 100644
--- a/devTools/sugarcube.d.ts
+++ b/devTools/sugarcube.d.ts
@@ -1310,6 +1310,7 @@ declare namespace SugarCubeLib {
 	declare interface ISugarCube {
 		Config: Config;
 		Macro: Macro;
+		Save: Save;
 		State: State;
 		Story: Story;
 		/**
diff --git a/src/002-config/fc-js-init.js b/src/002-config/fc-js-init.js
index ec07dba98be3edcd26bfbcce88e9f63aeb14728a..3966b6a6838ea330e47c7d820179af8e68340f75 100644
--- a/src/002-config/fc-js-init.js
+++ b/src/002-config/fc-js-init.js
@@ -5,6 +5,7 @@
 */
 window.App = { };
 // the same declaration for code parsers that don't line the line above
-var App = App || {};
+var App = window.App || {};
 
+App.Debug = {};
 App.Entity = {};
diff --git a/src/debugging/debugJS.js b/src/debugging/debugJS.js
index 7f1a9650c8aa8a80997420bc6d522bd6068ad8c4..aac1d50c7840374336d1ff0d68e186e69f7a0fb9 100644
--- a/src/debugging/debugJS.js
+++ b/src/debugging/debugJS.js
@@ -80,3 +80,34 @@ window.findNaN = function findNan() {
 	}
 	return result;
 };
+
+/**
+ * Dumps game save as a readable JSON to the browser for saving in a file
+ */
+App.Debug.dumpGameState = function () {
+	// helper to download a blob
+	// borrowed from stackexchange
+	function downloadToFile(content, fileName, contentType) {
+		var a = document.createElement("a");
+		var file = new Blob([content], {
+			type: contentType
+		});
+		a.href = URL.createObjectURL(file);
+		a.download = fileName;
+		a.click();
+	}
+
+	// we will replace SugarCube onSave handler
+	let oldHandler = SugarCube.Config.saves.onSave;
+	try {
+		SugarCube.Config.saves.onSave = function (save) {
+			if (oldHandler) {
+				oldHandler(save);
+			}
+			downloadToFile(JSON.stringify(save, null, 2), save.id + ".js", "text/plain");
+		}
+		SugarCube.Save.serialize();
+	} finally {
+		SugarCube.Config.saves.onSave = oldHandler;
+	}
+};
diff --git a/src/uncategorized/storyCaption.tw b/src/uncategorized/storyCaption.tw
index a0256f5a148ce5b902d9d2d246d73eee871f44f0..43d4d16200676b72d85ad0af646549856079cee6 100644
--- a/src/uncategorized/storyCaption.tw
+++ b/src/uncategorized/storyCaption.tw
@@ -830,6 +830,8 @@
 		<</if>>
 		<<goto _Pass>>
 	<</link>>
+	<br>
+	<<link "Dump Game State">><<run App.Debug.dumpGameState()>><</link>>
 <</if>>
 
 <</nobr>>