diff --git a/NOTES.md b/NOTES.md
index d33a485dbf77eff2dd11d4a1ce8903b755e4030b..4ef9374b1949fecde9c9b0f8ff1aa4d8c061a6c2 100644
--- a/NOTES.md
+++ b/NOTES.md
@@ -16,11 +16,14 @@ Look up how godoc does references to other things.
 
 Look up how to run migrations on the db from embedded files.
 
+Figure out readline completion.  Case sensitive - issue?  Building from
+repl.commands?
+
 ## Things to do
 
   * Implement a better dclish parser.
   * Implement each command.
-    * Next: HELP - move some commands to a Help array.
+    * Next: ????
   * Decide on how the boards are managed.
 
 ## Module links
diff --git a/accounts/accounts.go b/accounts/accounts.go
index 11e68a4f0710708e03ec000eab2f7998ccc44bc0..acd5b25f32a8bb167d46bff9891fa7e302baf6b9 100644
--- a/accounts/accounts.go
+++ b/accounts/accounts.go
@@ -51,7 +51,7 @@ func Open(acc string) error {
 	if err != nil {
 		return errors.New("account preference directory problem")
 	}
-	User.pref, err = sql.Open("sqlite", path.Join(prefdir, acc, ".db"))
+	User.pref, err = sql.Open("sqlite", path.Join(prefdir, fmt.Sprintf("%s.%s", acc, ".db")))
 	if err != nil {
 		return errors.New("account preference database problem")
 	}
diff --git a/dclish/dclish.go b/dclish/dclish.go
index 07d4a13fdedd792716d00f062424772451aeef83..57aa8aa96157fd6a5c88e6e1fbe772f586018b4f 100644
--- a/dclish/dclish.go
+++ b/dclish/dclish.go
@@ -22,11 +22,11 @@ type Flags map[string]*Flag
 
 // Command contains the definition of a command, it's flags and subcommands.
 type Command struct {
-	Flags Flags
-	// TODO: FlagOrder []string
-	Args []string
-	// TODO: MaxArgs int
-	// TODO: MinArgs int
+	Flags       Flags
+	FlagOrder   []string
+	Args        []string
+	MaxArgs     int
+	MinArgs     int
 	Commands    []*Command
 	Action      ActionFunc
 	Description string
diff --git a/repl/help.go b/repl/help.go
index b2beca93c3ddce51fad74e30320232cd0e6e9d18..490c80da81d7c55f6bb375ae0f9a235dfc44276e 100644
--- a/repl/help.go
+++ b/repl/help.go
@@ -52,7 +52,7 @@ use is to create a folder for posting SYSTEM messages only meant for a
 certain UIC group.  This is done by creating a PRIVATE SYSTEM folder, and
 giving access to that UIC group.  Only users in that UIC group will see
 the messages in that folder when they log in.`,
-	"Ctrl-C": `Except for when BULLETIN is awaiting input from the terminal, a 
+	"CTRL-C": `Except for when BULLETIN is awaiting input from the terminal, a 
 CTRL-C will cause BULLETIN to abort the execution of any command.  If
 BULLETIN is waiting for terminal input, a CTRL-C will cause BULLETIN
 to return to the BULLETIN> prompt.  If for some reason the user wishes
diff --git a/repl/misc.go b/repl/misc.go
index f8bb289d553066754a1fd5490e801c3cd635d15b..a5b62f330ab8cca7e7b9d70b0e8d970d73fd51a0 100644
--- a/repl/misc.go
+++ b/repl/misc.go
@@ -2,8 +2,7 @@
 package repl
 
 import (
-	"fmt"
-	"os"
+	"errors"
 
 	"git.lyda.ie/kevin/bulletin/accounts"
 	"git.lyda.ie/kevin/bulletin/dclish"
@@ -12,17 +11,13 @@ import (
 // ActionQuit handles the `QUIT` command.
 func ActionQuit(_ *dclish.Command) error {
 	accounts.User.Close()
-	fmt.Println("QUIT")
-	// TODO: IIRC, quit should not update unread data.  Check.
-	os.Exit(0)
-	return nil
+	// TODO: IIRC, quit should not update unread data.  Check old code to confirm.
+	return errors.New("QUIT")
 }
 
 // ActionExit handles the `EXIT` command.
 func ActionExit(_ *dclish.Command) error {
 	accounts.User.Close()
-	fmt.Println("EXIT")
 	// TODO: update unread data.
-	os.Exit(0)
-	return nil
+	return errors.New("EXIT")
 }
diff --git a/repl/repl.go b/repl/repl.go
index 96683609cd0177fa42e88c9458570a2772b42bfc..0f3536642795c308ecc81df622652c00864cbf0d 100644
--- a/repl/repl.go
+++ b/repl/repl.go
@@ -3,14 +3,24 @@ package repl
 
 import (
 	"fmt"
+	"path"
 
+	"github.com/adrg/xdg"
 	"github.com/chzyer/readline"
 )
 
 // Loop is the main event loop.
 func Loop(user string) error {
-	fmt.Printf("TODO: get config for user %s using xdg.", user)
-	rl, err := readline.New("BULLETIN> ")
+	fmt.Printf("TODO: get config for user %s using xdg.\n", user)
+	rl, err := readline.NewEx(
+		&readline.Config{
+			Prompt:      "BULLETIN> ",
+			HistoryFile: path.Join(xdg.ConfigHome, "BULLETIN", fmt.Sprintf("%s.history", user)),
+			// TODO: AutoComplete:    completer,
+			InterruptPrompt:   "^C",
+			EOFPrompt:         "EXIT",
+			HistorySearchFold: true,
+		})
 	if err != nil {
 		return err
 	}
@@ -19,6 +29,11 @@ func Loop(user string) error {
 	for {
 		line, err := rl.Readline()
 		if err != nil {
+			if err.Error() == "Interrupt" {
+				commands.ParseAndRun("QUIT")
+			} else if err.Error() == "EOF" {
+				commands.ParseAndRun("EXIT")
+			}
 			return err
 		}
 		if len(line) == 0 {
@@ -29,6 +44,4 @@ func Loop(user string) error {
 			return err
 		}
 	}
-
-	return nil
 }