diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js b/app/assets/javascripts/discourse/controllers/topic_controller.js
index e77a672d606..1ea8ffabc32 100644
--- a/app/assets/javascripts/discourse/controllers/topic_controller.js
+++ b/app/assets/javascripts/discourse/controllers/topic_controller.js
@@ -49,6 +49,122 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
   },
 
   actions: {
+    // Post related methods
+    replyToPost: function(post) {
+      var composerController = this.get('controllers.composer'),
+          quoteController = this.get('controllers.quote-button'),
+          quotedText = Discourse.Quote.build(quoteController.get('post'), quoteController.get('buffer')),
+          topic = post ? post.get('topic') : this.get('model');
+
+      quoteController.set('buffer', '');
+
+      if (composerController.get('content.topic.id') === topic.get('id') &&
+          composerController.get('content.action') === Discourse.Composer.REPLY) {
+        composerController.set('content.post', post);
+        composerController.set('content.composeState', Discourse.Composer.OPEN);
+        composerController.appendText(quotedText);
+      } else {
+
+        var opts = {
+          action: Discourse.Composer.REPLY,
+          draftKey: topic.get('draft_key'),
+          draftSequence: topic.get('draft_sequence')
+        };
+
+        if(post && post.get("post_number") !== 1){
+          opts.post = post;
+        } else {
+          opts.topic = topic;
+        }
+
+        composerController.open(opts).then(function() {
+          composerController.appendText(quotedText);
+        });
+      }
+      return false;
+    },
+
+    likePost: function(post) {
+      var likeAction = post.get('actionByName.like');
+      if (likeAction && likeAction.get('can_act')) {
+        likeAction.act();
+      }
+    },
+
+    recoverPost: function(post) {
+      // Recovering the first post recovers the topic instead
+      if (post.get('post_number') === 1) {
+        this.recoverTopic();
+        return;
+      }
+      post.recover();
+    },
+
+    deletePost: function(post) {
+
+      // Deleting the first post deletes the topic
+      if (post.get('post_number') === 1) {
+        this.deleteTopic();
+        return;
+      }
+
+      var user = Discourse.User.current(),
+          replyCount = post.get('reply_count'),
+          self = this;
+
+      // If the user is staff and the post has replies, ask if they want to delete replies too.
+      if (user.get('staff') && replyCount > 0) {
+        bootbox.dialog(I18n.t("post.controls.delete_replies.confirm", {count: replyCount}), [
+          {label: I18n.t("cancel"),
+           'class': 'btn-danger rightg'},
+          {label: I18n.t("post.controls.delete_replies.no_value"),
+            callback: function() {
+              post.destroy(user);
+            }
+          },
+          {label: I18n.t("post.controls.delete_replies.yes_value"),
+           'class': 'btn-primary',
+            callback: function() {
+              Discourse.Post.deleteMany([post], [post]);
+              self.get('postStream.posts').forEach(function (p) {
+                if (p === post || p.get('reply_to_post_number') === post.get('post_number')) {
+                  p.setDeletedState(user);
+                }
+              });
+            }
+          }
+        ]);
+      } else {
+        post.destroy(user).then(null, function(e) {
+          post.undoDeleteState();
+          var response = $.parseJSON(e.responseText);
+          if (response && response.errors) {
+            bootbox.alert(response.errors[0]);
+          } else {
+            bootbox.alert(I18n.t('generic_error'));
+          }
+        });
+      }
+    },
+
+    editPost: function(post) {
+      this.get('controllers.composer').open({
+        post: post,
+        action: Discourse.Composer.EDIT,
+        draftKey: post.get('topic.draft_key'),
+        draftSequence: post.get('topic.draft_sequence')
+      });
+    },
+
+    toggleBookmark: function(post) {
+      if (!Discourse.User.current()) {
+        alert(I18n.t("bookmarks.not_bookmarked"));
+        return;
+      }
+      post.toggleProperty('bookmarked');
+      return false;
+    },
+
     jumpTop: function() {
       Discourse.URL.routeTo(this.get('firstPostUrl'));
     },
@@ -453,109 +569,11 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
     Discourse.MessageBus.unsubscribe('/topic/*');
   },
 
-  // Post related methods
-  replyToPost: function(post) {
-    var composerController = this.get('controllers.composer'),
-        quoteController = this.get('controllers.quote-button'),
-        quotedText = Discourse.Quote.build(quoteController.get('post'), quoteController.get('buffer')),
-        topic = post ? post.get('topic') : this.get('model');
-
-    quoteController.set('buffer', '');
-
-    if (composerController.get('content.topic.id') === topic.get('id') &&
-        composerController.get('content.action') === Discourse.Composer.REPLY) {
-      composerController.set('content.post', post);
-      composerController.set('content.composeState', Discourse.Composer.OPEN);
-      composerController.appendText(quotedText);
-    } else {
-
-      var opts = {
-        action: Discourse.Composer.REPLY,
-        draftKey: topic.get('draft_key'),
-        draftSequence: topic.get('draft_sequence')
-      };
-
-      if(post && post.get("post_number") !== 1){
-        opts.post = post;
-      } else {
-        opts.topic = topic;
-      }
-
-      composerController.open(opts).then(function() {
-        composerController.appendText(quotedText);
-      });
-    }
-    return false;
-  },
-
   // Topic related
   reply: function() {
     this.replyToPost();
   },
 
-  // Edits a post
-  editPost: function(post) {
-    this.get('controllers.composer').open({
-      post: post,
-      action: Discourse.Composer.EDIT,
-      draftKey: post.get('topic.draft_key'),
-      draftSequence: post.get('topic.draft_sequence')
-    });
-  },
-
-  toggleBookmark: function(post) {
-    if (!Discourse.User.current()) {
-      alert(I18n.t("bookmarks.not_bookmarked"));
-      return;
-    }
-    post.toggleProperty('bookmarked');
-    return false;
-  },
-
-  recoverPost: function(post) {
-    post.recover();
-  },
-
-  deletePost: function(post) {
-    var user = Discourse.User.current(),
-        replyCount = post.get('reply_count'),
-        self = this;
-
-    // If the user is staff and the post has replies, ask if they want to delete replies too.
-    if (user.get('staff') && replyCount > 0) {
-      bootbox.dialog(I18n.t("post.controls.delete_replies.confirm", {count: replyCount}), [
-        {label: I18n.t("cancel"),
-         'class': 'btn-danger rightg'},
-        {label: I18n.t("post.controls.delete_replies.no_value"),
-          callback: function() {
-            post.destroy(user);
-          }
-        },
-        {label: I18n.t("post.controls.delete_replies.yes_value"),
-         'class': 'btn-primary',
-          callback: function() {
-            Discourse.Post.deleteMany([post], [post]);
-            self.get('postStream.posts').forEach(function (p) {
-              if (p === post || p.get('reply_to_post_number') === post.get('post_number')) {
-                p.setDeletedState(user);
-              }
-            });
-          }
-        }
-      ]);
-    } else {
-      post.destroy(user).then(null, function(e) {
-        post.undoDeleteState();
-        var response = $.parseJSON(e.responseText);
-        if (response && response.errors) {
-          bootbox.alert(response.errors[0]);
-        } else {
-          bootbox.alert(I18n.t('generic_error'));
-        }
-      });
-    }
-  },
-
   performTogglePost: function(post) {
     var selectedPosts = this.get('selectedPosts');
     if (this.postSelected(post)) {
diff --git a/app/assets/javascripts/discourse/initializers/keyboard-shortcuts.js.es6 b/app/assets/javascripts/discourse/initializers/keyboard-shortcuts.js.es6
index 7cc8e63d295..5ae89cdf2c6 100644
--- a/app/assets/javascripts/discourse/initializers/keyboard-shortcuts.js.es6
+++ b/app/assets/javascripts/discourse/initializers/keyboard-shortcuts.js.es6
@@ -5,7 +5,7 @@
 **/
 export default {
   name: "keyboard-shortcuts",
-  initialize: function() {
-    Discourse.KeyboardShortcuts.bindEvents(Mousetrap);
+  initialize: function(container) {
+    Discourse.KeyboardShortcuts.bindEvents(Mousetrap, container);
   }
 };
diff --git a/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js b/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js
index 967220976e2..e1f1af80c1b 100644
--- a/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js
+++ b/app/assets/javascripts/discourse/lib/keyboard_shortcuts.js
@@ -16,27 +16,30 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
     'g t': '/top'
   },
 
+  SELECTED_POST_BINDINGS: {
+    'b': 'toggleBookmark',
+    'd': 'deletePost',
+    'e': 'editPost',
+    'l': 'likePost',
+    'r': 'replyToPost',
+    '!': 'showFlags'
+  },
+
   CLICK_BINDINGS: {
-    'b': '.topic-post.selected button.bookmark',                      // bookmark current post
     'c': '#create-topic',                                         // create new topic
-    'd': '.topic-post.selected button.delete',                        // delete selected post
-    'e': '.topic-post.selected button.edit',                          // edit selected post
 
     // star topic
     'f': '#topic-footer-buttons button.star, #topic-list tr.topic-list-item.selected a.star',
 
-    'l': '.topic-post.selected button.like',                          // like selected post
     'm m': 'div.notification-options li[data-id="0"] a',          // mark topic as muted
     'm r': 'div.notification-options li[data-id="1"] a',          // mark topic as regular
     'm t': 'div.notification-options li[data-id="2"] a',          // mark topic as tracking
     'm w': 'div.notification-options li[data-id="3"] a',          // mark topic as watching
     'n': '#user-notifications',                                   // open notifictions menu
-    'o,enter': '#topic-list tr.selected a.title', // open selected topic
-    'shift+r': '#topic-footer-buttons button.create',                   // reply to topic
-    'r': '.topic-post.selected button.create',                        // reply to selected post
-    'shift+s': '#topic-footer-buttons button.share',                    // share topic
-    's': '.topic-post.selected button.share',                         // share selected post
-    '!': '.topic-post.selected button.flag'                         // flag selected post
+    'o,enter': '#topic-list tr.selected a.title',                 // open selected topic
+    'shift+r': '#topic-footer-buttons button.create',             // reply to topic
+    'shift+s': '#topic-footer-buttons button.share',              // share topic
+    's': '.topic-post.selected a.post-date'                       // share post
   },
 
   FUNCTION_BINDINGS: {
@@ -54,10 +57,12 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
     'q': 'quoteReply'
   },
 
-  bindEvents: function(keyTrapper) {
+  bindEvents: function(keyTrapper, container) {
     this.keyTrapper = keyTrapper;
+    this.container = container;
     _.each(this.PATH_BINDINGS, this._bindToPath, this);
     _.each(this.CLICK_BINDINGS, this._bindToClick, this);
+    _.each(this.SELECTED_POST_BINDINGS, this._bindToSelectedPost, this);
     _.each(this.FUNCTION_BINDINGS, this._bindToFunction, this);
   },
 
@@ -79,7 +84,7 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
 
   _jumpTo: function(direction) {
     if ($('.container.posts').length) {
-      Discourse.__container__.lookup('controller:topic').send(direction);
+      this.container.lookup('controller:topic').send(direction);
     }
   },
 
@@ -136,6 +141,22 @@ Discourse.KeyboardShortcuts = Ember.Object.createWithMixins({
     Discourse.__container__.lookup('controller:application').send('showKeyboardShortcutsHelp');
   },
 
+  _bindToSelectedPost: function(action, binding) {
+    var container = this.container;
+
+    this.keyTrapper.bind(binding, function() {
+      // TODO: We should keep track of the post without a CSS class
+      var selectedPostId = parseInt($('.topic-post.selected article.boxed').data('post-id'), 10);
+      if (selectedPostId) {
+        var topicController = container.lookup('controller:topic'),
+            post = topicController.get('postStream.posts').findBy('id', selectedPostId);
+        if (post) {
+          topicController.send(action, post);
+        }
+      }
+    });
+  },
+
   _bindToPath: function(path, binding) {
     this.keyTrapper.bind(binding, function() {
       Discourse.URL.routeTo(path);
diff --git a/app/assets/javascripts/discourse/views/post-menu.js.es6 b/app/assets/javascripts/discourse/views/post-menu.js.es6
index f6f97046c4d..5a583cf52d9 100644
--- a/app/assets/javascripts/discourse/views/post-menu.js.es6
+++ b/app/assets/javascripts/discourse/views/post-menu.js.es6
@@ -73,7 +73,7 @@ export default Discourse.View.extend({
     var handler = this["click" + action.capitalize()];
     if (!handler) return;
 
-    handler.call(this);
+    handler.call(this, this.get('post'));
   },
 
   // Replies Button
@@ -109,7 +109,7 @@ export default Discourse.View.extend({
 
   // Delete button
   renderDelete: function(post, buffer) {
-    var label, action, icon;
+    var label, icon;
 
     if (post.get('post_number') === 1) {
       // If it's the first post, the delete/undo actions are related to the topic
@@ -117,12 +117,10 @@ export default Discourse.View.extend({
       if (topic.get('deleted_at')) {
         if (!topic.get('details.can_recover')) { return; }
         label = "topic.actions.recover";
-        action = "recoverTopic";
         icon = "undo";
       } else {
         if (!topic.get('details.can_delete')) { return; }
         label = "topic.actions.delete";
-        action = "deleteTopic";
         icon = "trash-o";
       }
 
@@ -131,35 +129,26 @@ export default Discourse.View.extend({
       if (post.get('deleted_at') || post.get('user_deleted')) {
         if (!post.get('can_recover')) { return; }
         label = "post.controls.undelete";
-        action = "recover";
         icon = "undo";
       } else {
         if (!post.get('can_delete')) { return; }
         label = "post.controls.delete";
-        action = "delete";
         icon = "trash-o";
       }
     }
 
+    var action = (icon === 'trash-o') ? 'delete' : 'recover';
     buffer.push("<button title=\"" +
                 I18n.t(label) +
                 "\" data-action=\"" + action + "\" class=\"delete\"><i class=\"fa fa-" + icon + "\"></i></button>");
   },
 
-  clickDeleteTopic: function() {
-    this.get('controller').deleteTopic();
+  clickRecover: function(post) {
+    this.get('controller').send('recoverPost', post);
   },
 
-  clickRecoverTopic: function() {
-    this.get('controller').recoverTopic();
-  },
-
-  clickRecover: function() {
-    this.get('controller').recoverPost(this.get('post'));
-  },
-
-  clickDelete: function() {
-    this.get('controller').deletePost(this.get('post'));
+  clickDelete: function(post) {
+    this.get('controller').send('deletePost', post);
   },
 
   // Like button
@@ -170,9 +159,8 @@ export default Discourse.View.extend({
                 "\" data-action=\"like\" class='like'><i class=\"fa fa-heart\"></i></button>");
   },
 
-  clickLike: function() {
-    var likeAction = this.get('post.actionByName.like');
-    if (likeAction) likeAction.act();
+  clickLike: function(post) {
+    this.get('controller').send('likePost', post);
   },
 
   // Flag button
@@ -183,8 +171,8 @@ export default Discourse.View.extend({
                 "\" data-action=\"flag\" class='flag'><i class=\"fa fa-flag\"></i></button>");
   },
 
-  clickFlag: function() {
-    this.get('controller').send('showFlags', this.get('post'));
+  clickFlag: function(post) {
+    this.get('controller').send('showFlags', post);
   },
 
   // Edit button
@@ -195,8 +183,8 @@ export default Discourse.View.extend({
                  "\" data-action=\"edit\" class='edit'><i class=\"fa fa-pencil\"></i></button>");
   },
 
-  clickEdit: function() {
-    this.get('controller').editPost(this.get('post'));
+  clickEdit: function(post) {
+    this.get('controller').send('editPost', post);
   },
 
   // Share button
@@ -216,8 +204,8 @@ export default Discourse.View.extend({
                  (I18n.t("topic.reply.title")) + "</span></button>");
   },
 
-  clickReply: function() {
-    this.get('controller').replyToPost(this.get('post'));
+  clickReply: function(post) {
+    this.get('controller').send('replyToPost', post);
   },
 
   // Bookmark button
@@ -242,8 +230,8 @@ export default Discourse.View.extend({
                 "'></div></button>");
   },
 
-  clickBookmark: function() {
-    this.get('post').toggleProperty('bookmarked');
+  clickBookmark: function(post) {
+    this.get('controller').send('toggleBookmark', post);
   },
 
   renderAdmin: function(post, buffer) {
diff --git a/test/javascripts/components/keyboard_shortcuts_component_test.js b/test/javascripts/components/keyboard_shortcuts_component_test.js
index 5d9efbbdb85..da84e58830f 100644
--- a/test/javascripts/components/keyboard_shortcuts_component_test.js
+++ b/test/javascripts/components/keyboard_shortcuts_component_test.js
@@ -25,13 +25,7 @@ module("Discourse.KeyboardShortcuts", {
 
     $("#qunit-fixture").html([
       "<article class='topic-post selected'>",
-      "  <button class='bookmark'></button>",
-      "  <button class='delete'></button>",
-      "  <button class='edit'></button>",
-      "  <button class='like'></button>",
-      "  <button class='create'></button>",
-      "  <button class='share'></button>",
-      "  <button class='flag'></button>",
+      "<a class='post-date'></a>" +
       "</article>",
       "<div class='notification-options'>",
       "  <ul>",