diff --git a/cmd-set-option.c b/cmd-set-option.c
index b35d60d8..ad058b8e 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -42,8 +42,8 @@ const struct cmd_entry cmd_set_option_entry = {
 	.name = "set-option",
 	.alias = "set",
 
-	.args = { "agoqst:uw", 1, 2 },
-	.usage = "[-agosquw] [-t target-window] option [value]",
+	.args = { "aFgoqst:uw", 1, 2 },
+	.usage = "[-aFgosquw] [-t target-window] option [value]",
 
 	.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
 
@@ -55,8 +55,8 @@ const struct cmd_entry cmd_set_window_option_entry = {
 	.name = "set-window-option",
 	.alias = "setw",
 
-	.args = { "agoqt:u", 1, 2 },
-	.usage = "[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
+	.args = { "aFgoqt:u", 1, 2 },
+	.usage = "[-aFgoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
 
 	.target = { 't', CMD_FIND_WINDOW, CMD_FIND_CANFAIL },
 
@@ -70,33 +70,38 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 	struct args			*args = self->args;
 	int				 append = args_has(args, 'a');
 	struct cmd_find_state		*fs = &item->target;
+	struct client			*c, *loop;
 	struct session			*s = fs->s;
 	struct winlink			*wl = fs->wl;
 	struct window			*w;
-	struct client			*c;
 	enum options_table_scope	 scope;
 	struct options			*oo;
 	struct options_entry		*parent, *o;
-	char				*name;
-	const char			*value, *target;
+	char				*name, *argument, *value = NULL, *cause;
+	const char			*target;
 	int				 window, idx, already, error, ambiguous;
-	char				*cause;
+
+	/* Expand argument. */
+	c = cmd_find_client(item, NULL, 1);
+	argument = format_single(item, args->argv[0], c, s, wl, NULL);
 
 	/* Parse option name and index. */
-	name = options_match(args->argv[0], &idx, &ambiguous);
+	name = options_match(argument, &idx, &ambiguous);
 	if (name == NULL) {
 		if (args_has(args, 'q'))
-			return (CMD_RETURN_NORMAL);
+			goto out;
 		if (ambiguous)
-			cmdq_error(item, "ambiguous option: %s", args->argv[0]);
+			cmdq_error(item, "ambiguous option: %s", argument);
 		else
-			cmdq_error(item, "invalid option: %s", args->argv[0]);
-		return (CMD_RETURN_ERROR);
+			cmdq_error(item, "invalid option: %s", argument);
+		goto fail;
 	}
 	if (args->argc < 2)
 		value = NULL;
+	else if (args_has(args, 'F'))
+		value = format_single(item, args->argv[1], c, s, wl, NULL);
 	else
-		value = args->argv[1];
+		value = xstrdup(args->argv[1]);
 
 	/*
 	 * Figure out the scope: for user options it comes from the arguments,
@@ -114,12 +119,12 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 			scope = OPTIONS_TABLE_WINDOW;
 		else {
 			scope = OPTIONS_TABLE_NONE;
-			xasprintf(&cause, "unknown option: %s", args->argv[0]);
+			xasprintf(&cause, "unknown option: %s", argument);
 		}
 	}
 	if (scope == OPTIONS_TABLE_NONE) {
 		if (args_has(args, 'q'))
-			return (CMD_RETURN_NORMAL);
+			goto out;
 		cmdq_error(item, "%s", cause);
 		free(cause);
 		goto fail;
@@ -159,7 +164,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 	/* Check that array options and indexes match up. */
 	if (idx != -1) {
 		if (*name == '@' || options_array_size(parent, NULL) == -1) {
-			cmdq_error(item, "not an array: %s", args->argv[0]);
+			cmdq_error(item, "not an array: %s", argument);
 			goto fail;
 		}
 	}
@@ -176,8 +181,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 		}
 		if (already) {
 			if (args_has(args, 'q'))
-				return (CMD_RETURN_NORMAL);
-			cmdq_error(item, "already set: %s", args->argv[0]);
+				goto out;
+			cmdq_error(item, "already set: %s", argument);
 			goto fail;
 		}
 	}
@@ -217,7 +222,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 				options_array_clear(o);
 			options_array_assign(o, value);
 		} else if (options_array_set(o, idx, value, append) != 0) {
-			cmdq_error(item, "invalid index: %s", args->argv[0]);
+			cmdq_error(item, "invalid index: %s", argument);
 			goto fail;
 		}
 	}
@@ -232,8 +237,8 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 		}
 	}
 	if (strcmp(name, "key-table") == 0) {
-		TAILQ_FOREACH(c, &clients, entry)
-			server_client_set_key_table(c, NULL);
+		TAILQ_FOREACH(loop, &clients, entry)
+			server_client_set_key_table(loop, NULL);
 	}
 	if (strcmp(name, "status") == 0 ||
 	    strcmp(name, "status-interval") == 0)
@@ -257,15 +262,20 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
 	 * anyway.
 	 */
 	recalculate_sizes();
-	TAILQ_FOREACH(c, &clients, entry) {
-		if (c->session != NULL)
-			server_redraw_client(c);
+	TAILQ_FOREACH(loop, &clients, entry) {
+		if (loop->session != NULL)
+			server_redraw_client(loop);
 	}
 
+out:
+	free(argument);
+	free(value);
 	free(name);
 	return (CMD_RETURN_NORMAL);
 
 fail:
+	free(argument);
+	free(value);
 	free(name);
 	return (CMD_RETURN_ERROR);
 }
diff --git a/cmd-show-options.c b/cmd-show-options.c
index 382dd7fb..2dc3dee3 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -127,25 +127,36 @@ cmd_show_options_one(struct cmd *self, struct cmdq_item *item,
     struct options *oo)
 {
 	struct args		*args = self->args;
+	struct client		*c = cmd_find_client(item, NULL, 1);
+	struct session		*s = item->target.s;
+	struct winlink		*wl = item->target.wl;
 	struct options_entry	*o;
 	int			 idx, ambiguous;
-	const char		*name = args->argv[0];
+	char			*name;
 
+	name = format_single(item, args->argv[0], c, s, wl, NULL);
 	o = options_match_get(oo, name, &idx, 1, &ambiguous);
 	if (o == NULL) {
-		if (args_has(args, 'q'))
+		if (args_has(args, 'q')) {
+			free(name);
 			return (CMD_RETURN_NORMAL);
+		}
 		if (ambiguous) {
 			cmdq_error(item, "ambiguous option: %s", name);
+			free(name);
 			return (CMD_RETURN_ERROR);
 		}
 		if (*name != '@' &&
-		    options_match_get(oo, name, &idx, 0, &ambiguous) != NULL)
+		    options_match_get(oo, name, &idx, 0, &ambiguous) != NULL) {
+			free(name);
 			return (CMD_RETURN_NORMAL);
+		}
 		cmdq_error(item, "unknown option: %s", name);
+		free(name);
 		return (CMD_RETURN_ERROR);
 	}
 	cmd_show_options_print(self, item, o, idx);
+	free(name);
 	return (CMD_RETURN_NORMAL);
 }
 
diff --git a/tmux.1 b/tmux.1
index 5284f5cc..05a19e2c 100644
--- a/tmux.1
+++ b/tmux.1
@@ -2335,7 +2335,7 @@ abc123
 Commands which set options are as follows:
 .Bl -tag -width Ds
 .It Xo Ic set-option
-.Op Fl agoqsuw
+.Op Fl aFgoqsuw
 .Op Fl t Ar target-session | Ar target-window
 .Ar option Ar value
 .Xc
@@ -2351,6 +2351,8 @@ otherwise a session option.
 If
 .Fl g
 is given, the global session or window option is set.
+.Fl F
+expands formats in the option value.
 The
 .Fl u
 flag unsets an option, so a session inherits the option from the global
@@ -2901,7 +2903,7 @@ The default is
 .Ql \ -_@ .
 .El
 .It Xo Ic set-window-option
-.Op Fl agoqu
+.Op Fl aFgoqu
 .Op Fl t Ar target-window
 .Ar option Ar value
 .Xc
@@ -2909,6 +2911,7 @@ The default is
 Set a window option.
 The
 .Fl a ,
+.Fl F ,
 .Fl g ,
 .Fl o ,
 .Fl q