diff --git a/src/002-config/mousetrapConfig.js b/src/002-config/mousetrapConfig.js
index 586c861857bc62827afcf84cf3c7983c00bc19aa..c905ac5be13f53be60f625abca0ea9cab222984f 100644
--- a/src/002-config/mousetrapConfig.js
+++ b/src/002-config/mousetrapConfig.js
@@ -16,12 +16,24 @@ App.UI.Hotkeys = (function() {
 	 */
 	const actions = {};
 
+	/**
+	 * Contains the default combinations for every action
+	 * @type {object.<string, Array<string>>}
+	 */
+	const defaultCombinations = {};
+
 	/**
 	 * References a key combination to a set of actions
 	 * @type {object.<string, Array<string>>}
 	 */
 	const bindings = {};
 
+	/**
+	 * To ensure we only record one at at time
+	 * @type {boolean}
+	 */
+	let recording = false;
+
 	/**
 	 * @param {string} name used as key
 	 * @param {action} action
@@ -31,18 +43,20 @@ App.UI.Hotkeys = (function() {
 		for (const binding of action.combinations) {
 			addBinding(name, binding);
 		}
+		defaultCombinations[name] = [...action.combinations];
 	}
 
 	/**
-	 * @param {string} action
+	 * @param {string} actionKey
 	 * @param {string} combination
 	 */
-	function addBinding(action, combination) {
+	function addBinding(actionKey, combination) {
 		if (bindings[combination]) {
-			bindings[combination].push(action);
+			bindings[combination].push(actionKey);
 		} else {
-			bindings[combination] = [action];
-			Mousetrap.bind(combination, () => {
+			bindings[combination] = [actionKey];
+			Mousetrap.bind(combination, e => {
+				e.preventDefault();
 				for (const binding of bindings[combination]) {
 					const action = actions[binding];
 					// only activate callback if we are on the right passage
@@ -55,17 +69,18 @@ App.UI.Hotkeys = (function() {
 	}
 
 	/**
+	 * @param {string} actionKey
 	 * @param {string} combination
 	 */
-	function removeBinding(combination) {
+	function removeBinding(actionKey, combination) {
 		if (bindings[combination]) {
-			const index = bindings[combination].indexOf(category);
+			const index = bindings[combination].indexOf(actionKey);
 			if (index > -1) {
 				bindings[combination].splice(index, 1);
-			}
-			if (bindings[combination].length === 0) {
-				delete bindings[combination];
-				Mousetrap.unbind(combination);
+				if (bindings[combination].length === 0) {
+					delete bindings[combination];
+					Mousetrap.unbind(combination);
+				}
 			}
 		}
 	}
@@ -78,7 +93,7 @@ App.UI.Hotkeys = (function() {
 		if (!actions[name]) {
 			return "";
 		}
-		const c =actions[name].combinations
+		const c = actions[name].combinations;
 		if (c.length === 0) {
 			return "";
 		}
@@ -89,11 +104,105 @@ App.UI.Hotkeys = (function() {
 		return `[${c[0]},${c[1]}]`;
 	}
 
+	/**
+	 * @returns {HTMLDivElement}
+	 */
+	function settingsMenu() {
+		const div = document.createElement("div");
+		div.className = "hotkey-settings";
+
+		for (const actionsKey in actions) {
+			settingsRow(div, actionsKey);
+		}
+
+		return div;
+	}
+
+	/**
+	 * @param {HTMLDivElement} container
+	 * @param {string} actionKey
+	 */
+	function settingsRow(container, actionKey) {
+		const action = actions[actionKey];
+		// get correct name
+		let name = actionKey;
+		if (action.uiName) {
+			if (typeof action.uiName === "string") {
+				name = action.uiName;
+			} else {
+				name = action.uiName();
+			}
+		}
+		App.UI.DOM.appendNewElement("div", container, name, "description");
+
+		settingsCell(container, actionKey, 0);
+		settingsCell(container, actionKey, 1);
+
+		const button = App.UI.DOM.appendNewElement("button", container, "Reset");
+		if (isDefault(actionKey)) {
+			button.className = "inactive";
+		} else {
+			button.onclick = () => {
+				action.combinations = [...defaultCombinations[name]];
+				App.UI.reload();
+			};
+		}
+	}
+
+	/**
+	 * Checks if the combinations assigned to an action are the default ones.
+	 * @param {string} actionKey
+	 * @returns {boolean}
+	 */
+	function isDefault(actionKey) {
+		if (defaultCombinations[actionKey].length !== actions[actionKey].combinations.length) {
+			return false;
+		}
+		if (defaultCombinations[actionKey].length === 0) {
+			return true;
+		}
+		if (defaultCombinations[actionKey][0] !== actions[actionKey].combinations[0]) {
+			return false;
+		}
+		if (defaultCombinations[actionKey].length === 1) {
+			return true;
+		}
+		return defaultCombinations[actionKey][1] === actions[actionKey].combinations[1];
+	}
+
+	/**
+	 * @param {HTMLDivElement} container
+	 * @param {string} actionKey
+	 * @param {number} index
+	 */
+	function settingsCell(container, actionKey, index) {
+		const action = actions[actionKey];
+		const button = App.UI.DOM.appendNewElement("button", container,
+			action.combinations[index] ? action.combinations[index] : "", "combination");
+		button.onclick = () => {
+			if (recording) { return; }
+			recording = true;
+
+			$(button).empty();
+			Mousetrap.record(function(sequence) {
+				// sequence is an array like ['ctrl+k', 'c']
+				const combination = sequence.join(" ");
+				if (action.combinations[index]) {
+					removeBinding(actionKey, action.combinations[index]);
+				}
+				action.combinations[index] = combination;
+				addBinding(actionKey, combination);
+				App.UI.reload();
+				recording = false;
+			});
+		};
+	}
+
 	return {
 		add: addDefault,
 		hotkeys: hotkeysForAction,
 		//init: loadFromStorage,
-		//settings: settingsMenu,
+		settings: settingsMenu,
 	};
 })();
 
diff --git a/src/gui/options/hotkeySettings.css b/src/gui/options/hotkeySettings.css
new file mode 100644
index 0000000000000000000000000000000000000000..eb695486a2583e89c2bdb81cd3013c5b18f605e5
--- /dev/null
+++ b/src/gui/options/hotkeySettings.css
@@ -0,0 +1,35 @@
+div.hotkey-settings {
+    display: grid;
+    grid-template-columns: max-content max-content max-content max-content;
+}
+
+div.hotkey-settings div.description {
+    margin-right: 10px;
+    /* center text vertically */
+    display: flex;
+    justify-content: center;
+    flex-direction: column;
+}
+
+div.hotkey-settings button {
+    margin: 5px;
+    border-width: 2px;
+    background-color: var(--button-color);
+    border-color: var(--button-border-color);
+}
+
+div.hotkey-settings button.combination {
+    min-width: 150px;
+    border-width: 0;
+}
+
+div.hotkey-settings button.inactive, div.hotkey-settings button.inactive:hover {
+    background-color: var(--button-selected-color);
+    cursor: default;
+
+}
+
+div.hotkey-settings button:hover {
+    background-color: var(--button-hover-color);
+    border-color: var(--button-border-color);
+}
diff --git a/src/gui/options/hotkeySettings.tw b/src/gui/options/hotkeySettings.tw
new file mode 100644
index 0000000000000000000000000000000000000000..c415b29b410c9e0c74f2f76e78e3f62ed1452606
--- /dev/null
+++ b/src/gui/options/hotkeySettings.tw
@@ -0,0 +1,27 @@
+:: Hotkey Settings [nobr jump-to-safe jump-from-safe]
+
+<<set $nextButton = "Back", $nextLink = "Main">>
+
+<h1>Hotkey Settings</h1>
+
+<p>
+    <ul>
+        <li>
+            On keyboards layouts other than the <a href="https://en.wikipedia.org/wiki/File:KB_United_States.svg"
+            target="_blank">US-QWERTY layout</a>  there may be keys or combinations of keys where the recorded key is
+            different from the key used to listen to key events. You will have to find these keys yourself through trial
+            and error.
+        </li>
+        <li>
+            Custom hotkeys are browser specific and are not part of your save.
+        </li>
+        <li>
+            While we try to not overwrite browser or OS level key combinations it is possible to do so with custom
+            hotkeys. This also means that during recording of custom hotkeys no browser or OS level key combinations are
+            available. There are however keys that cannot be overwritten, the <code>Win key</code> on Windows is an
+            example for this.
+        </li>
+    </ul>
+</p>
+
+<<includeDOM App.UI.Hotkeys.settings()>>
diff --git a/src/gui/quicklinks.js b/src/gui/quicklinks.js
index 249817e1f507c3676d0e33afc22a6f8ab6175432..1b17599fdca0746d823e01a429549f49ba150efd 100644
--- a/src/gui/quicklinks.js
+++ b/src/gui/quicklinks.js
@@ -77,6 +77,7 @@ App.UI.quickMenu = (function() {
 			"Summary Options": true,
 			"Description Options": true,
 			"Universal Rules": true,
+			"Hotkey Settings": true,
 		}
 	});
 
@@ -241,6 +242,8 @@ App.UI.quickMenu = (function() {
 				const action = {
 					callback: () => {
 						if (hotkeysEnabled
+							// we are not already on the passage
+							&& State.passage !== passage
 							// the passage is accessible
 							&& !(hiddenPassages[passage] && hiddenPassages[passage]())) {
 							Engine.play(passage);