diff --git a/README.md b/README.md
index ad580115223f10535af040245928e7f8892609c5..1de37fe8bcb3504530e5f1047e3c25983ba2b8cb 100644
--- a/README.md
+++ b/README.md
@@ -12,11 +12,12 @@ A Gitlab bot for Matrix. It uses
   * [x] View full commit messages
 	* [x] View commit diffs
 	* [x] View commit history
-* [ ] Issue management
+* [x] Issue management
 	* [x] Read issues
 	* [x] Create/close/reopen issues
-	* [ ] Read comments on issues
+	* [x] Read comments on issues
 	* [x] Comment on issues
+* [ ] Shorter commands
 
 ## Usage
 Configure the server by copying `example-config.json` to `config.json` and
diff --git a/commands.go b/commands.go
index 5d5edc9444b66994080efe7a328942bbe0d514fe..277aa19ed8a06e04aef9e0ce6023bec7a084538f 100644
--- a/commands.go
+++ b/commands.go
@@ -287,6 +287,49 @@ func commandCommentOnIssue(git *gitlab.Client, room *mautrix.Room, sender string
 	})
 }
 
+func commandReadIssueComments(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) {
+	if len(args) < 2 {
+		room.Send("Usage: !gitlab issue comments <repo> <issue id> [n] [page]")
+		return
+	}
+
+	issueID, err := strconv.Atoi(args[1])
+	if err != nil {
+		room.Sendf("Invalid issue ID: %s", args[1])
+	}
+
+	n := 5
+	page := 1
+	if len(args) > 2 {
+		n, _ = strconv.Atoi(args[2])
+		if len(args) > 3 {
+			page, _ = strconv.Atoi(args[3])
+		}
+	}
+
+	comments, resp, err := git.Notes.ListIssueNotes(args[0], issueID, &gitlab.ListIssueNotesOptions{
+		ListOptions: gitlab.ListOptions{
+			Page:    page,
+			PerPage: n,
+		},
+	})
+	if resp.StatusCode == 404 {
+		room.Sendf("Issue #%d or repository %s not found.", issueID, args[0])
+		return
+	} else if err != nil {
+		room.Sendf("Failed to read comments: %s", err)
+		return
+	}
+	var buf bytes.Buffer
+	for _, comment := range comments {
+		fmt.Fprintf(&buf, "%s at %s:<br/>\n<blockquote>%s</blockquote>",
+			comment.Author.Name,
+			comment.CreatedAt.Format("Jan _2, 2006 15:04:05"),
+			comment.Body)
+	}
+	room.SendHTML(buf.String())
+}
+
 func commandIssue(git *gitlab.Client, room *mautrix.Room, sender string, args []string, lines []string) {
 	if len(args) == 0 {
 		room.SendHTML("Unknown subcommand. Try <code>!gitlab help issue</code> for help.")
@@ -333,7 +376,10 @@ func commandIssue(git *gitlab.Client, room *mautrix.Room, sender string, args []
 		}
 	case "comment":
 		commandCommentOnIssue(git, room, sender, args, lines)
+	case "comments":
+		fallthrough
 	case "read-comments":
+		commandReadIssueComments(git, room, sender, args, lines)
 	default:
 		room.SendHTML("Unknown subcommand. Try <code>!gitlab help issue</code> for help.")
 	}