diff --git a/repl/command.go b/repl/command.go
index e048e30972271e3fa60fa46b074be9f5605f17b6..074fdcf18d4adac2b8fb6b5e4186d2e80108e5f4 100644
--- a/repl/command.go
+++ b/repl/command.go
@@ -1647,9 +1647,8 @@ have done this.`,
 						Description: `/FOLDER=[foldername]
 
   Specifies to display  the latest message that was read  by the user(s)
-  for the  specified foldername. A  newsgroup can be specified,  but the
-  info can only be shown if the user has subscribed to the newsgroup. If
-  the foldername is not specified, the selected folder will be used.`,
+  for the specified foldername.  If the foldername is not specified, the
+	selected folder will be used.`,
 					},
 					"/SINCE": {
 						Description: `/SINCE=[date]
diff --git a/repl/show.go b/repl/show.go
index 9448f7899089702de561e8cd21a9eae6211009ae..f800729579d7cf967be9bb0464051a9a5963e26f 100644
--- a/repl/show.go
+++ b/repl/show.go
@@ -115,8 +115,25 @@ func ActionShowPrivileges(_ *dclish.Command) error {
 }
 
 // ActionShowUser handles the `SHOW USER` command.
-func ActionShowUser(_ *dclish.Command) error {
+func ActionShowUser(cmd *dclish.Command) error {
+	showAll := false
+	if cmd.Flags["/ALL"].Value == "true" {
+		// TODO: Check permissions.
+		showAll = true
+	}
+	showLogin := false
+	if cmd.Flags["/LOGIN"].Value == "true" {
+		// TODO: Check permissions.
+		showLogin = true
+	}
+	folder := this.Folder
+	if cmd.Flags["/FOLDER"].Value != "" {
+		// TODO: Check permissions.
+		folder = folders.FindFolder(cmd.Flags["/FOLDER"].Value)
+	}
+	since := cmd.Flags["/FOLDER"].Value
 	fmt.Println("TODO: implement ActionShowUser.")
+	fmt.Printf("TODO: %t %t %s %s.\n", showAll, showLogin, folder.Name, since)
 	return nil
 }
 
diff --git a/storage/migrations/1_create_table.up.sql b/storage/migrations/1_create_table.up.sql
index 863515cede390c0d4325644d4c0f9189af93c5d9..b2de88bc767f00e431c11bc75a7f6cde00b5b151 100644
--- a/storage/migrations/1_create_table.up.sql
+++ b/storage/migrations/1_create_table.up.sql
@@ -121,12 +121,22 @@ CREATE TABLE messages (
 CREATE INDEX messages_idx_shutdown ON messages(shutdown);
 CREATE INDEX messages_idx_expiration ON messages(expiration);
 
+CREATE TRIGGER messages_after_update_update_at
+  AFTER UPDATE ON messages FOR EACH ROW
+    WHEN NEW.update_at = OLD.update_at    --- avoid infinite loop
+BEGIN
+  UPDATE messages SET update_at=CURRENT_TIMESTAMP
+    WHERE folder=NEW.folder AND id=NEW.id;
+END;
+
 CREATE TABLE seen (
   login       VARCHAR(25) REFERENCES users(login)
               ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
   folder      VARCHAR(25) REFERENCES folders(name)
               ON DELETE CASCADE ON UPDATE CASCADE NOT NULL,
   msgid       INT     NOT NULL,
+  create_at   TIMESTAMP    DEFAULT CURRENT_TIMESTAMP NOT NULL,
+  --- Nothing to update in this table.
   PRIMARY KEY (folder, login, msgid),
   CONSTRAINT read_fk_id_folder
     FOREIGN KEY (msgid, folder)
diff --git a/storage/models.go b/storage/models.go
index ea5558cbbd29ae33e95a32d67b078de035ec0138..d0089adc1fe00551e8cf670913831e6452707e33 100644
--- a/storage/models.go
+++ b/storage/models.go
@@ -62,9 +62,10 @@ type Owner struct {
 }
 
 type Seen struct {
-	Login  string
-	Folder string
-	Msgid  int64
+	Login    string
+	Folder   string
+	Msgid    int64
+	CreateAt time.Time
 }
 
 type System struct {
diff --git a/storage/standard.sql.go b/storage/standard.sql.go
index ffe19b2d4305b6f8575091f440407e50e9dd67f0..b192647d0836e26f743e4a245bbddcbbf3902d3a 100644
--- a/storage/standard.sql.go
+++ b/storage/standard.sql.go
@@ -376,7 +376,7 @@ func (q *Queries) GetOwners(ctx context.Context, folder string) ([]Owner, error)
 }
 
 const getSeen = `-- name: GetSeen :one
-SELECT login, folder, msgid FROM seen WHERE folder = ? AND login = ? AND msgid = ?
+SELECT login, folder, msgid, create_at FROM seen WHERE folder = ? AND login = ? AND msgid = ?
 `
 
 type GetSeenParams struct {
@@ -388,7 +388,12 @@ type GetSeenParams struct {
 func (q *Queries) GetSeen(ctx context.Context, arg GetSeenParams) (Seen, error) {
 	row := q.db.QueryRowContext(ctx, getSeen, arg.Folder, arg.Login, arg.Msgid)
 	var i Seen
-	err := row.Scan(&i.Login, &i.Folder, &i.Msgid)
+	err := row.Scan(
+		&i.Login,
+		&i.Folder,
+		&i.Msgid,
+		&i.CreateAt,
+	)
 	return i, err
 }
 
@@ -600,7 +605,7 @@ func (q *Queries) ListOwners(ctx context.Context) ([]Owner, error) {
 }
 
 const listSeen = `-- name: ListSeen :many
-SELECT login, folder, msgid FROM seen
+SELECT login, folder, msgid, create_at FROM seen
 `
 
 func (q *Queries) ListSeen(ctx context.Context) ([]Seen, error) {
@@ -612,7 +617,12 @@ func (q *Queries) ListSeen(ctx context.Context) ([]Seen, error) {
 	var items []Seen
 	for rows.Next() {
 		var i Seen
-		if err := rows.Scan(&i.Login, &i.Folder, &i.Msgid); err != nil {
+		if err := rows.Scan(
+			&i.Login,
+			&i.Folder,
+			&i.Msgid,
+			&i.CreateAt,
+		); err != nil {
 			return nil, err
 		}
 		items = append(items, i)