diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index 0f17c90cce..5dafeaf3c4 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -55,6 +55,7 @@ public abstract class PlayerList {
     public PlayerList(MinecraftServer minecraftserver) {
         minecraftserver.server = new CraftServer(minecraftserver, this);
         minecraftserver.console = org.bukkit.craftbukkit.command.ColouredConsoleSender.getInstance();
+        minecraftserver.reader.addCompleter(new org.bukkit.craftbukkit.command.ConsoleCommandCompleter(minecraftserver.server));
         this.cserver = minecraftserver.server;
         // CraftBukkit end
 
diff --git a/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
new file mode 100644
index 0000000000..7ef5772719
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/command/ConsoleCommandCompleter.java
@@ -0,0 +1,47 @@
+package org.bukkit.craftbukkit.command;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.Level;
+
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.craftbukkit.util.Waitable;
+
+import jline.console.completer.Completer;
+
+public class ConsoleCommandCompleter implements Completer {
+    private final CraftServer server;
+
+    public ConsoleCommandCompleter(CraftServer server) {
+        this.server = server;
+    }
+
+    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
+        Waitable<List<String>> waitable = new Waitable<List<String>>() {
+            @Override
+            protected List<String> evaluate() {
+                return server.getCommandMap().tabComplete(server.getConsoleSender(), buffer);
+            }
+        };
+        this.server.getServer().processQueue.add(waitable);
+        try {
+            List<String> offers = waitable.get();
+            if (offers == null) {
+                return cursor;
+            }
+            candidates.addAll(offers);
+
+            final int lastSpace = buffer.lastIndexOf(' ');
+            if (lastSpace == -1) {
+                return cursor - buffer.length();
+            } else {
+                return cursor - (buffer.length() - lastSpace - 1);
+            }
+        } catch (ExecutionException e) {
+            this.server.getLogger().log(Level.WARNING, "Unhandled exception when tab completing", e);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+        return cursor;
+    }
+}