Index: uspace/app/bdsh/input.c
===================================================================
--- uspace/app/bdsh/input.c	(revision 025759cdc4055ca51d57f936b27dc11c8f46f1b3)
+++ uspace/app/bdsh/input.c	(revision 272f88f0092491c270b7b8e516115d98d7801676)
@@ -38,4 +38,5 @@
 #include <vfs/vfs.h>
 #include <errno.h>
+#include <assert.h>
 #include <bool.h>
 
@@ -47,4 +48,6 @@
 #include "exec.h"
 
+#define HISTORY_LEN 10
+
 typedef struct {
 	wchar_t buffer[INPUT_MAX];
@@ -53,4 +56,8 @@
 	int nc;
 	int pos;
+
+	char *history[1 + HISTORY_LEN];
+	int hnum;
+	int hpos;
 } tinput_t;
 
@@ -125,4 +132,17 @@
 }
 
+static char *tinput_get_str(tinput_t *ti)
+{
+	char *str;
+
+	str = malloc(STR_BOUNDS(ti->nc) + 1);
+	if (str == NULL)
+		return NULL;
+
+	wstr_nstr(str, ti->buffer, STR_BOUNDS(ti->nc) + 1);
+
+	return str;
+}
+
 static void tinput_position_caret(tinput_t *ti)
 {
@@ -235,4 +255,63 @@
 
 	tinput_position_caret(ti);
+}
+
+static void tinput_history_insert(tinput_t *ti, char *str)
+{
+	int i;
+
+	if (ti->hnum < HISTORY_LEN) {
+		ti->hnum += 1;
+	} else {
+		if (ti->history[HISTORY_LEN] != NULL)
+			free(ti->history[HISTORY_LEN]);
+	}
+
+	for (i = ti->hnum; i > 1; --i)
+		ti->history[i] = ti->history[i - 1];
+
+	ti->history[1] = str_dup(str);
+
+	if (ti->history[0] != NULL) {
+		free(ti->history[0]);
+		ti->history[0] = NULL;
+	}
+}
+
+static void tinput_set_str(tinput_t *ti, char *str)
+{
+	str_to_wstr(ti->buffer, INPUT_MAX, str);
+	ti->nc = wstr_length(ti->buffer);
+	ti->pos = ti->nc;
+}
+
+static void tinput_history_seek(tinput_t *ti, int offs)
+{
+	int pad;
+
+	if (ti->hpos + offs < 0 || ti->hpos + offs > ti->hnum)
+		return;
+
+	if (ti->history[ti->hpos] != NULL) {
+		free(ti->history[ti->hpos]);
+		ti->history[ti->hpos] = NULL;
+	}
+
+	ti->history[ti->hpos] = tinput_get_str(ti);
+	ti->hpos += offs;
+
+	pad = ti->nc - str_length(ti->history[ti->hpos]);
+	if (pad < 0) pad = 0;
+
+	tinput_set_str(ti, ti->history[ti->hpos]);
+	tinput_display_tail(ti, 0, pad);
+	tinput_position_caret(ti);
+}
+
+static void tinput_init(tinput_t *ti)
+{
+	ti->hnum = 0;
+	ti->hpos = 0;
+	ti->history[0] = NULL;
 }
 
@@ -295,4 +374,10 @@
 				tinput_seek_max(ti, seek_forward);
 				break;
+			case KC_UP:
+				tinput_history_seek(ti, +1);
+				break;
+			case KC_DOWN:
+				tinput_history_seek(ti, -1);
+				break;
 			}
 		}
@@ -306,10 +391,9 @@
 	putchar('\n');
 
-	ti->buffer[ti->nc] = '\0';
-	str = malloc(STR_BOUNDS(ti->nc) + 1);
-	if (str == NULL)
-		return NULL;
-
-	wstr_nstr(str, ti->buffer, STR_BOUNDS(ti->nc) + 1);
+	str = tinput_get_str(ti);
+	if (str_cmp(str, "") != 0)
+		tinput_history_insert(ti, str);
+
+	ti->hpos = 0;
 
 	return str;
@@ -337,2 +421,7 @@
 	return;
 }
+
+void input_init(void)
+{
+	tinput_init(&tinput);
+}
Index: uspace/app/bdsh/input.h
===================================================================
--- uspace/app/bdsh/input.h	(revision 025759cdc4055ca51d57f936b27dc11c8f46f1b3)
+++ uspace/app/bdsh/input.h	(revision 272f88f0092491c270b7b8e516115d98d7801676)
@@ -8,4 +8,5 @@
 extern void get_input(cliuser_t *);
 extern int tok_input(cliuser_t *);
+extern void input_init(void);
 
 #endif
Index: uspace/app/bdsh/scli.c
===================================================================
--- uspace/app/bdsh/scli.c	(revision 025759cdc4055ca51d57f936b27dc11c8f46f1b3)
+++ uspace/app/bdsh/scli.c	(revision 272f88f0092491c270b7b8e516115d98d7801676)
@@ -64,4 +64,7 @@
 	usr->prompt = (char *) NULL;
 	usr->lasterr = 0;
+
+	input_init();
+
 	return (int) cli_set_prompt(usr);
 }
Index: uspace/lib/libc/generic/string.c
===================================================================
--- uspace/lib/libc/generic/string.c	(revision 025759cdc4055ca51d57f936b27dc11c8f46f1b3)
+++ uspace/lib/libc/generic/string.c	(revision 272f88f0092491c270b7b8e516115d98d7801676)
@@ -583,4 +583,36 @@
 }
 
+/** Convert string to wide string.
+ *
+ * Convert string @a src to wide string. The output is written to the
+ * buffer specified by @a dest and @a size, which must have non-zero
+ * size. The output will always be null-terminated.
+ *
+ * @param dest	Destination buffer.
+ * @param dlen	Length of destination buffer (number of wchars).
+ * @param src	Source string.
+ */
+void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
+{
+	size_t offset;
+	size_t di;
+	wchar_t c;
+
+	assert(dlen > 0);
+
+	offset = 0;
+	di = 0;
+
+	do {
+		if (di >= dlen - 1)
+			break;
+
+		c = str_decode(src, &offset, STR_NO_LIMIT);
+		dest[di++] = c;
+	} while (c != '\0');
+
+	dest[dlen - 1] = '\0';
+}
+
 /** Find first occurence of character in string.
  *
Index: uspace/lib/libc/include/string.h
===================================================================
--- uspace/lib/libc/include/string.h	(revision 025759cdc4055ca51d57f936b27dc11c8f46f1b3)
+++ uspace/lib/libc/include/string.h	(revision 272f88f0092491c270b7b8e516115d98d7801676)
@@ -74,4 +74,5 @@
 
 extern void wstr_nstr(char *dst, const wchar_t *src, size_t size);
+extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
 
 extern char *str_chr(const char *str, wchar_t ch);
