diff -up ../dmenu-4.5/dmenu.1 ./dmenu.1
--- ../dmenu-4.5/dmenu.1	2012-01-08 07:18:43.000000000 -0500
+++ ./dmenu.1	2013-03-11 15:57:11.812706207 -0400
@@ -20,6 +20,8 @@ dmenu \- dynamic menu
 .IR color ]
 .RB [ \-sf
 .IR color ]
+.RB [ \-hist
+.IR "<filename>" ]
 .RB [ \-v ]
 .P
 .BR dmenu_run " ..."
@@ -70,6 +72,9 @@ defines the selected background color.
 .BI \-sf " color"
 defines the selected foreground color.
 .TP
+.BI \-hist " <histfile>"
+the file to use for history
+.TP
 .B \-v
 prints version information to stdout, then exits.
 .SH USAGE
diff -up ../dmenu-4.5/dmenu.c ./dmenu.c
--- ../dmenu-4.5/dmenu.c	2012-01-08 07:18:43.000000000 -0500
+++ ./dmenu.c	2013-03-11 16:07:40.556683999 -0400
@@ -34,7 +34,7 @@ static void keypress(XKeyEvent *ev);
 static void match(void);
 static size_t nextrune(int inc);
 static void paste(void);
-static void readstdin(void);
+static void readitems(void);
 static void run(void);
 static void setup(void);
 static void usage(void);
@@ -61,6 +61,9 @@ static Item *prev, *curr, *next, *sel;
 static Window win;
 static XIC xic;
 
+static char *histfile = NULL;
+static Item *histitems, *histend;
+
 static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
 static char *(*fstrstr)(const char *, const char *) = strstr;
 
@@ -100,6 +103,8 @@ main(int argc, char *argv[]) {
 			selbgcolor = argv[++i];
 		else if(!strcmp(argv[i], "-sf"))  /* selected foreground color */
 			selfgcolor = argv[++i];
+		else if(!strcmp(argv[i], "-hist"))
+			histfile = argv[++i];
 		else
 			usage();
 
@@ -108,10 +113,10 @@ main(int argc, char *argv[]) {
 
 	if(fast) {
 		grabkeyboard();
-		readstdin();
+		readitems();
 	}
 	else {
-		readstdin();
+		readitems();
 		grabkeyboard();
 	}
 	setup();
@@ -120,6 +125,59 @@ main(int argc, char *argv[]) {
 	return 1; /* unreachable */
 }
 
+static int
+writehistory(char *command) {
+	FILE *f;
+	Item *histitem;
+	char *histline;
+	char *histcmd;
+	int currcnt = 1;
+	int histcnt;
+
+	if(!histfile || strlen(command) <= 0)
+		return 0;
+
+	if((f = fopen(histfile, "w"))) {
+		/* get the current count of previous runs for this command */
+		for(histitem = histitems; histitem && histitem->text; histitem=histitem->right) {
+			histline = strdup(histitem->text);
+			histcmd = strsep(&histline, "\t");
+			if(strcmp(command, histcmd) == 0) {
+				currcnt = atoi(strsep(&histline, "\t")) + 1;
+			}
+		}
+
+		/* loop through history printing those with more runs */
+		for(histitem = histitems; histitem && histitem->text; histitem=histitem->right) {
+			histline = strdup(histitem->text);
+			histcmd = strsep(&histline, "\t");
+			histcnt = atoi(strsep(&histline, "\t"));
+			if(histcnt > currcnt) {
+				fprintf(f, "%s", histitem->text);
+			} else {
+				break;
+			}
+		}
+
+		/* print this command now so it's the first in line with this run count */
+		/* reducing the count by 1 here to keep the next comparison loop simple */
+		fprintf(f, "%s\t%d\n", command, currcnt--);
+
+		/* print all the rest except this command's old line */
+		for(; histitem && histitem->text; histitem=histitem->right) {
+			histline = strdup(histitem->text);
+			histcmd = strsep(&histline, "\t");
+			histcnt = atoi(strsep(&histline, "\t"));
+			if(histcnt < currcnt || strcmp(command, histcmd) != 0)
+				fprintf(f, "%s", histitem->text);
+		}
+		fclose(f);
+		return 1;
+	}
+
+	return 0;
+}
+
 void
 appenditem(Item *item, Item **list, Item **last) {
 	if(*last)
@@ -359,6 +417,7 @@ keypress(XKeyEvent *ev) {
 	case XK_Return:
 	case XK_KP_Enter:
 		puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
+		writehistory( (sel == NULL) ? text : sel->text);
 		exit(EXIT_SUCCESS);
 	case XK_Right:
 		if(text[cursor] != '\0') {
@@ -464,26 +523,60 @@ paste(void) {
 }
 
 void
-readstdin(void) {
-	char buf[sizeof text], *p, *maxstr = NULL;
-	size_t i, max = 0, size = 0;
+readitems(void) {
+	char buf[sizeof text], *p, *maxstr = NULL, *histline, *histcmd;
+	size_t i = 0, j = 0, k = 0, max = 0, size = 0;
+	FILE *f;
+	Bool listed;
+	Item *histitem;
+	histitems = histend = NULL;
+
+	if(histfile && (f = fopen(histfile, "r"))) {
+		for(; fgets(buf, sizeof buf, f); i++) {
+			histitem = malloc(sizeof *histitem);
+			histitem->text = strdup(buf);
+			appenditem(histitem, &histitems, &histend);
+			if(i+1 >= size / sizeof *items)
+				if(!(items = realloc(items, (size += BUFSIZ))))
+					eprintf("cannot realloc %u bytes:", size);
+			if((p = strchr(buf, '\n')))
+				*p = '\0';
+			histline = strdup(buf);
+			histcmd = strsep(&histline, "\t");
+			if(!(items[i].text = strdup(histcmd)))
+				eprintf("cannot strdup %u bytes:", strlen(histcmd)+1);
+			if(strlen(items[i].text) > max)
+				max = strlen(maxstr = items[i].text);
+		}
+		fclose(f);
+	}
 
 	/* read each line from stdin and add it to the item list */
-	for(i = 0; fgets(buf, sizeof buf, stdin); i++) {
-		if(i+1 >= size / sizeof *items)
-			if(!(items = realloc(items, (size += BUFSIZ))))
-				eprintf("cannot realloc %u bytes:", size);
+	for(j = i; fgets(buf, sizeof buf, stdin); j++) {
 		if((p = strchr(buf, '\n')))
 			*p = '\0';
-		if(!(items[i].text = strdup(buf)))
-			eprintf("cannot strdup %u bytes:", strlen(buf)+1);
-		if(strlen(items[i].text) > max)
-			max = strlen(maxstr = items[i].text);
+		listed = False;
+		for(k = 0; k < i; k++) {
+			if(strcmp(buf, items[k].text) == 0) {
+				listed = True;
+				j--;
+				break;
+			}
+		}
+		if(!listed) {
+			if(j+1 >= size / sizeof *items)
+				if(!(items = realloc(items, (size += BUFSIZ))))
+					eprintf("cannot realloc %u bytes:", size);
+			if(!(items[j].text = strdup(buf)))
+				eprintf("cannot strdup %u bytes:", strlen(buf)+1);
+			if(strlen(items[j].text) > max)
+				max = strlen(maxstr = items[j].text);
+		}
 	}
 	if(items)
-		items[i].text = NULL;
+		items[j].text = NULL;
 	inputw = maxstr ? textw(dc, maxstr) : 0;
-	lines = MIN(lines, i);
+	lines = MIN(lines, j);
 }
 
 void
@@ -602,6 +695,6 @@ setup(void) {
 void
 usage(void) {
 	fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font]\n"
-	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
+	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-hist histfile] [-v]\n", stderr);
 	exit(EXIT_FAILURE);
 }
