diff --git a/Makefile.am b/Makefile.am
index fb707df..3bdbfd3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -103,6 +103,7 @@ dist_tmux_SOURCES = \
 	cmd-list.c \
 	cmd-load-buffer.c \
 	cmd-lock-server.c \
+	cmd-log-pane.c \
 	cmd-move-window.c \
 	cmd-new-session.c \
 	cmd-new-window.c \
diff --git a/cmd-log-pane.c b/cmd-log-pane.c
new file mode 100644
index 0000000..10eabe1
--- /dev/null
+++ b/cmd-log-pane.c
@@ -0,0 +1,190 @@
+/* $Id$ */
+
+/*
+ * Copyright (c) 2013 Nicholas Marriott <nicm@users.sourceforge.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "tmux.h"
+
+/*
+ * Open a logfile for pane output logging
+ */
+
+enum cmd_retval	 cmd_log_pane_exec(struct cmd *, struct cmd_q *);
+char		*cmd_log_pane_parse_filename(struct session *, struct winlink *, struct window_pane *, const char *);
+void		 cmd_log_pane_open_file(struct session *, struct winlink *, struct window_pane *);
+
+const struct cmd_entry cmd_log_pane_entry = {
+	"log-pane", "logp",
+	"beot:f:", 0, 1,
+	"[-b|e|o] " CMD_TARGET_PANE_USAGE " [-f filename]",
+	0,
+	NULL,
+	NULL,
+	cmd_log_pane_exec
+};
+
+enum cmd_retval
+cmd_log_pane_exec(struct cmd *self, struct cmd_q *cmdq)
+{
+	struct args		*args = self->args;
+	struct winlink		*wl;
+	struct session		*s;
+	struct window_pane	*wp;
+	const char		*farg;
+	char 			*filename;
+	int			 opt_b, opt_e, opt_f, opt_o;
+
+	
+	if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
+		return (CMD_RETURN_ERROR);
+
+
+	opt_b = opt_e = opt_f = opt_o = 0;
+	if (args_has(self->args, 'b'))
+		opt_b = 1;
+	if (args_has(self->args, 'e'))
+		opt_e = 1;
+	if (args_has(self->args, 'f'))
+		opt_f = 1;
+	if (args_has(self->args, 'o'))
+		opt_o = 1;
+
+	if ((opt_b && opt_e) || (opt_b && opt_o) || (opt_e && opt_o)) {
+		cmdq_error(cmdq, "usage error: specify only 1 of -b, -e, or -o");
+		return (CMD_RETURN_ERROR);
+	}
+
+	if (!opt_b && !opt_e && !opt_f && !opt_o) {
+		cmdq_error(cmdq, "usage error: specify at least 1 of -b, -e, -o, or -f");
+		return (CMD_RETURN_ERROR);
+	}
+
+
+	if (opt_f) {
+		farg = args_get(self->args, 'f');
+		filename = cmd_log_pane_parse_filename(s, wl, wp, farg);
+
+		if (filename == NULL) {
+			cmdq_error(cmdq, "bad filename");
+			return (CMD_RETURN_ERROR);
+		}
+
+		if (wp->logpane_filename != NULL)
+			free(wp->logpane_filename);
+
+		wp->logpane_filename = filename;
+		
+	}
+
+	if (opt_e) {
+		if (wp->logpane_fd != -1) {
+			close(wp->logpane_fd);
+			wp->logpane_fd = -1;
+		}
+		return (CMD_RETURN_NORMAL);
+	}
+
+	if (opt_o && wp->logpane_fd != -1) {
+		close(wp->logpane_fd);
+		wp->logpane_fd = -1;
+		return (CMD_RETURN_NORMAL);
+	}
+		
+	if (opt_b || (opt_o && wp->logpane_fd == -1)) {
+
+		if (wp->logpane_fd != -1)
+			return (CMD_RETURN_NORMAL);
+		
+		cmd_log_pane_open_file(s, wl, wp);
+
+		if (wp->logpane_fd == -1 ) {
+			cmdq_error(cmdq, "error opening logfile %s: %s", wp->logpane_filename, strerror(errno));
+			return (CMD_RETURN_ERROR);
+		}
+
+	}
+
+	return (CMD_RETURN_NORMAL);
+}
+
+
+char *
+cmd_log_pane_parse_filename(struct session *s, struct winlink *wl, struct window_pane *wp, const char *filename)
+{
+
+	char			*newfilename, *ftmp;
+
+	if (filename == NULL)
+		return (NULL);
+
+	ftmp = status_replace(NULL, s, wl, wp, filename, time(NULL), 0);
+	if (ftmp == NULL)
+		return (NULL);
+
+	newfilename = cmd_string_expand_path(ftmp);
+	free(ftmp);
+
+	return (newfilename);
+}
+
+
+void
+cmd_log_pane_open_file(struct session *s, struct winlink *wl, struct window_pane *wp)
+{
+	char *filename;
+
+	if (wp->logpane_filename == NULL) {
+		filename = options_get_string(&s->options, "logpane-default-logname");
+		wp->logpane_filename = cmd_log_pane_parse_filename(s, wl, wp, filename);
+	}
+
+	wp->logpane_fd = open(wp->logpane_filename, O_CREAT|O_WRONLY|O_APPEND|O_NOCTTY, 0600);
+}
+
+
+void
+cmd_log_pane_write_data(struct window_pane *wp, char *data, size_t size)
+{
+	char		*ptr;
+	int 		 rc;
+	size_t		 written;
+
+	written = 0;
+	while(written < size) {
+		ptr = &data[written];
+		rc = write(wp->logpane_fd, ptr, size - written);
+		if (rc < 0) {
+			if(errno == EINTR) {
+				rc = 0;
+			} else {
+				close(wp->logpane_fd);
+				wp->logpane_fd = -1;
+				return;
+			}
+		}
+
+		written += rc;
+	}
+}
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 4eebe63..562c44b 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -20,6 +20,7 @@
 
 #include <pwd.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
@@ -59,6 +60,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 	struct client		*c = cmdq->client;
 	struct session		*s, *groupwith;
 	struct window		*w;
+	struct window_pane	*wp;
 	struct environ		 env;
 	struct termios		 tio, *tiop;
 	struct passwd		*pw;
@@ -200,6 +202,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 		options_set_number(&w->options, "automatic-rename", 0);
 	}
 
+	/* Open the logfile if logging is enabled. */
+        if (options_get_number(&s->options, "logpane-autolog")) {
+		wp = s->curw->window->active;
+		cmd_log_pane_open_file(s, s->curw, wp);
+		if(wp->logpane_fd == -1)
+			cmdq_error(cmdq, "error opening logfile %s: %s", wp->logpane_filename, strerror(errno));
+	}
+
 	/*
 	 * If a target session is given, this is to be part of a session group,
 	 * so add it to the group and synchronize.
diff --git a/cmd-new-window.c b/cmd-new-window.c
index cfc0b8b..f81a7ba 100644
--- a/cmd-new-window.c
+++ b/cmd-new-window.c
@@ -19,6 +19,8 @@
 #include <sys/types.h>
 
 #include <stdlib.h>
+#include <errno.h>
+#include <string.h>
 
 #include "tmux.h"
 
@@ -50,6 +52,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 	char			*cause, *cp;
 	int			 idx, last, detached;
 	struct format_tree	*ft;
+	struct window_pane	*wp;
 
 	if (args_has(args, 'a')) {
 		wl = cmd_find_window(cmdq, args_get(args, 't'), &s);
@@ -119,6 +122,13 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 	} else
 		server_status_session_group(s);
 
+	if (options_get_number(&s->options, "logpane-autolog")) {
+		wp = wl->window->active;
+		cmd_log_pane_open_file(s, wl, wp);
+		if(wp->logpane_fd == -1)
+			cmdq_error(cmdq, "error opening logfile %s: %s", wp->logpane_filename, strerror(errno));
+	}
+
 	if (args_has(args, 'P')) {
 		if ((template = args_get(args, 'F')) == NULL)
 			template = NEW_WINDOW_TEMPLATE;
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 601dcb1..aa6dc61 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -20,6 +20,8 @@
 
 #include <stdlib.h>
 #include <unistd.h>
+#include <errno.h>
+#include <string.h>
 
 #include "tmux.h"
 
@@ -138,6 +140,12 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 
 	environ_free(&env);
 
+	if (options_get_number(&s->options, "logpane-autolog")) {
+		cmd_log_pane_open_file(s, wl, new_wp);
+		if(new_wp->logpane_fd == -1)
+			cmdq_error(cmdq, "error opening logfile %s: %s", new_wp->logpane_filename, strerror(errno));
+	}
+
 	if (args_has(args, 'P')) {
 		if ((template = args_get(args, 'F')) == NULL)
 			template = SPLIT_WINDOW_TEMPLATE;
diff --git a/cmd-string.c b/cmd-string.c
index 7e84eda..25edb29 100644
--- a/cmd-string.c
+++ b/cmd-string.c
@@ -37,6 +37,7 @@ void	 cmd_string_copy(char **, char *, size_t *);
 char	*cmd_string_string(const char *, size_t *, char, int);
 char	*cmd_string_variable(const char *, size_t *);
 char	*cmd_string_expand_tilde(const char *, size_t *);
+char	*cmd_string_expand_path(const char *);
 
 int
 cmd_string_getc(const char *s, size_t *p)
@@ -341,3 +342,65 @@ cmd_string_expand_tilde(const char *s, size_t *p)
 	xasprintf(&path, "%s/", home);
 	return (path);
 }
+
+char *
+cmd_string_expand_path(const char *s)
+{
+	size_t	 p, len;
+	char	*buf, *t;
+	int	 ch;
+
+	buf = NULL;
+	len = 0;
+        p = 0;
+
+        for (;;) {
+                ch = cmd_string_getc(s, &p);
+                switch (ch) {
+                case '\'':
+                        if ((t = cmd_string_string(s, &p, '\'', 0)) == NULL)
+                                goto error;
+                        cmd_string_copy(&buf, t, &len);
+                        break;
+                case '"':
+                        if ((t = cmd_string_string(s, &p, '"', 1)) == NULL)
+                                goto error;
+                        cmd_string_copy(&buf, t, &len);
+                        break;
+                case '$':
+                        if ((t = cmd_string_variable(s, &p)) == NULL)
+                                goto error;
+                        cmd_string_copy(&buf, t, &len);
+                        break;
+		case EOF:
+                        if (buf != NULL) {
+                                buf = xrealloc(buf, 1, len + 1);
+                                buf[len] = '\0';
+                        }
+			goto out;
+                case '~':
+                        if (buf == NULL) {
+                                t = cmd_string_expand_tilde(s, &p);
+                                if (t == NULL)
+                                        goto error;
+                                cmd_string_copy(&buf, t, &len);
+                                break;
+                        }
+                        /* FALLTHROUGH */
+                default:
+                        if (len >= SIZE_MAX - 2)
+                                goto error;
+
+                        buf = xrealloc(buf, 1, len + 1);
+                        buf[len++] = ch;
+                        break;
+                }
+        }
+
+error:
+        free(buf);
+	buf = NULL;
+
+out:
+        return (buf);
+}
diff --git a/cmd.c b/cmd.c
index 282fb11..91ba36c 100644
--- a/cmd.c
+++ b/cmd.c
@@ -69,6 +69,7 @@ const struct cmd_entry *cmd_table[] = {
 	&cmd_lock_client_entry,
 	&cmd_lock_server_entry,
 	&cmd_lock_session_entry,
+	&cmd_log_pane_entry,
 	&cmd_move_pane_entry,
 	&cmd_move_window_entry,
 	&cmd_new_session_entry,
diff --git a/options-table.c b/options-table.c
index 0b86ef7..dc6a82e 100644
--- a/options-table.c
+++ b/options-table.c
@@ -275,6 +275,16 @@ const struct options_table_entry session_options_table[] = {
 	  .default_num = 8
 	},
 
+	{ .name = "logpane-autolog",
+	  .type = OPTIONS_TABLE_FLAG,
+	  .default_num = 0
+	},
+
+	{ .name = "logpane-default-logname",
+	  .type = OPTIONS_TABLE_STRING,
+	  .default_str = "~/tmux-#S-#I-#P.log"
+	},
+
 	{ .name = "prefix",
 	  .type = OPTIONS_TABLE_KEY,
 	  .default_num = '\002',
diff --git a/status.c b/status.c
index 358f809..e3238a0 100644
--- a/status.c
+++ b/status.c
@@ -404,7 +404,7 @@ status_replace1(struct client *c, char **iptr, char **optr, char *out,
 			ch = ')';
 			goto skip_to;
 		}
-		if ((ptr = status_find_job(c, iptr)) == NULL)
+		if (c == NULL || (ptr = status_find_job(c, iptr)) == NULL)
 			return;
 		goto do_replace;
 	case '[':
@@ -466,11 +466,11 @@ status_replace(struct client *c, struct session *s, struct winlink *wl,
 	if (fmt == NULL)
 		return (xstrdup(""));
 
-	if (s == NULL)
+	if (s == NULL && c != NULL)
 		s = c->session;
-	if (wl == NULL)
+	if (wl == NULL && s != NULL)
 		wl = s->curw;
-	if (wp == NULL)
+	if (wp == NULL && wl != NULL)
 		wp = wl->window->active;
 
 	len = strftime(in, sizeof in, fmt, localtime(&t));
@@ -493,10 +493,18 @@ status_replace(struct client *c, struct session *s, struct winlink *wl,
 	*optr = '\0';
 
 	ft = format_create();
-	format_client(ft, c);
-	format_session(ft, s);
-	format_winlink(ft, s, wl);
-	format_window_pane(ft, wp);
+	if (c != NULL)
+		format_client(ft, c);
+
+	if (s != NULL) {
+		format_session(ft, s);
+		if (wl != NULL)
+			format_winlink(ft, s, wl);
+	}
+
+	if (wp != NULL)
+		format_window_pane(ft, wp);
+
 	expanded = format_expand(ft, out);
 	format_free(ft);
 	return (expanded);
diff --git a/tmux.h b/tmux.h
index 1cb5cd8..dd98f64 100644
--- a/tmux.h
+++ b/tmux.h
@@ -963,6 +963,9 @@ struct window_pane {
 	struct bufferevent *pipe_event;
 	size_t		 pipe_off;
 
+	int		 logpane_fd;
+	char		*logpane_filename;
+
 	struct screen	*screen;
 	struct screen	 base;
 
@@ -1808,6 +1811,7 @@ extern const struct cmd_entry cmd_load_buffer_entry;
 extern const struct cmd_entry cmd_lock_client_entry;
 extern const struct cmd_entry cmd_lock_server_entry;
 extern const struct cmd_entry cmd_lock_session_entry;
+extern const struct cmd_entry cmd_log_pane_entry;
 extern const struct cmd_entry cmd_move_pane_entry;
 extern const struct cmd_entry cmd_move_window_entry;
 extern const struct cmd_entry cmd_new_session_entry;
@@ -1877,6 +1881,7 @@ void		 cmdq_flush(struct cmd_q *);
 /* cmd-string.c */
 int	cmd_string_parse(const char *, struct cmd_list **, const char *,
 	    u_int, char **);
+char	*cmd_string_expand_path(const char *);
 
 /* client.c */
 int	client_main(int, char **, int);
@@ -2366,4 +2371,8 @@ int		 xvasprintf(char **, const char *, va_list);
 int printflike3	 xsnprintf(char *, size_t, const char *, ...);
 int		 xvsnprintf(char *, size_t, const char *, va_list);
 
+/* cmd-log-pane.c */
+void cmd_log_pane_open_file(struct session *, struct winlink *, struct window_pane *);
+void cmd_log_pane_write_data(struct window_pane *, char *, size_t);
+
 #endif /* TMUX_H */
diff --git a/window.c b/window.c
index 7678adc..e4715a9 100644
--- a/window.c
+++ b/window.c
@@ -691,6 +691,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
 	wp->pipe_off = 0;
 	wp->pipe_event = NULL;
 
+	wp->logpane_filename = NULL;
+	wp->logpane_fd = -1;
+
 	wp->saved_grid = NULL;
 
 	screen_init(&wp->base, sx, sy, hlimit);
@@ -725,6 +728,12 @@ window_pane_destroy(struct window_pane *wp)
 		close(wp->pipe_fd);
 	}
 
+	if (wp->logpane_fd != -1)
+		close(wp->logpane_fd);
+
+	if (wp->logpane_filename != NULL)
+		free(wp->logpane_filename);
+
 	RB_REMOVE(window_pane_tree, &all_window_panes, wp);
 
 	free(wp->cwd);
@@ -871,9 +880,14 @@ window_pane_read_callback(unused struct bufferevent *bufev, void *data)
 	size_t			new_size;
 
 	new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
-	if (wp->pipe_fd != -1 && new_size > 0) {
+	if ((wp->pipe_fd != -1 || wp->logpane_fd != -1) && new_size > 0) {
 		new_data = EVBUFFER_DATA(wp->event->input);
-		bufferevent_write(wp->pipe_event, new_data, new_size);
+
+		if (wp->pipe_fd != -1 )
+			bufferevent_write(wp->pipe_event, new_data, new_size);
+
+		if (wp->logpane_fd != -1)
+			cmd_log_pane_write_data(wp, new_data, new_size);
 	}
 
 	input_parse(wp);
