diff --git a/lib/spack/spack/cmd/common/arguments.py b/lib/spack/spack/cmd/common/arguments.py
index ade6844813926aa06db886d95e2750725c32979f..d5bd4bb7112c654b11b0939957814e4cb4d02211 100644
--- a/lib/spack/spack/cmd/common/arguments.py
+++ b/lib/spack/spack/cmd/common/arguments.py
@@ -46,19 +46,25 @@ class ConstraintAction(argparse.Action):
     """Constructs a list of specs based on a constraint given on the command line
 
     An instance of this class is supposed to be used as an argument action
-    in a parser. It will read a constraint and will attach a list of matching
-    specs to the namespace
+    in a parser. It will read a constraint and will attach a function to the
+    arguments that accepts optional keyword arguments.
+
+    To obtain the specs from a command the function must be called.
     """
-    qualifiers = {}
 
     def __call__(self, parser, namespace, values, option_string=None):
         # Query specs from command line
-        d = self.qualifiers.get(namespace.subparser_name, {})
-        specs = [s for s in spack.store.db.query(**d)]
-        values = ' '.join(values)
+        self.values = values
+        namespace.contraint = values
+        namespace.specs = self._specs
+
+    def _specs(self, **kwargs):
+        specs = [s for s in spack.store.db.query(**kwargs)]
+        values = ' '.join(self.values)
         if values:
             specs = [x for x in specs if x.satisfies(values, strict=True)]
-        namespace.specs = specs
+        return specs
+
 
 _arguments['constraint'] = Args(
     'constraint', nargs='*', action=ConstraintAction,
diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py
index 50e61124860e2ab2c167bcc8418541fda7671709..29bf263f51fd5f9f6a579cbc75aace0bd19f8f15 100644
--- a/lib/spack/spack/cmd/find.py
+++ b/lib/spack/spack/cmd/find.py
@@ -22,16 +22,11 @@
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
-import argparse
 import sys
 
 import llnl.util.tty as tty
-import spack
-import spack.spec
-import spack.store
-from llnl.util.lang import *
-from llnl.util.tty.colify import *
-from llnl.util.tty.color import *
+import spack.cmd.common.arguments as arguments
+
 from spack.cmd import display_specs
 
 description = "Find installed spack packages"
@@ -43,6 +38,7 @@ def setup_parser(subparser):
                               action='store_const',
                               dest='mode',
                               const='short',
+                              default='short',
                               help='Show only specs (default)')
     format_group.add_argument('-p', '--paths',
                               action='store_const',
@@ -68,12 +64,12 @@ def setup_parser(subparser):
                            action='store_true',
                            dest='show_flags',
                            help='Show spec compiler flags.')
-
-    subparser.add_argument(
+    implicit_explicit = subparser.add_mutually_exclusive_group()
+    implicit_explicit.add_argument(
         '-e', '--explicit',
         action='store_true',
         help='Show only specs that were installed explicitly')
-    subparser.add_argument(
+    implicit_explicit.add_argument(
         '-E', '--implicit',
         action='store_true',
         help='Show only specs that were installed as dependencies')
@@ -100,17 +96,10 @@ def setup_parser(subparser):
                            action='store_true',
                            help='Show fully qualified package names.')
 
-    subparser.add_argument('query_specs',
-                           nargs=argparse.REMAINDER,
-                           help='optional specs to filter results')
+    arguments.add_common_arguments(subparser, ['constraint'])
 
 
 def query_arguments(args):
-    # Check arguments
-    if args.explicit and args.implicit:
-        tty.error('You can\'t pass -E and -e options simultaneously.')
-        raise SystemExit(1)
-
     # Set up query arguments.
     installed, known = True, any
     if args.only_missing:
@@ -129,35 +118,17 @@ def query_arguments(args):
 
 
 def find(parser, args):
-    # Filter out specs that don't exist.
-    query_specs = spack.cmd.parse_specs(args.query_specs)
-    query_specs, nonexisting = partition_list(
-        query_specs, lambda s: spack.repo.exists(s.name) or not s.name)
-
-    if nonexisting:
-        msg = "No such package%s: " % ('s' if len(nonexisting) > 1 else '')
-        msg += ", ".join(s.name for s in nonexisting)
-        tty.msg(msg)
-
-        if not query_specs:
-            return
-
     q_args = query_arguments(args)
-
-    # Get all the specs the user asked for
+    query_specs = args.specs(**q_args)
+    # Exit early if no package matches the constraint
     if not query_specs:
-        specs = set(spack.store.db.query(**q_args))
-    else:
-        results = [set(spack.store.db.query(qs, **q_args))
-                   for qs in query_specs]
-        specs = set.union(*results)
-
-    if not args.mode:
-        args.mode = 'short'
-
+        msg = "No package matches the query: {0}".format(args.contraint)
+        tty.msg(msg)
+        return
+    # Display the result
     if sys.stdout.isatty():
-        tty.msg("%d installed packages." % len(specs))
-    display_specs(specs,
+        tty.msg("%d installed packages." % len(query_specs))
+    display_specs(query_specs,
                   mode=args.mode,
                   long=args.long,
                   very_long=args.very_long,
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
index d7abe0fa871ece117e0a4bde616ddfd3d625f686..31460b312441eb8618841423871d9384882f4247 100644
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -244,17 +244,17 @@ def module(parser, args):
             'known': True
         },
     }
-    arguments.ConstraintAction.qualifiers.update(constraint_qualifiers)
-
+    query_args = constraint_qualifiers.get(args.subparser_name, {})
+    specs = args.specs(**query_args)
     module_type = args.module_type
     constraint = args.constraint
     try:
-        callbacks[args.subparser_name](module_type, args.specs, args)
+        callbacks[args.subparser_name](module_type, specs, args)
     except MultipleMatches:
         message = ('the constraint \'{query}\' matches multiple packages, '
                    'and this is not allowed in this context')
         tty.error(message.format(query=constraint))
-        for s in args.specs:
+        for s in specs:
             sys.stderr.write(s.format(color=True) + '\n')
         raise SystemExit(1)
     except NoMatch:
diff --git a/lib/spack/spack/test/cmd/find.py b/lib/spack/spack/test/cmd/find.py
index fa82db7733789fb933f851ea00fe6f8c53cd5730..4788da8ec6b5d8ee50d2e798b1255686fe64cf56 100644
--- a/lib/spack/spack/test/cmd/find.py
+++ b/lib/spack/spack/test/cmd/find.py
@@ -52,5 +52,3 @@ def test_query_arguments(self):
         args.implicit = True
         q_args = query_arguments(args)
         self.assertEqual(q_args['explicit'], False)
-        args.explicit = True
-        self.assertRaises(SystemExit, query_arguments, args)
diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py
index 3a0ce32e6cb070a6fe969a4cff71c1c8b4ca2b9c..39f9c5649fc8734b41e6b1feb45d6181197b4cd6 100644
--- a/lib/spack/spack/test/cmd/module.py
+++ b/lib/spack/spack/test/cmd/module.py
@@ -34,7 +34,7 @@ class TestModule(spack.test.mock_database.MockDatabase):
 
     def _get_module_files(self, args):
         return [modules.module_types[args.module_type](spec).file_name
-                for spec in args.specs]
+                for spec in args.specs()]
 
     def test_module_common_operations(self):
         parser = argparse.ArgumentParser()