diff --git a/cmd.c b/cmd.c
index 8f69ed92..02d2ac41 100644
--- a/cmd.c
+++ b/cmd.c
@@ -636,7 +636,7 @@ cmd_list_free(struct cmd_list *cmdlist)
 
 /* Copy a command list, expanding %s in arguments. */
 struct cmd_list *
-cmd_list_copy(struct cmd_list *cmdlist, int argc, char **argv)
+cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv)
 {
 	struct cmd	*cmd;
 	struct cmd_list	*new_cmdlist;
@@ -667,7 +667,7 @@ cmd_list_copy(struct cmd_list *cmdlist, int argc, char **argv)
 
 /* Get a command list as a string. */
 char *
-cmd_list_print(struct cmd_list *cmdlist, int escaped)
+cmd_list_print(const struct cmd_list *cmdlist, int escaped)
 {
 	struct cmd	*cmd, *next;
 	char		*buf, *this;
diff --git a/format.c b/format.c
index 3757180b..42f80f6f 100644
--- a/format.c
+++ b/format.c
@@ -5432,9 +5432,14 @@ format_grid_hyperlink(struct grid *gd, u_int x, u_int y, struct screen* s)
 	const char		*uri;
 	struct grid_cell	 gc;
 
-	grid_get_cell(gd, x, y, &gc);
-	if (gc.flags & GRID_FLAG_PADDING)
-		return (NULL);
+	for (;;) {
+		grid_get_cell(gd, x, y, &gc);
+		if (~gc.flags & GRID_FLAG_PADDING)
+			break;
+		if (x == 0)
+			return (NULL);
+		x--;
+	}
 	if (s->hyperlinks == NULL || gc.link == 0)
 		return (NULL);
 	if (!hyperlinks_get(s->hyperlinks, gc.link, &uri, NULL, NULL))
diff --git a/options-table.c b/options-table.c
index a461b3ea..3d1b4f85 100644
--- a/options-table.c
+++ b/options-table.c
@@ -285,6 +285,13 @@ const struct options_table_entry options_table[] = {
 	  .text = "Style of the cursor."
 	},
 
+	{ .name = "default-client-command",
+	  .type = OPTIONS_TABLE_COMMAND,
+	  .scope = OPTIONS_TABLE_SERVER,
+	  .default_str = "new-session",
+	  .text = "Default command to run when tmux is run without a command."
+	},
+
 	{ .name = "default-terminal",
 	  .type = OPTIONS_TABLE_STRING,
 	  .scope = OPTIONS_TABLE_SERVER,
diff --git a/options.c b/options.c
index 5541a376..f39fbf2a 100644
--- a/options.c
+++ b/options.c
@@ -260,6 +260,7 @@ options_default(struct options *oo, const struct options_table_entry *oe)
 	struct options_entry	*o;
 	union options_value	*ov;
 	u_int			 i;
+	struct cmd_parse_result	*pr;
 
 	o = options_empty(oo, oe);
 	ov = &o->value;
@@ -278,6 +279,17 @@ options_default(struct options *oo, const struct options_table_entry *oe)
 	case OPTIONS_TABLE_STRING:
 		ov->string = xstrdup(oe->default_str);
 		break;
+	case OPTIONS_TABLE_COMMAND:
+		pr = cmd_parse_from_string(oe->default_str, NULL);
+		switch (pr->status) {
+		case CMD_PARSE_ERROR:
+			free(pr->error);
+			break;
+		case CMD_PARSE_SUCCESS:
+			ov->cmdlist = pr->cmdlist;
+			break;
+		}
+		break;
 	default:
 		ov->number = oe->default_num;
 		break;
@@ -737,6 +749,19 @@ options_get_number(struct options *oo, const char *name)
 	return (o->value.number);
 }
 
+const struct cmd_list *
+options_get_command(struct options *oo, const char *name)
+{
+	struct options_entry	*o;
+
+	o = options_get(oo, name);
+	if (o == NULL)
+		fatalx("missing option %s", name);
+	if (!OPTIONS_IS_COMMAND(o))
+		fatalx("option %s is not a command", name);
+	return (o->value.cmdlist);
+}
+
 struct options_entry *
 options_set_string(struct options *oo, const char *name, int append,
     const char *fmt, ...)
@@ -798,6 +823,30 @@ options_set_number(struct options *oo, const char *name, long long value)
 	return (o);
 }
 
+struct options_entry *
+options_set_command(struct options *oo, const char *name,
+    struct cmd_list *value)
+{
+	struct options_entry	*o;
+
+	if (*name == '@')
+		fatalx("user option %s must be a string", name);
+
+	o = options_get_only(oo, name);
+	if (o == NULL) {
+		o = options_default(oo, options_parent_table_entry(oo, name));
+		if (o == NULL)
+			return (NULL);
+	}
+
+	if (!OPTIONS_IS_COMMAND(o))
+		fatalx("option %s is not a command", name);
+	if (o->value.cmdlist != NULL)
+		cmd_list_free(o->value.cmdlist);
+	o->value.cmdlist = value;
+	return (o);
+}
+
 int
 options_scope_from_name(struct args *args, int window,
     const char *name, struct cmd_find_state *fs, struct options **oo,
@@ -1054,6 +1103,7 @@ options_from_string(struct options *oo, const struct options_table_entry *oe,
 	const char		*errstr, *new;
 	char			*old;
 	key_code		 key;
+	struct cmd_parse_result	*pr;
 
 	if (oe != NULL) {
 		if (value == NULL &&
@@ -1112,6 +1162,15 @@ options_from_string(struct options *oo, const struct options_table_entry *oe,
 	case OPTIONS_TABLE_CHOICE:
 		return (options_from_string_choice(oe, oo, name, value, cause));
 	case OPTIONS_TABLE_COMMAND:
+		pr = cmd_parse_from_string(value, NULL);
+		switch (pr->status) {
+		case CMD_PARSE_ERROR:
+			*cause = pr->error;
+			return (-1);
+		case CMD_PARSE_SUCCESS:
+			options_set_command(oo, name, pr->cmdlist);
+			return (0);
+		}
 		break;
 	}
 	return (-1);
diff --git a/server-client.c b/server-client.c
index 30cf5280..ae2e54f9 100644
--- a/server-client.c
+++ b/server-client.c
@@ -3448,6 +3448,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
 	struct cmd_parse_result	 *pr;
 	struct args_value	 *values;
 	struct cmdq_item	 *new_item;
+	struct cmd_list		 *cmdlist;
 
 	if (c->flags & CLIENT_EXIT)
 		return;
@@ -3468,33 +3469,33 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
 	}
 
 	if (argc == 0) {
-		argc = 1;
-		argv = xcalloc(1, sizeof *argv);
-		*argv = xstrdup("new-session");
+		cmdlist = cmd_list_copy(options_get_command(global_options,
+		    "default-client-command"), 0, NULL);
+	} else {
+		values = args_from_vector(argc, argv);
+		pr = cmd_parse_from_arguments(values, argc, NULL);
+		switch (pr->status) {
+		case CMD_PARSE_ERROR:
+			cause = pr->error;
+			goto error;
+		case CMD_PARSE_SUCCESS:
+			break;
+		}
+		args_free_values(values, argc);
+		free(values);
+		cmd_free_argv(argc, argv);
+		cmdlist = pr->cmdlist;
 	}
 
-	values = args_from_vector(argc, argv);
-	pr = cmd_parse_from_arguments(values, argc, NULL);
-	switch (pr->status) {
-	case CMD_PARSE_ERROR:
-		cause = pr->error;
-		goto error;
-	case CMD_PARSE_SUCCESS:
-		break;
-	}
-	args_free_values(values, argc);
-	free(values);
-	cmd_free_argv(argc, argv);
-
 	if ((c->flags & CLIENT_READONLY) &&
-	    !cmd_list_all_have(pr->cmdlist, CMD_READONLY))
+	    !cmd_list_all_have(cmdlist, CMD_READONLY))
 		new_item = cmdq_get_callback(server_client_read_only, NULL);
 	else
-		new_item = cmdq_get_command(pr->cmdlist, NULL);
+		new_item = cmdq_get_command(cmdlist, NULL);
 	cmdq_append(c, new_item);
 	cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
 
-	cmd_list_free(pr->cmdlist);
+	cmd_list_free(cmdlist);
 	return;
 
 error:
diff --git a/tmux.1 b/tmux.1
index 7a2aad7a..ac9797b5 100644
--- a/tmux.1
+++ b/tmux.1
@@ -254,9 +254,10 @@ was given) and off.
 This specifies one of a set of commands used to control
 .Nm ,
 as described in the following sections.
-If no commands are specified, the
-.Ic new-session
-command is assumed.
+If no commands are specified, the command in
+.Ic default-client-command
+is assumed, which defaults to
+.Ic new-session .
 .El
 .Sh DEFAULT KEY BINDINGS
 .Nm
@@ -4085,6 +4086,10 @@ where the number is a hexadecimal number.
 Give the command to pipe to if the
 .Ic copy-pipe
 copy mode command is used without arguments.
+.It Ic default-client-command Ar command
+Set the default command to run when tmux is called without a command.
+The default is
+.Ic new-session .
 .It Ic default-terminal Ar terminal
 Set the default terminal for new windows created in this session - the
 default value of the
diff --git a/tmux.h b/tmux.h
index bde95365..0753cb27 100644
--- a/tmux.h
+++ b/tmux.h
@@ -2393,10 +2393,13 @@ struct options_entry *options_match_get(struct options *, const char *, int *,
 		     int, int *);
 const char	*options_get_string(struct options *, const char *);
 long long	 options_get_number(struct options *, const char *);
+const struct cmd_list *options_get_command(struct options *, const char *);
 struct options_entry * printflike(4, 5) options_set_string(struct options *,
 		     const char *, int, const char *, ...);
 struct options_entry *options_set_number(struct options *, const char *,
 		     long long);
+struct options_entry *options_set_command(struct options *, const char *,
+		     struct cmd_list *);
 int		 options_scope_from_name(struct args *, int,
 		     const char *, struct cmd_find_state *, struct options **,
 		     char **);
@@ -2680,12 +2683,12 @@ struct cmd	*cmd_copy(struct cmd *, int, char **);
 void		 cmd_free(struct cmd *);
 char		*cmd_print(struct cmd *);
 struct cmd_list	*cmd_list_new(void);
-struct cmd_list	*cmd_list_copy(struct cmd_list *, int, char **);
+struct cmd_list	*cmd_list_copy(const struct cmd_list *, int, char **);
 void		 cmd_list_append(struct cmd_list *, struct cmd *);
 void		 cmd_list_append_all(struct cmd_list *, struct cmd_list *);
 void		 cmd_list_move(struct cmd_list *, struct cmd_list *);
 void		 cmd_list_free(struct cmd_list *);
-char		*cmd_list_print(struct cmd_list *, int);
+char		*cmd_list_print(const struct cmd_list *, int);
 struct cmd	*cmd_list_first(struct cmd_list *);
 struct cmd	*cmd_list_next(struct cmd *);
 int		 cmd_list_all_have(struct cmd_list *, int);
diff --git a/window-tree.c b/window-tree.c
index 6b14bb63..7e84189a 100644
--- a/window-tree.c
+++ b/window-tree.c
@@ -302,6 +302,7 @@ window_tree_build_pane(struct session *s, struct winlink *wl,
 	struct window_tree_itemdata	*item;
 	char				*name, *text;
 	u_int				 idx;
+	struct format_tree		*ft;
 
 	window_pane_index(wp, &idx);
 
@@ -311,8 +312,11 @@ window_tree_build_pane(struct session *s, struct winlink *wl,
 	item->winlink = wl->idx;
 	item->pane = wp->id;
 
-	text = format_single(NULL, data->format, NULL, s, wl, wp);
+	ft = format_create(NULL, NULL, FORMAT_PANE|wp->id, 0);
+	format_defaults(ft, NULL, s, wl, wp);
+	text = format_expand(ft, data->format);
 	xasprintf(&name, "%u", idx);
+	format_free(ft);
 
 	mode_tree_add(data->data, parent, item, (uint64_t)wp, name, text, -1);
 	free(text);
@@ -348,6 +352,7 @@ window_tree_build_window(struct session *s, struct winlink *wl,
 	struct window_pane		*wp, **l;
 	u_int				 n, i;
 	int				 expanded;
+	struct format_tree		*ft;
 
 	item = window_tree_add_item(data);
 	item->type = WINDOW_TREE_WINDOW;
@@ -355,8 +360,11 @@ window_tree_build_window(struct session *s, struct winlink *wl,
 	item->winlink = wl->idx;
 	item->pane = -1;
 
-	text = format_single(NULL, data->format, NULL, s, wl, NULL);
+	ft = format_create(NULL, NULL, FORMAT_PANE|wl->window->active->id, 0);
+	format_defaults(ft, NULL, s, wl, NULL);
+	text = format_expand(ft, data->format);
 	xasprintf(&name, "%u", wl->idx);
+	format_free(ft);
 
 	if (data->type == WINDOW_TREE_SESSION ||
 	    data->type == WINDOW_TREE_WINDOW)
@@ -373,7 +381,6 @@ window_tree_build_window(struct session *s, struct winlink *wl,
 	if (TAILQ_NEXT(wp, entry) == NULL) {
 		if (!window_tree_filter_pane(s, wl, wp, filter))
 			goto empty;
-		return (1);
 	}
 
 	l = NULL;
@@ -411,9 +418,10 @@ window_tree_build_session(struct session *s, void *modedata,
 	struct window_tree_itemdata	*item;
 	struct mode_tree_item		*mti;
 	char				*text;
-	struct winlink			*wl, **l;
+	struct winlink			*wl = s->curw, **l;
 	u_int				 n, i, empty;
 	int				 expanded;
+	struct format_tree		*ft;
 
 	item = window_tree_add_item(data);
 	item->type = WINDOW_TREE_SESSION;
@@ -421,7 +429,10 @@ window_tree_build_session(struct session *s, void *modedata,
 	item->winlink = -1;
 	item->pane = -1;
 
-	text = format_single(NULL, data->format, NULL, s, NULL, NULL);
+	ft = format_create(NULL, NULL, FORMAT_PANE|wl->window->active->id, 0);
+	format_defaults(ft, NULL, s, NULL, NULL);
+	text = format_expand(ft, data->format);
+	format_free(ft);
 
 	if (data->type == WINDOW_TREE_SESSION)
 		expanded = 0;