diff --git a/cmd-new-session.c b/cmd-new-session.c
index b1e1aa4..c0865ad 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>
@@ -49,6 +50,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;
@@ -205,6 +207,16 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
 		session_select(s, RB_ROOT(&s->windows)->idx);
 	}
 
+
+	/* Open the logfile if logging is enabled. */
+        if (options_get_number(&s->curw->window->options, "automatic-log")) {
+		wp = s->curw->window->active;
+		logging_open_file(s, s->curw, wp);
+		if(wp->logging_fd == -1)
+			cmdq_info(cmdq, "error opening logfile: %s", strerror(errno));
+	}
+
+
 	/*
 	 * Set the client to the new session. If a command client exists, it is
 	 * taking this session and needs to get MSG_READY and stay around.
diff --git a/cmd-new-window.c b/cmd-new-window.c
index 2ca0cec..bbffd71 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"
 
@@ -49,6 +51,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);
@@ -118,6 +121,13 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
 	} else
 		server_status_session_group(s);
 
+	if (options_get_number(&wl->window->options, "automatic-log")) {
+		wp = wl->window->active;
+		logging_open_file(s, wl, wp);
+		if(wp->logging_fd == -1)
+			cmdq_info(cmdq, "error opening logfile: %s", strerror(errno));
+	}
+
 	if (args_has(args, 'P')) {
 		if ((template = args_get(args, 'F')) == NULL)
 			template = NEW_WINDOW_TEMPLATE;
diff --git a/cmd-set-option.c b/cmd-set-option.c
index 3acf125..76c1051 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -20,6 +20,10 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
 
 #include "tmux.h"
 
@@ -61,6 +65,19 @@ struct options_entry *cmd_set_option_choice(struct cmd *, struct cmd_q *,
 	    const struct options_table_entry *, struct options *,
 	    const char *);
 
+char	*logging_expand_filename(struct session *, struct winlink *,
+		 struct window_pane *, const char *);
+void	logging_open_file(struct session *, struct winlink *,
+		 struct window_pane *);
+void	logging_error_callback(struct bufferevent *, short, void *);
+
+enum cmd_retval	logging_global_enable(struct cmd_q *);
+enum cmd_retval	logging_window_enable(struct cmd_q *, struct winlink *);
+void	logging_global_disable(void);
+void	logging_window_disable(struct winlink *);
+
+
+
 const struct cmd_entry cmd_set_option_entry = {
 	"set-option", "set",
 	"agoqst:uw", 1, 2,
@@ -168,6 +185,33 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq)
 			return (CMD_RETURN_ERROR);
 	}
 
+
+
+	/* start or stop logging */
+	if (strcmp (oe->name, "automatic-log") == 0) {
+		if (oo == &global_w_options) {
+			if (options_get_number(oo, "automatic-log")) {
+				if (logging_global_enable(cmdq) == CMD_RETURN_ERROR)
+					return (CMD_RETURN_ERROR);
+			} else {
+				logging_global_disable();
+			}
+		} else if (wl != NULL && oo == &wl->window->options) {
+			if (options_get_number(oo, "automatic-log")) {
+				if (logging_window_enable(cmdq, wl) == CMD_RETURN_ERROR)
+					return (CMD_RETURN_ERROR);
+			} else {
+				logging_window_disable(wl);
+			}
+		} else {
+			cmdq_error(cmdq, "unknown option table");
+			return (CMD_RETURN_ERROR);
+		}
+	}
+
+
+
+
 	/* Start or stop timers when automatic-rename changed. */
 	if (strcmp (oe->name, "automatic-rename") == 0) {
 		for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
@@ -462,3 +506,133 @@ cmd_set_option_choice(unused struct cmd *self, struct cmd_q *cmdq,
 
 	return (options_set_number(oo, oe->name, choice));
 }
+
+char *
+logging_expand_filename(struct session *s, struct winlink *wl, struct window_pane *wp, const char *alf)
+{
+
+	char			*expanded, buf[BUFSIZ];
+	struct format_tree	*ft;
+	time_t			 t;
+
+	if (alf == NULL)
+		return (NULL);
+
+	t = time(NULL);
+	strftime(buf, sizeof buf, alf, localtime(&t));
+
+	ft = format_create();
+	format_session(ft, s);
+	format_winlink(ft, s, wl);
+	format_window_pane(ft, wp);
+	expanded = format_expand(ft, buf);
+	format_free(ft);
+	return (expanded);
+}
+
+void
+logging_open_file(struct session *s, struct winlink *wl, struct window_pane *wp)
+{
+	const char	*alf;
+	char		*filename;
+
+	alf = options_get_string(&wl->window->options, "automatic-log-file");
+
+	filename = logging_expand_filename(s, wl, wp, alf);
+	wp->logging_fd = open(filename, O_CREAT|O_WRONLY|O_APPEND|O_NOCTTY, 0600);
+	free(filename);
+
+	if (wp->logging_fd != -1) {
+		wp->logging_event = bufferevent_new(wp->logging_fd,
+		    NULL, NULL, logging_error_callback, wp);
+		bufferevent_enable(wp->logging_event, EV_WRITE);
+	}
+}
+
+void
+logging_error_callback(
+    unused struct bufferevent *bufev, unused short what, void *data)
+{
+	struct window_pane	*wp = data;
+
+	bufferevent_free(wp->logging_event);
+	close(wp->logging_fd);
+	wp->logging_fd = -1;
+}
+
+
+enum cmd_retval
+logging_global_enable(struct cmd_q *cmdq)
+{
+	struct session		*s;
+	struct winlink		*wl;
+
+	RB_FOREACH(s, sessions, &sessions) {
+		RB_FOREACH(wl, winlinks, &s->windows) {
+			if (options_get_number(&wl->window->options, "automatic-log"))
+				if (logging_window_enable(cmdq, wl) == CMD_RETURN_ERROR)
+					return (CMD_RETURN_ERROR);
+		}
+	}
+	return (CMD_RETURN_NORMAL);
+}
+
+
+void
+logging_global_disable()
+{
+	struct session		*s;
+	struct winlink		*wl;
+
+	RB_FOREACH(s, sessions, &sessions) {
+		RB_FOREACH(wl, winlinks, &s->windows) {
+			if (!options_get_number(&wl->window->options, "automatic-log"))
+				logging_window_disable(wl);
+		}
+	}
+}
+
+
+enum cmd_retval
+logging_window_enable(struct cmd_q *cmdq, struct winlink *wl)
+{
+	struct session		*s;
+	struct window_pane	*wp;
+
+
+	RB_FOREACH(s, sessions, &sessions) {
+		if (session_has(s, wl->window) != NULL)
+			break;
+	}
+	if (s == NULL) {
+		cmdq_error(cmdq, "failed to enable logging");
+		return (CMD_RETURN_ERROR);
+	}
+
+	TAILQ_FOREACH(wp, &wl->window->panes, entry) {
+		if (wp->logging_fd == -1 ) {
+			logging_open_file(s, wl, wp);
+
+			if (wp->logging_fd == -1) {
+				cmdq_error(cmdq, "failed to enable logging: %s", strerror(errno));
+				return (CMD_RETURN_ERROR);
+			}
+		}
+	}
+	return (CMD_RETURN_NORMAL);
+}
+				
+			
+void
+logging_window_disable(struct winlink *wl)
+{
+	struct window_pane	*wp;
+
+	TAILQ_FOREACH(wp, &wl->window->panes, entry) {
+		if (wp->logging_fd != -1) {
+			bufferevent_free(wp->logging_event);
+			close(wp->logging_fd);
+			wp->logging_fd = -1;
+		}
+	}
+}
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 5b5140b..0c5f73b 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"
 
@@ -137,6 +139,12 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
 
 	environ_free(&env);
 
+	if (options_get_number(&wl->window->options, "automatic-log")) {
+		logging_open_file(s, wl, new_wp);
+		if(new_wp->logging_fd == -1)
+			cmdq_info(cmdq, "error opening logfile: %s", strerror(errno));
+	}
+
 	if (args_has(args, 'P')) {
 		if ((template = args_get(args, 'F')) == NULL)
 			template = SPLIT_WINDOW_TEMPLATE;
diff --git a/options-table.c b/options-table.c
index f6a1547..765395c 100644
--- a/options-table.c
+++ b/options-table.c
@@ -476,6 +476,16 @@ const struct options_table_entry window_options_table[] = {
 	  .default_num = 1
 	},
 
+	{ .name = "automatic-log",
+	  .type = OPTIONS_TABLE_FLAG,
+	  .default_num = 0
+	},
+
+	{ .name = "automatic-log-file",
+	  .type = OPTIONS_TABLE_STRING,
+	  .default_str = "tmux-#S-#I-#P.log"
+	},
+
 	{ .name = "automatic-rename",
 	  .type = OPTIONS_TABLE_FLAG,
 	  .default_num = 1
diff --git a/tmux.h b/tmux.h
index 63eddd1..37438dd 100644
--- a/tmux.h
+++ b/tmux.h
@@ -963,6 +963,9 @@ struct window_pane {
 	struct bufferevent *pipe_event;
 	size_t		 pipe_off;
 
+	int		 logging_fd;
+	struct bufferevent *logging_event;
+
 	struct screen	*screen;
 	struct screen	 base;
 
@@ -2371,4 +2374,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-set-option.c */
+void	logging_open_file(struct session *, struct winlink *,
+		struct window_pane *);
+
 #endif /* TMUX_H */
diff --git a/window.c b/window.c
index 7912bd3..d36b635 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->logging_fd = -1;
+	wp->logging_event = NULL;
+
 	wp->saved_grid = NULL;
 
 	screen_init(&wp->base, sx, sy, hlimit);
@@ -725,6 +728,11 @@ window_pane_destroy(struct window_pane *wp)
 		close(wp->pipe_fd);
 	}
 
+	if (wp->logging_fd != -1) {
+		bufferevent_free(wp->logging_event);
+		close(wp->logging_fd);
+	}
+
 	RB_REMOVE(window_pane_tree, &all_window_panes, wp);
 
 	free(wp->cwd);
@@ -871,9 +879,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->logging_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->logging_fd != -1)
+			bufferevent_write(wp->logging_event, new_data, new_size);
 	}
 
 	input_parse(wp);
