diff --git a/folders/messages.go b/folders/messages.go
index c787c4b3391734d3cbc4fb8fe036b4cf8ee3802d..92f859bffd994afa53dbd3675f862ef5397a3e95 100644
--- a/folders/messages.go
+++ b/folders/messages.go
@@ -2,6 +2,7 @@ package folders
 
 import (
 	"errors"
+	"fmt"
 	"time"
 
 	"git.lyda.ie/kevin/bulletin/storage"
@@ -40,6 +41,7 @@ func CreateMessage(author, subject, message, folder string, permanent, shutdown
 // ReadMessage reads a message for a user.
 func ReadMessage(login, folder string, msgid int64) (*storage.Message, error) {
 	ctx := storage.Context()
+	fmt.Printf("TODO: Make sure %s can read this message.\n", login)
 	msg, err := this.Q.ReadMessage(ctx, storage.ReadMessageParams{
 		Folder: folder,
 		ID:     msgid,
@@ -51,11 +53,6 @@ func ReadMessage(login, folder string, msgid int64) (*storage.Message, error) {
 	if msg.ID != int64(msgid) || msgid == 0 {
 		return nil, errors.New("Specified message was not found")
 	}
-	err = this.Q.SetMessageSeen(ctx, storage.SetMessageSeenParams{
-		Login:  login,
-		Folder: folder,
-		Msgid:  int64(msgid),
-	})
 
 	return &msg, nil
 }
@@ -130,6 +127,16 @@ func FirstMessage(folder string) int64 {
 	return first
 }
 
+// LastMessage gets the last message in a folder.
+func LastMessage(folder string) int64 {
+	ctx := storage.Context()
+	last, err := this.Q.LastMsgidIgnoringSeen(ctx, folder)
+	if err != nil {
+		return 0
+	}
+	return last
+}
+
 // ListMessages lists messages.
 func ListMessages(folder string) ([]storage.Message, error) {
 	ctx := storage.Context()
diff --git a/repl/command.go b/repl/command.go
index 536814373143c8c9a5a588cd7ca872d7bf2c73d1..e35f61bb50059e0e4bdb5b0a78924f13c00d436b 100644
--- a/repl/command.go
+++ b/repl/command.go
@@ -127,13 +127,6 @@ topic of the message.
   Specifies that the editor is to be used to read the message.  This is
   useful for scanning a long message.`,
 			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Specifies that if a message header exists, the header will be shown.
-  If /HEADER or /NOHEADER is specified, the setting will apply for all
-  further reads in the selected folder.  The default is /HEADER.`,
-			},
 		},
 	},
 	"CHANGE": {
@@ -176,10 +169,6 @@ This can be suppressed by the qualifier /NEW.
 			"/GENERAL": {
 				Description: `  Specifies that the message is to be converted from a SYSTEM message to
   a GENERAL message.  This only applies to the GENERAL folder.`,
-			},
-			"/HEADER": {
-				Description: `  Specifies  that the  message header  is to  be replaced.  You will  be
-  prompted for the new message description.`,
 			},
 			"/NEW": {
 				Description: `  If the editor is to be used for replacing the text of the message, NEW
@@ -236,17 +225,11 @@ The key words  CURRENT and LAST can  also be specified in  the range in,
 place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 		MinArgs: 1,
 		MaxArgs: 2,
+		Action:  ActionCopy,
 		Flags: dclish.Flags{
 			"/ALL": {
 				Description: `  Specifies to copy all the messages in the old folder.`,
 			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Valid  only if  destination folder  is  a news  group. Specifies  that
-  header of  message is to  be included with the  text when the  text is
-  copied. The default is /NOHEADER.`,
-			},
 			"/MERGE": {
 				Description: `  Specifies that the  original date and time of the  copied messages are
   saved and that the messages  are placed in correct chronological order
@@ -382,13 +365,6 @@ of the message again, you can enter the CURRENT command.
 				Description: `  Specifies that the editor  is to be used to read  the message. This is
   useful for scanning a long message.`,
 			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Specifies that if a message header exists, the header will be shown.
-  If /HEADER or /NOHEADER is specified, the setting will apply for all
-  further reads in the selected folder.  The default is /HEADER.`,
-			},
 		},
 	},
 	"DELETE": {
@@ -560,13 +536,6 @@ place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 			"/FF": {
 				Description: `  Specifies that a form feed is placed between messages in the file.`,
 			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Controls whether a  header containing the owner, subject,  and date of
-  the  message is  written in  the  file. The  default is  to write  the
-  header.`,
-			},
 			"/NEW": {
 				Description: `  Specifies  that  a new  file  is  to  be  created. Otherwise,  if  the
   specified file exists, the file would be appended to that file.`,
@@ -631,10 +600,6 @@ where one left off after one has read a message.
 				Description: `  If specified,  causes the listing  to be reinitialized and  start from
   the first folder.`,
 			},
-			"/SUBSCRIBE": {
-				Description: `  If  specified,  lists  only  those   news  folders  which  have  been
-  subscribed to.`,
-			},
 		},
 	},
 	"LAST": {
@@ -642,18 +607,12 @@ where one left off after one has read a message.
 
   Format:
     LAST`,
+		Action: ActionLast,
 		Flags: dclish.Flags{
 			"/EDIT": {
 				Description: `  Specifies that the editor  is to be used to read  the message. This is
   useful for scanning a long message.`,
 			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Specifies that if  a message header exists, the header  will be shown.
-  If /HEADER or  /NOHEADER is specified, the setting will  apply for all
-  further reads in the selected folder. The default is /HEADER.`,
-			},
 		},
 	},
 	"MAIL": {
@@ -674,13 +633,6 @@ specified as xxx%"""address""".`,
 			"/EDIT": {
 				Description: `  Specifies that  the editor is  to be used  to edit the  message before
   mailing it.`,
-			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Controls whether a  header containing the owner, subject,  and date of
-  the  message is  written in  the  mail. The  default is  to write  the
-  header.`,
 			},
 			"/SUBJECT": {
 				Description: `/SUBJECT=text
@@ -768,6 +720,7 @@ The key words  CURRENT and LAST can  also be specified in  the range in,
 place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`,
 		MinArgs: 1,
 		MaxArgs: 2,
+		Action:  ActionMove,
 		Flags: dclish.Flags{
 			"/ALL": {
 				Description: `  Specifies to move  all the messages from the old  folder. Note: If the
@@ -797,13 +750,6 @@ you would like to skip over.`,
 				Description: `  Specifies that the editor  is to be used to read  the message. This is
   useful for scanning a long message.`,
 			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Specifies that if  a message header exists, the header  will be shown.
-  If /HEADER or  /NOHEADER is specified, the setting will  apply for all
-  further reads in the selected folder. The default is /HEADER.`,
-			},
 		},
 	},
 	"PRINT": {
@@ -844,12 +790,6 @@ it's subject line, DIRECTORY/PRINT/SUBJ would allow you do it.`,
   to have  your job  print, the  system manager  should stop  the queue,
   physically change  the paper stock  on the output device,  and restart
   the queue specifying the new form type as the mounted form.)`,
-			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Controls whether a header containing the owner, subject, and date of the
-  message is printed at the beginning. The default is to write the header.`,
 			},
 			"/NOTIFY": {
 				Description: `/[NO]NOTIFY
@@ -904,13 +844,6 @@ the help on the SEEN command.`,
 			"/EDIT": {
 				Description: `  Specifies that the editor  is to be used to read  the message. This is
   useful for scanning a long message.`,
-			},
-			"/HEADER": {
-				Description: `/[NO]HEADER
-
-  Specifies that if  a message header exists, the header  will be shown.
-  If /HEADER or  /NOHEADER is specified, the setting will  apply for all
-  further reads in the selected folder. The default is /HEADER.`,
 			},
 			"/MARKED": {
 				Description: `  Specifies to read only messages that have been marked (marked messages
@@ -1263,12 +1196,14 @@ sure they are read.
 
   Format:
     SET ALWAYS`,
+				Action: ActionSetAlways,
 			},
 			"NOALWAYS": {
 				Description: `Removes ALWAYS attribute from the selected folder.
 
   Format:
     SET NOALWAYS`,
+				Action: ActionSetAlways,
 			},
 			"BRIEF": {
 				Description: `Controls whether you will be alerted upon logging  that  there  are  new
@@ -1281,6 +1216,7 @@ READNEW setting (and visa versa).
 
   Format:
     SET BRIEF`,
+				Action: ActionSetBrief,
 				Flags: dclish.Flags{
 					"/ALL": {
 						Description: `  Specifies that the  SET BRIEF option is the default  for all users for
@@ -1306,6 +1242,7 @@ privileged qualifier.`,
 
   Format:
     SET NOBRIEF`,
+				Action: ActionSetBrief,
 				Flags: dclish.Flags{
 					"/ALL": {
 						Description: `  Specifies that the SET NOBRIEF option is the default for all users for
@@ -1385,6 +1322,7 @@ In a cluster, if the logical name MAIL$SYSTEM_FLAGS is defined so that
 bit 1 is set, users will be notified no matter which node they are logged
 in to.  If you wish to disable this, you should define BULL_SYSTEM_FLAGS
 so that bit 1 is cleared.`,
+				Action: ActionSetNotify,
 				Flags: dclish.Flags{
 					"/ALL": {
 						Description: `  Specifies that the SET NOTIFY option  is the default for all users for
@@ -1410,6 +1348,7 @@ so that bit 1 is cleared.`,
 
   Format:
     SET NONOTIFY [folder-name]`,
+				Action:  ActionSetNonotify,
 				MaxArgs: 1,
 			},
 			"PRIVILEGES": {
@@ -1560,14 +1499,21 @@ is allowed to have SYSTEM and SHUTDOWN messages added to it.  This is a
 privileged command.
 
   Format:
-    SET [NO]SYSTEM
+    SET SYSTEM
 
 By default, the GENERAL folder is a SYSTEM folder, and the setting for
-that folder cannot be removed.
+that folder cannot be removed.`,
+				Action: ActionSetSystem,
+			},
+			"NOSYSTEM": {
+				Description: `Specifies that the selected folder is not a SYSTEM folder.
 
-If the selected folder is remote, /SYSTEM cannot be specified unless the
-folder at the other node is also a SYSTEM folder.
-`,
+  Format:
+    SET NOSYSTEM
+
+By default, the GENERAL folder is a SYSTEM folder, and the setting for
+that folder cannot be removed.`,
+				Action: ActionSetNosystem,
 			},
 		},
 	},
@@ -1654,7 +1600,7 @@ have done this.`,
   Specifies to display  only those users whose latest  read message date
   is the  same date  or later  than the  specified date.  If no  date is
   specified, the  date of the  current message  is used. Only  valid for
-  folders or with /LOGIN. Use /START for newsgroups.`,
+  folders or with /LOGIN.`,
 					},
 				},
 			},
diff --git a/repl/messages.go b/repl/messages.go
index b0cd69c41a44059972f2113a81102da2856eff90..6388862956756ecc5190c5044b34ec6f1e8bd501 100644
--- a/repl/messages.go
+++ b/repl/messages.go
@@ -200,6 +200,17 @@ func ActionFirst(_ *dclish.Command) error {
 	return nil
 }
 
+// ActionLast handles the `LAST` command.
+func ActionLast(_ *dclish.Command) error {
+	msgid := folders.LastMessage(this.Folder.Name)
+	if msgid == 0 {
+		fmt.Println("No messages in folder")
+		return nil
+	}
+	this.MsgID = msgid
+	return nil
+}
+
 // ActionNext handles the `NEXT` command.
 func ActionNext(_ *dclish.Command) error {
 	// TODO: handle flags.
@@ -219,6 +230,31 @@ func ActionNext(_ *dclish.Command) error {
 	return nil
 }
 
+// ActionPrint handles the `PRINT` command.
+func ActionPrint(cmd *dclish.Command) error {
+	// TODO: handle flags.
+	msgids := []int64{this.MsgID}
+	if len(cmd.Args) == 1 {
+		var err error
+		msgids, err = ParseNumberList(cmd.Args[0])
+		if err != nil {
+			return err
+		}
+	}
+	print("\033[5i")
+	for _, msgid := range msgids {
+		msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+		if err != nil {
+			fmt.Printf("Message %d not found.\n")
+		} else {
+			fmt.Print(msg.String())
+		}
+		print("\n\v")
+	}
+	print("\033[4i")
+	return nil
+}
+
 // ActionRead handles the `READ` command.
 func ActionRead(cmd *dclish.Command) error {
 	// TODO: handle flags.
@@ -234,11 +270,11 @@ func ActionRead(cmd *dclish.Command) error {
 	if err != nil {
 		return err
 	}
-	// TODO: pager needs to report if the whole message was read
-	// and only increment if not.
-	pager.Pager(msg.String())
-	msgid = folders.NextMsgid(this.User.Login, this.Folder.Name, msgid)
-	this.MsgID = max(this.MsgID, msgid)
+	if pager.Pager(msg.String()) {
+		folders.MarkSeen([]int64{msgid})
+		msgid = folders.NextMsgid(this.User.Login, this.Folder.Name, msgid)
+		this.MsgID = max(this.MsgID, msgid)
+	}
 	return nil
 }
 
diff --git a/repl/msg-text.go b/repl/msg-text.go
new file mode 100644
index 0000000000000000000000000000000000000000..029ef275a8d714b74ca52ad49ea5430b832d0b2a
--- /dev/null
+++ b/repl/msg-text.go
@@ -0,0 +1,8 @@
+package repl
+
+import "strings"
+
+func quote(content string) string {
+	lines := strings.Split(content, "\n")
+	return "> " + strings.Join(lines, "\n> ")
+}
diff --git a/repl/repl.go b/repl/repl.go
index 88173b268c5446d3887f480436bfb2444b4c8b63..6f3e2363e3670d5c5c7ea924000b303d011f84dd 100644
--- a/repl/repl.go
+++ b/repl/repl.go
@@ -34,8 +34,10 @@ func Loop() error {
 	// TODO: Remove once commands are implemented.
 	unimplemented := 0
 	total := len(commands)
+	fmt.Print("Missing")
 	for c := range commands {
 		if commands[c].Action == nil {
+			fmt.Printf(" [%s]", c)
 			unimplemented++
 		}
 		if len(commands[c].Commands) > 0 {
@@ -43,13 +45,14 @@ func Loop() error {
 			unimplemented--
 			for subc := range commands[c].Commands {
 				if commands[c].Commands[subc].Action == nil {
+					fmt.Printf(" [%s %s]", c, subc)
 					unimplemented++
 				}
 			}
 			total += len(commands[c].Commands)
 		}
 	}
-	fmt.Printf("TODO: %d out of %d commands still to be implemented.\n",
+	fmt.Printf("\nTODO: %d out of %d commands still to be implemented.\n",
 		unimplemented, total)
 	// TODO: END
 
diff --git a/repl/set.go b/repl/set.go
index b72e0b30c26fe497fdbc5fb06fbe6f00ff75dcab..f8e078c672ac7ec0ec44f506f35158205fa2ebec 100644
--- a/repl/set.go
+++ b/repl/set.go
@@ -8,6 +8,7 @@ import (
 
 	"git.lyda.ie/kevin/bulletin/dclish"
 	"git.lyda.ie/kevin/bulletin/folders"
+	"git.lyda.ie/kevin/bulletin/storage"
 	"git.lyda.ie/kevin/bulletin/this"
 )
 
@@ -19,25 +20,43 @@ func ActionSetAccess(_ *dclish.Command) error {
 
 // ActionSetAlways handles the `SET ALWAYS` command.
 func ActionSetAlways(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetAlways.")
+	ctx := storage.Context()
+	this.Q.UpdateFolderAlways(ctx, storage.UpdateFolderAlwaysParams{
+		Always: 1,
+		Name:   this.Folder.Name,
+	})
 	return nil
 }
 
 // ActionSetNoalways handles the `SET NOALWAYS` command.
 func ActionSetNoalways(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetNoalways.")
+	ctx := storage.Context()
+	this.Q.UpdateFolderAlways(ctx, storage.UpdateFolderAlwaysParams{
+		Always: 0,
+		Name:   this.Folder.Name,
+	})
 	return nil
 }
 
 // ActionSetBrief handles the `SET BRIEF` command.
 func ActionSetBrief(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetBrief.")
+	// TODO: parse flags.
+	ctx := storage.Context()
+	this.Q.UpdateFolderBrief(ctx, storage.UpdateFolderBriefParams{
+		Brief: 1,
+		Name:  this.Folder.Name,
+	})
 	return nil
 }
 
 // ActionSetNobrief handles the `SET NOBRIEF` command.
 func ActionSetNobrief(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetNobrief.")
+	// TODO: parse flags.
+	ctx := storage.Context()
+	this.Q.UpdateFolderBrief(ctx, storage.UpdateFolderBriefParams{
+		Brief: 1,
+		Name:  this.Folder.Name,
+	})
 	return nil
 }
 
@@ -79,13 +98,23 @@ func ActionSetFolder(cmd *dclish.Command) error {
 
 // ActionSetNotify handles the `SET NOTIFY` command.
 func ActionSetNotify(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetNotify.")
+	// TODO: parse flags and args.
+	ctx := storage.Context()
+	this.Q.UpdateFolderNotify(ctx, storage.UpdateFolderNotifyParams{
+		Notify: 1,
+		Name:   this.Folder.Name,
+	})
 	return nil
 }
 
 // ActionSetNonotify handles the `SET NONOTIFY` command.
 func ActionSetNonotify(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetNonotify.")
+	// TODO: parse flags and args.
+	ctx := storage.Context()
+	this.Q.UpdateFolderNotify(ctx, storage.UpdateFolderNotifyParams{
+		Notify: 0,
+		Name:   this.Folder.Name,
+	})
 	return nil
 }
 
@@ -163,6 +192,22 @@ func ActionSetNoShowNew(_ *dclish.Command) error {
 
 // ActionSetSystem handles the `SET SYSTEM` command.
 func ActionSetSystem(_ *dclish.Command) error {
-	fmt.Println("TODO: implement ActionSetSystem.")
+	// TODO: parse flags and args.
+	ctx := storage.Context()
+	this.Q.UpdateFolderSystem(ctx, storage.UpdateFolderSystemParams{
+		System: 1,
+		Name:   this.Folder.Name,
+	})
+	return nil
+}
+
+// ActionSetNosystem handles the `SET SYSTEM` command.
+func ActionSetNosystem(_ *dclish.Command) error {
+	// TODO: parse flags and args.
+	ctx := storage.Context()
+	this.Q.UpdateFolderSystem(ctx, storage.UpdateFolderSystemParams{
+		System: 1,
+		Name:   this.Folder.Name,
+	})
 	return nil
 }
diff --git a/repl/xfer.go b/repl/xfer.go
new file mode 100644
index 0000000000000000000000000000000000000000..c4c22542104e0ff160310a2af727827bb4bb216f
--- /dev/null
+++ b/repl/xfer.go
@@ -0,0 +1,53 @@
+// Package repl implements the main event loop.
+package repl
+
+import (
+	"fmt"
+
+	"git.lyda.ie/kevin/bulletin/dclish"
+	"git.lyda.ie/kevin/bulletin/this"
+)
+
+// ActionCopy handles the `COPY` command.
+func ActionCopy(cmd *dclish.Command) error {
+	// TODO: handle flags.
+	folder := cmd.Args[0]
+	msgids := []int64{this.MsgID}
+	if len(cmd.Args) == 2 {
+		var err error
+		msgids, err = ParseNumberList(cmd.Args[1])
+		if err != nil {
+			return err
+		}
+	}
+	fmt.Printf("TODO: copy %+v to %s\n", msgids, folder)
+	/*
+		msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+		if err != nil {
+			return err
+		}
+	*/
+	return nil
+}
+
+// ActionMove handles the `MOVE` command.
+func ActionMove(cmd *dclish.Command) error {
+	// TODO: handle flags.
+	folder := cmd.Args[0]
+	msgids := []int64{this.MsgID}
+	if len(cmd.Args) == 2 {
+		var err error
+		msgids, err = ParseNumberList(cmd.Args[1])
+		if err != nil {
+			return err
+		}
+	}
+	fmt.Printf("TODO: move %+v to %s\n", msgids, folder)
+	/*
+		msg, err := folders.ReadMessage(this.User.Login, this.Folder.Name, msgid)
+		if err != nil {
+			return err
+		}
+	*/
+	return nil
+}
diff --git a/storage/folders.sql.go b/storage/folders.sql.go
index 4666356abaa920dd5acd07f222d8d98e7c2952ba..7476fc84eb5a23ee0deaccb009f5d4abaf003895 100644
--- a/storage/folders.sql.go
+++ b/storage/folders.sql.go
@@ -226,3 +226,115 @@ func (q *Queries) ListFolderForAdmin(ctx context.Context) ([]ListFolderForAdminR
 	}
 	return items, nil
 }
+
+const updateFolderAlways = `-- name: UpdateFolderAlways :exec
+UPDATE folders SET always = ? WHERE name = ?
+`
+
+type UpdateFolderAlwaysParams struct {
+	Always int64
+	Name   string
+}
+
+func (q *Queries) UpdateFolderAlways(ctx context.Context, arg UpdateFolderAlwaysParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderAlways, arg.Always, arg.Name)
+	return err
+}
+
+const updateFolderBrief = `-- name: UpdateFolderBrief :exec
+UPDATE folders SET brief = ? WHERE name = ?
+`
+
+type UpdateFolderBriefParams struct {
+	Brief int64
+	Name  string
+}
+
+func (q *Queries) UpdateFolderBrief(ctx context.Context, arg UpdateFolderBriefParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderBrief, arg.Brief, arg.Name)
+	return err
+}
+
+const updateFolderExpire = `-- name: UpdateFolderExpire :exec
+UPDATE folders SET expire = ? WHERE name = ?
+`
+
+type UpdateFolderExpireParams struct {
+	Expire int64
+	Name   string
+}
+
+func (q *Queries) UpdateFolderExpire(ctx context.Context, arg UpdateFolderExpireParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderExpire, arg.Expire, arg.Name)
+	return err
+}
+
+const updateFolderNotify = `-- name: UpdateFolderNotify :exec
+UPDATE folders SET notify = ? WHERE name = ?
+`
+
+type UpdateFolderNotifyParams struct {
+	Notify int64
+	Name   string
+}
+
+func (q *Queries) UpdateFolderNotify(ctx context.Context, arg UpdateFolderNotifyParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderNotify, arg.Notify, arg.Name)
+	return err
+}
+
+const updateFolderReadnew = `-- name: UpdateFolderReadnew :exec
+UPDATE folders SET readnew = ? WHERE name = ?
+`
+
+type UpdateFolderReadnewParams struct {
+	Readnew int64
+	Name    string
+}
+
+func (q *Queries) UpdateFolderReadnew(ctx context.Context, arg UpdateFolderReadnewParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderReadnew, arg.Readnew, arg.Name)
+	return err
+}
+
+const updateFolderShownew = `-- name: UpdateFolderShownew :exec
+UPDATE folders SET shownew = ? WHERE name = ?
+`
+
+type UpdateFolderShownewParams struct {
+	Shownew int64
+	Name    string
+}
+
+func (q *Queries) UpdateFolderShownew(ctx context.Context, arg UpdateFolderShownewParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderShownew, arg.Shownew, arg.Name)
+	return err
+}
+
+const updateFolderSystem = `-- name: UpdateFolderSystem :exec
+UPDATE folders SET system = ? WHERE name = ?
+`
+
+type UpdateFolderSystemParams struct {
+	System int64
+	Name   string
+}
+
+func (q *Queries) UpdateFolderSystem(ctx context.Context, arg UpdateFolderSystemParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderSystem, arg.System, arg.Name)
+	return err
+}
+
+const updateFolderVisibility = `-- name: UpdateFolderVisibility :exec
+UPDATE folders SET visibility = ? WHERE name = ?
+`
+
+type UpdateFolderVisibilityParams struct {
+	Visibility int64
+	Name       string
+}
+
+func (q *Queries) UpdateFolderVisibility(ctx context.Context, arg UpdateFolderVisibilityParams) error {
+	_, err := q.db.ExecContext(ctx, updateFolderVisibility, arg.Visibility, arg.Name)
+	return err
+}
diff --git a/storage/messages.sql.go b/storage/messages.sql.go
index 9f51c306905db459aa4606b08bdf1cf2121aff58..bdec2bb9fe67e29f4b51dd4b9dd507bc4779729f 100644
--- a/storage/messages.sql.go
+++ b/storage/messages.sql.go
@@ -50,6 +50,17 @@ func (q *Queries) DeleteAllMessages(ctx context.Context, folder string) error {
 	return err
 }
 
+const lastMsgidIgnoringSeen = `-- name: LastMsgidIgnoringSeen :one
+SELECT CAST(MAX(id) AS INT) FROM messages AS m WHERE m.folder = ?1
+`
+
+func (q *Queries) LastMsgidIgnoringSeen(ctx context.Context, folder string) (int64, error) {
+	row := q.db.QueryRowContext(ctx, lastMsgidIgnoringSeen, folder)
+	var column_1 int64
+	err := row.Scan(&column_1)
+	return column_1, err
+}
+
 const nextMsgid = `-- name: NextMsgid :one
 SELECT CAST(COALESCE(MIN(id), 0) AS INT) FROM messages AS m
   WHERE m.folder = ?1 AND m.id > ?2
diff --git a/storage/queries/folders.sql b/storage/queries/folders.sql
index da30c3f92c19c57c05d9420d7c9daf9f821196f9..3c5f8a26b8c9ebb4304d3eb55853e83e25d793f9 100644
--- a/storage/queries/folders.sql
+++ b/storage/queries/folders.sql
@@ -38,3 +38,27 @@ SELECT 1 FROM owners WHERE folder = ? AND login = ?;
 
 -- name: GetFolderExpire :one
 SELECT expire FROM folders WHERE name = ?;
+
+-- name: UpdateFolderAlways :exec
+UPDATE folders SET always = ? WHERE name = ?;
+
+-- name: UpdateFolderSystem :exec
+UPDATE folders SET system = ? WHERE name = ?;
+
+-- name: UpdateFolderBrief :exec
+UPDATE folders SET brief = ? WHERE name = ?;
+
+-- name: UpdateFolderNotify :exec
+UPDATE folders SET notify = ? WHERE name = ?;
+
+-- name: UpdateFolderReadnew :exec
+UPDATE folders SET readnew = ? WHERE name = ?;
+
+-- name: UpdateFolderShownew :exec
+UPDATE folders SET shownew = ? WHERE name = ?;
+
+-- name: UpdateFolderVisibility :exec
+UPDATE folders SET visibility = ? WHERE name = ?;
+
+-- name: UpdateFolderExpire :exec
+UPDATE folders SET expire = ? WHERE name = ?;
diff --git a/storage/queries/messages.sql b/storage/queries/messages.sql
index 7750b8fab03e6357f58c975307444aaa3960dea8..e9bd74d0daadec4096f9a000e73977affb3a744e 100644
--- a/storage/queries/messages.sql
+++ b/storage/queries/messages.sql
@@ -34,3 +34,6 @@ SELECT CAST(MAX(id) AS INT) FROM messages AS m
 
 -- name: DeleteAllMessages :exec
 DELETE FROM messages WHERE folder = ?;
+
+-- name: LastMsgidIgnoringSeen :one
+SELECT CAST(MAX(id) AS INT) FROM messages AS m WHERE m.folder = ?1;
diff --git a/this/this.go b/this/this.go
index 22a64268c981af8fa0e67e84b1ed8f912d2fa1e6..e7588d9dec06fd239876c2ff5b3847af4163292e 100644
--- a/this/this.go
+++ b/this/this.go
@@ -89,6 +89,5 @@ func StartThis(login, name string) error {
 		})
 	}
 
-	fmt.Printf("User: %s\nFolder: %s\nMsgID: %d\n", User, Folder.Name, MsgID)
 	return nil
 }