Added plugin support to the cli
diff --git a/docs/cli.rst b/docs/cli.rst
index 5af0cf8836..d1b0850d64 100644
--- a/docs/cli.rst
+++ b/docs/cli.rst
@@ -214,3 +214,37 @@ step.
     Whenever click now needs to operate on a Flask application it will
     call that function with the script info and ask for it to be created.
 4.  All is rounded up by invoking the script.
+
+CLI Plugins
+-----------
+
+Flask extensions can always patch the `Flask.cli` instance with more
+commands if they want.  However there is a second way to add CLI plugins
+to Flask which is through `setuptools`.  If you make a Python package that
+should export a Flask command line plugin you can ship a `setup.py` file
+that declares an entrypoint that points to a click command:
+
+Example `setup.py`::
+
+    from setuptools import setup
+
+    setup(
+        name='flask-my-extension',
+        ...
+        entry_points='''
+            [flask.commands]
+            my-command=mypackage.commands:cli
+        ''',
+    )
+
+Inside `mypackage/comamnds.py` you can then export a Click object::
+
+    import click
+
+    @click.command()
+    def cli():
+        """This is an example command."""
+
+Once that package is installed in the same virtualenv as Flask itself you
+can run ``flask my-command`` to invoke your command.  This is useful to
+provide extra functionality that Flask itself cannot ship.
diff --git a/flask/cli.py b/flask/cli.py
index 6bd9398b9d..b94e931722 100644
--- a/flask/cli.py
+++ b/flask/cli.py
@@ -282,7 +282,24 @@ def __init__(self, add_default_commands=True, create_app=None, **extra):
             self.add_command(run_command)
             self.add_command(shell_command)
 
+        self._loaded_plugin_commands = False
+
+    def _load_plugin_commands(self):
+        if self._loaded_plugin_commands:
+            return
+        try:
+            import pkg_resources
+        except ImportError:
+            self._loaded_plugin_commands = True
+            return
+
+        for ep in pkg_resources.iter_entry_points('flask.commands'):
+            self.add_command(ep.load(), ep.name)
+        self._loaded_plugin_commands = True
+
     def get_command(self, ctx, name):
+        self._load_plugin_commands()
+
         # We load built-in commands first as these should always be the
         # same no matter what the app does.  If the app does want to
         # override this it needs to make a custom instance of this group
@@ -303,6 +320,8 @@ def get_command(self, ctx, name):
             pass
 
     def list_commands(self, ctx):
+        self._load_plugin_commands()
+
         # The commands available is the list of both the application (if
         # available) plus the builtin commands.
         rv = set(click.Group.list_commands(self, ctx))

This fixes #1776
