diff --git a/sway/commands.c b/sway/commands.c
index 3a86ae53..464c9932 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -112,6 +112,7 @@ static struct cmd_handler handlers[] = {
 	{ "mouse_warping", cmd_mouse_warping },
 	{ "output", cmd_output },
 	{ "seat", cmd_seat },
+	{ "set", cmd_set },
 	{ "show_marks", cmd_show_marks },
 	{ "workspace", cmd_workspace },
 	{ "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth },
@@ -120,7 +121,6 @@ static struct cmd_handler handlers[] = {
 /* Config-time only commands. Keep alphabetized */
 static struct cmd_handler config_handlers[] = {
 	{ "default_orientation", cmd_default_orientation },
-	{ "set", cmd_set },
 	{ "swaybg_command", cmd_swaybg_command },
 	{ "workspace_layout", cmd_workspace_layout },
 };
@@ -270,6 +270,13 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
 				goto cleanup;
 			}
 
+			// Var replacement, for all but first argument of set
+			for (int i = handler->handle == cmd_set ? 2 : 1; i < argc; ++i) {
+				argv[i] = do_var_replacement(argv[i]);
+				unescape_string(argv[i]);
+				strip_quotes(argv[i]);
+			}
+
 			if (!config->handler_context.using_criteria) {
 				// without criteria, the command acts upon the focused
 				// container
diff --git a/sway/config.c b/sway/config.c
index 445c3d55..f382eefa 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -657,6 +657,14 @@ char *do_var_replacement(char *str) {
 				continue;
 			}
 		}
+		// Unescape double $ and move on
+		if (find[1] == '$') {
+			size_t length = strlen(find + 1);
+			strncpy(find, find + 1, length);
+			find[length] = '\0';
+			find += 2;
+			continue;
+		}
 		// Find matching variable
 		for (i = 0; i < config->symbols->length; ++i) {
 			struct sway_variable *var = config->symbols->items[i];
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index f78ae9a5..3c42e259 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -128,12 +128,14 @@ char *workspace_next_name(const char *output_name) {
 		}
 
 		if (strcmp("workspace", cmd) == 0 && name) {
-			wlr_log(L_DEBUG, "Got valid workspace command for target: '%s'", name);
 			char *_target = strdup(name);
+			_target = do_var_replacement(_target);
 			strip_quotes(_target);
 			while (isspace(*_target)) {
 				memmove(_target, _target+1, strlen(_target+1));
 			}
+			wlr_log(L_DEBUG, "Got valid workspace command for target: '%s'",
+					_target);
 
 			// Make sure that the command references an actual workspace
 			// not a command about workspaces