diff --git a/dclish/dclish.go b/dclish/dclish.go
index 15788c5a34452a8fb92099bf755954ef738d1941..76a38a2c05ff7f779817393ff57a712b135bc5bb 100644
--- a/dclish/dclish.go
+++ b/dclish/dclish.go
@@ -162,8 +162,11 @@ func (c Commands) run(words []string) error {
 	// Deal with subcommands.
 	if len(cmd.Commands) > 0 {
 		if len(words) == 1 {
-			fmt.Printf("ERROR: missing subcommand for %s.\n", wordup)
-			return nil
+			if cmd.Action == nil {
+				fmt.Printf("ERROR: missing subcommand for %s.\n", wordup)
+				return nil
+			}
+			return cmd.Action(cmd)
 		}
 		return cmd.Commands.run(words[1:])
 	}
diff --git a/repl/accounts.go b/repl/accounts.go
new file mode 100644
index 0000000000000000000000000000000000000000..0047b875271617cba65bc0c1511a042286bc4cb1
--- /dev/null
+++ b/repl/accounts.go
@@ -0,0 +1,94 @@
+package repl
+
+import (
+	"fmt"
+
+	"git.lyda.ie/kevin/bulletin/dclish"
+)
+
+// ActionUser handles the `USER` command.
+func ActionUser(cmd *dclish.Command) error {
+	fmt.Println(cmd.Description)
+	fmt.Println(`
+The following commands are available:
+
+  ADD        ADMIN      DELETE     DISABLE    ENABLE     MOD
+  NOADMIN    NOMOD`)
+	fmt.Println()
+	return nil
+}
+
+// ActionUserAdd handles the `USER ADD` command.
+func ActionUserAdd(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserDelete handles the `USER DELETE` command.
+func ActionUserDelete(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserEnable handles the `USER ENABLE` command.
+func ActionUserEnable(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserDisable handles the `USER DISABLE` command.
+func ActionUserDisable(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserAdmin handles the `USER ADMIN` command.
+func ActionUserAdmin(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserNoadmin handles the `USER NOADMIN` command.
+func ActionUserNoadmin(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserMod handles the `USER MOD` command.
+func ActionUserMod(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionUserNomod handles the `USER NOMOD` command.
+func ActionUserNomod(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionSSH handles the `SSH` command.
+func ActionSSH(cmd *dclish.Command) error {
+	fmt.Println(cmd.Description)
+	fmt.Println(`\nThe following commands are available:
+
+  ADD        DELETE     LIST`)
+	return nil
+}
+
+// ActionSSHAdd handles the `SSH ADD` command.
+func ActionSSHAdd(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionSSHDelete handles the `SSH DELETE` command.
+func ActionSSHDelete(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
+
+// ActionSSHList handles the `SSH LIST` command.
+func ActionSSHList(_ *dclish.Command) error {
+	// TODO: implement
+	return nil
+}
diff --git a/repl/command.go b/repl/command.go
index e35f61bb50059e0e4bdb5b0a78924f13c00d436b..6b87031f43cc6173c0a93ce3ed0e7e78c4956d2d 100644
--- a/repl/command.go
+++ b/repl/command.go
@@ -773,6 +773,7 @@ provides more  flexibility than is  present with the PRINT  command. For
 example, if you  want to print all messages with  a particular string in
 it's subject line, DIRECTORY/PRINT/SUBJ would allow you do it.`,
 		MaxArgs: 1,
+		Action:  ActionPrint,
 		Flags: dclish.Flags{
 			"/ALL": {
 				Description: `  Prints all the messages in the current folder.`,
@@ -1089,9 +1090,9 @@ Omitting the folder name will select the default general messages.
 After selecting a folder, the user will notified of the number of unread
 messages,  and  the  message  pointer will be placed at the first unread
 message.`,
-		Action:  ActionSelect,
 		MinArgs: 1,
 		MaxArgs: 1,
+		Action:  ActionSelect,
 		Flags: dclish.Flags{
 			"/MARKED": {
 				Description: `  Selects  only messages that have been marked (indicated by an asterisk).
@@ -1100,12 +1101,90 @@ message.`,
 			},
 		},
 	},
+	"USER": {
+		Description: `Commands for managing users.`,
+		Action:      ActionUser,
+		Commands: dclish.Commands{
+			"ADD": {
+				Description: `  Creates a user.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserAdd,
+			},
+			"DELETE": {
+				Description: `  Removes a user.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserDelete,
+			},
+			"ENABLE": {
+				Description: `  Enables a user.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserEnable,
+			},
+			"DISABLE": {
+				Description: `  Disables a user.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserDisable,
+			},
+			"ADMIN": {
+				Description: `  Makes a user an admin.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserAdmin,
+			},
+			"NOADMIN": {
+				Description: `  Removes the admin bit from a user.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserNoadmin,
+			},
+			"MOD": {
+				Description: `  Makes a user an mod.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserMod,
+			},
+			"NOMOD": {
+				Description: `  Removes the mod bit from a user.`,
+				MinArgs:     1,
+				MaxArgs:     1,
+				Action:      ActionUserNomod,
+			},
+		},
+	},
+	"SSH": {
+		Description: `The SSH command is used to manage SSH keys for users.`,
+		Action:      ActionSSH,
+		Commands: dclish.Commands{
+			"ADD": {
+				Description: `  Adds an ssh key for a user.
+
+  Prompts the user for an ssh key and then adds it.`,
+				Action: ActionSSHAdd,
+			},
+			"DELETE": {
+				Description: `  Removes an ssh key for a user.
+
+  The user  is given a list  of current ssh  keys and is asked  which to
+  remove.`,
+				Action: ActionSSHDelete,
+			},
+			"LIST": {
+				Description: `  Prints a list of ssh keys for the user.`,
+				Action:      ActionSSHList,
+			},
+		},
+	},
 	"SET": {
 		Description: `The SET command  is  used  with  other  commands  to  define  or  change
 characteristics of the BULLETIN Utility.
 
   Format:
     SET option`,
+		Action: ActionSet,
 		Commands: dclish.Commands{
 			"ACCESS": {
 				Description: `Controls  access  to  a  private  folder.   A private folder can only be
@@ -1351,33 +1430,6 @@ so that bit 1 is cleared.`,
 				Action:  ActionSetNonotify,
 				MaxArgs: 1,
 			},
-			"PRIVILEGES": {
-				Description: `Specifies  either  process  privileges  or  rights  identifiers that are
-necessary to use privileged commands.  Use the SHOW  PRIVILEGES  command
-to see what is presently set.  This is a privileged command.
-
-  Format:
-    SET PRIVILEGES parameters
-
-The parameters are one or  more  privileges  separated  by  commas.   To
-remove  a privilege, specify the privilege preceeded by "NO".  If /ID is
-specified, the parameters are rights identifiers.
-
-For the reimplementation this is used to manage users.  The following parameters
-are available.
-
-  Format:
-	  SET PRIVILEGES CREATE login
-	  SET PRIVILEGES DELETE login
-	  SET PRIVILEGES SSH [login]
-	  SET PRIVILEGES [NO]ADMIN login
-	  SET PRIVILEGES [NO]MOD login [folder]
-	  SET PRIVILEGES ENABLE login
-	  SET PRIVILEGES DISABLE login`,
-				MinArgs: 1,
-				MaxArgs: 3,
-				Action:  ActionSetPrivileges,
-			},
 			"PROMPT_EXPIRE": {
 				Description: `Specifies  that a  user will  be prompted  for an  expiration date  when
 adding a message. If the value  specified is greater than the expiration
@@ -1520,6 +1572,7 @@ that folder cannot be removed.`,
 	"SHOW": {
 		Description: `The SHOW command displays information about certain characteristics.
 `,
+		Action: ActionShow,
 		Commands: dclish.Commands{
 			"FLAGS": {
 				Description: `Shows whether BRIEF, NOTIFY, READNEW, or SHOWNEW has been set for the
diff --git a/repl/set.go b/repl/set.go
index f8e078c672ac7ec0ec44f506f35158205fa2ebec..605d99eeb09040ff391eff0f8aafa75d100a9a0b 100644
--- a/repl/set.go
+++ b/repl/set.go
@@ -12,6 +12,22 @@ import (
 	"git.lyda.ie/kevin/bulletin/this"
 )
 
+// ActionSet handles the `SET` command.
+func ActionSet(cmd *dclish.Command) error {
+	fmt.Println(cmd.Description)
+	fmt.Println(`
+The following commands are available:
+
+  NOPROMPT_EXPIRE  NOPROMPT_EXPIRE  NOPROMPT_EXPIRE  NOPROMPT_EXPIRE
+  ACCESS           ALWAYS           BRIEF            DEFAULT_EXPIRE
+  EXPIRE_LIMIT     FOLDER           NOALWAYS         NOBRIEF
+  NONOTIFY         NOPROMPT_EXPIRE  NOREADNEW        NOSHOWNEW     
+  NOSYSTEM         NOTIFY           PROMPT_EXPIRE    READNEW     
+  SHOWNEW          SYSTEM`)
+	fmt.Println()
+	return nil
+}
+
 // ActionSetAccess handles the `SET ACCESS` command.
 func ActionSetAccess(_ *dclish.Command) error {
 	fmt.Println("TODO: implement ActionSetAccess.")
diff --git a/repl/show.go b/repl/show.go
index 3f4a05ec6081523c2dbcdc746593345fc6d72075..a583496e0faa9a4b30f89858567e22d4017d3472 100644
--- a/repl/show.go
+++ b/repl/show.go
@@ -12,6 +12,17 @@ import (
 	"git.lyda.ie/kevin/bulletin/this"
 )
 
+// ActionShow handles the `SHOW` command.
+func ActionShow(cmd *dclish.Command) error {
+	fmt.Println(cmd.Description)
+	fmt.Println(`
+The following commands are available:
+
+  FLAGS       FOLDER      NEW         PRIVILEGES  USER        VERSION`)
+	fmt.Println()
+	return nil
+}
+
 // ActionShowFlags handles the `SHOW FLAGS` command.
 func ActionShowFlags(_ *dclish.Command) error {
 	flagset := false