diff --git a/lib/spack/spack/cmd/__init__.py b/lib/spack/spack/cmd/__init__.py
index 672999159c01d25fa006c6c6a636328141f914a8..230115df50acaae15eb0623d60804cb7c96d0b87 100644
--- a/lib/spack/spack/cmd/__init__.py
+++ b/lib/spack/spack/cmd/__init__.py
@@ -27,16 +27,18 @@
 import sys
 
 import llnl.util.tty as tty
-from llnl.util.lang import attr_setdefault
-
 import spack
-import spack.spec
 import spack.config
+import spack.spec
+from llnl.util.lang import *
+from llnl.util.tty.colify import *
+from llnl.util.tty.color import *
 
 #
 # Settings for commands that modify configuration
 #
-# Commands that modify confguration By default modify the *highest* priority scope.
+# Commands that modify confguration By default modify the *highest*
+# priority scope.
 default_modify_scope = spack.config.highest_precedence_scope().name
 # Commands that list confguration list *all* scopes by default.
 default_list_scope = None
@@ -48,7 +50,7 @@
 ignore_files = r'^\.|^__init__.py$|^#'
 
 SETUP_PARSER = "setup_parser"
-DESCRIPTION  = "description"
+DESCRIPTION = "description"
 
 command_path = os.path.join(spack.lib_path, "spack", "cmd")
 
@@ -71,7 +73,7 @@ def get_module(name):
         module_name, fromlist=[name, SETUP_PARSER, DESCRIPTION],
         level=0)
 
-    attr_setdefault(module, SETUP_PARSER, lambda *args: None) # null-op
+    attr_setdefault(module, SETUP_PARSER, lambda *args: None)  # null-op
     attr_setdefault(module, DESCRIPTION, "")
 
     fn_name = get_cmd_function_name(name)
@@ -101,17 +103,17 @@ def parse_specs(args, **kwargs):
         specs = spack.spec.parse(args)
         for spec in specs:
             if concretize:
-                spec.concretize() # implies normalize
+                spec.concretize()  # implies normalize
             elif normalize:
                 spec.normalize()
 
         return specs
 
-    except spack.parse.ParseError, e:
+    except spack.parse.ParseError as e:
         tty.error(e.message, e.string, e.pos * " " + "^")
         sys.exit(1)
 
-    except spack.spec.SpecError, e:
+    except spack.spec.SpecError as e:
         tty.error(e.message)
         sys.exit(1)
 
@@ -127,7 +129,7 @@ def elide_list(line_list, max_num=10):
            [1, 2, 3, '...', 6]
     """
     if len(line_list) > max_num:
-        return line_list[:max_num-1] + ['...'] + line_list[-1:]
+        return line_list[:max_num - 1] + ['...'] + line_list[-1:]
     else:
         return line_list
 
@@ -138,10 +140,104 @@ def disambiguate_spec(spec):
         tty.die("Spec '%s' matches no installed packages." % spec)
 
     elif len(matching_specs) > 1:
-        args =  ["%s matches multiple packages." % spec,
-                 "Matching packages:"]
+        args = ["%s matches multiple packages." % spec,
+                "Matching packages:"]
         args += ["  " + str(s) for s in matching_specs]
         args += ["Use a more specific spec."]
         tty.die(*args)
 
     return matching_specs[0]
+
+
+def ask_for_confirmation(message):
+    while True:
+        tty.msg(message + '[y/n]')
+        choice = raw_input().lower()
+        if choice == 'y':
+            break
+        elif choice == 'n':
+            raise SystemExit('Operation aborted')
+        tty.warn('Please reply either "y" or "n"')
+
+
+def gray_hash(spec, length):
+    return colorize('@K{%s}' % spec.dag_hash(length))
+
+
+def display_specs(specs, **kwargs):
+    mode = kwargs.get('mode', 'short')
+    hashes = kwargs.get('long', False)
+    namespace = kwargs.get('namespace', False)
+    flags = kwargs.get('show_flags', False)
+    variants = kwargs.get('variants', False)
+
+    hlen = 7
+    if kwargs.get('very_long', False):
+        hashes = True
+        hlen = None
+
+    nfmt = '.' if namespace else '_'
+    ffmt = '$%+' if flags else ''
+    vfmt = '$+' if variants else ''
+    format_string = '$%s$@%s%s' % (nfmt, ffmt, vfmt)
+
+    # Make a dict with specs keyed by architecture and compiler.
+    index = index_by(specs, ('architecture', 'compiler'))
+
+    # Traverse the index and print out each package
+    for i, (architecture, compiler) in enumerate(sorted(index)):
+        if i > 0:
+            print
+
+        header = "%s{%s} / %s{%s}" % (spack.spec.architecture_color,
+                                      architecture, spack.spec.compiler_color,
+                                      compiler)
+        tty.hline(colorize(header), char='-')
+
+        specs = index[(architecture, compiler)]
+        specs.sort()
+
+        abbreviated = [s.format(format_string, color=True) for s in specs]
+        if mode == 'paths':
+            # Print one spec per line along with prefix path
+            width = max(len(s) for s in abbreviated)
+            width += 2
+            format = "    %%-%ds%%s" % width
+
+            for abbrv, spec in zip(abbreviated, specs):
+                if hashes:
+                    print(gray_hash(spec, hlen), )
+                print(format % (abbrv, spec.prefix))
+
+        elif mode == 'deps':
+            for spec in specs:
+                print(spec.tree(
+                    format=format_string,
+                    color=True,
+                    indent=4,
+                    prefix=(lambda s: gray_hash(s, hlen)) if hashes else None))
+
+        elif mode == 'short':
+            # Print columns of output if not printing flags
+            if not flags:
+
+                def fmt(s):
+                    string = ""
+                    if hashes:
+                        string += gray_hash(s, hlen) + ' '
+                    string += s.format('$-%s$@%s' % (nfmt, vfmt), color=True)
+
+                    return string
+
+                colify(fmt(s) for s in specs)
+            # Print one entry per line if including flags
+            else:
+                for spec in specs:
+                    # Print the hash if necessary
+                    hsh = gray_hash(spec, hlen) + ' ' if hashes else ''
+                    print(hsh + spec.format(format_string, color=True) + '\n')
+
+        else:
+            raise ValueError(
+                "Invalid mode for display_specs: %s. Must be one of (paths,"
+                "deps, short)." % mode)  # NOQA: ignore=E501
diff --git a/lib/spack/spack/cmd/common/__init__.py b/lib/spack/spack/cmd/common/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..ed1ec23bcab2aa19523b3574b84ae6444bb45308
--- /dev/null
+++ b/lib/spack/spack/cmd/common/__init__.py
@@ -0,0 +1,24 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##############################################################################
diff --git a/lib/spack/spack/cmd/common/arguments.py b/lib/spack/spack/cmd/common/arguments.py
new file mode 100644
index 0000000000000000000000000000000000000000..af041708243b3960435dbb6b0a22595d6237ff2a
--- /dev/null
+++ b/lib/spack/spack/cmd/common/arguments.py
@@ -0,0 +1,96 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 spack.modules
+from spack.util.pattern import Bunch
+__all__ = ['add_common_arguments']
+
+_arguments = {}
+
+
+def add_common_arguments(parser, list_of_arguments):
+    for argument in list_of_arguments:
+        if argument not in _arguments:
+            message = 'Trying to add the non existing argument "{0}" to a command'  # NOQA: ignore=E501
+            raise KeyError(message.format(argument))
+        x = _arguments[argument]
+        parser.add_argument(*x.flags, **x.kwargs)
+
+
+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
+    """
+    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.installed_db.query(**d)]
+        values = ' '.join(values)
+        if values:
+            specs = [x for x in specs if x.satisfies(values, strict=True)]
+        namespace.specs = specs
+
+parms = Bunch(
+    flags=('constraint',),
+    kwargs={
+        'nargs': '*',
+        'help': 'Constraint to select a subset of installed packages',
+        'action': ConstraintAction
+    })
+_arguments['constraint'] = parms
+
+parms = Bunch(
+    flags=('-m', '--module-type'),
+    kwargs={
+        'help': 'Type of module files',
+        'default': 'tcl',
+        'choices': spack.modules.module_types
+    })
+_arguments['module_type'] = parms
+
+parms = Bunch(
+    flags=('-y', '--yes-to-all'),
+    kwargs={
+        'action': 'store_true',
+        'dest': 'yes_to_all',
+        'help': 'Assume "yes" is the answer to every confirmation asked to the user.'  # NOQA: ignore=E501
+    })
+_arguments['yes_to_all'] = parms
+
+parms = Bunch(
+    flags=('-r', '--dependencies'),
+    kwargs={
+        'action': 'store_true',
+        'dest': 'recurse_dependencies',
+        'help': 'Recursively traverse spec dependencies'
+    })
+_arguments['recurse_dependencies'] = parms
diff --git a/lib/spack/spack/cmd/find.py b/lib/spack/spack/cmd/find.py
index 3ec671f93f6155f8f4430bb9692c31af02b687ac..d3ea38c573f9cec8a8efbab57efd554236697a27 100644
--- a/lib/spack/spack/cmd/find.py
+++ b/lib/spack/spack/cmd/find.py
@@ -31,7 +31,7 @@
 from llnl.util.lang import *
 from llnl.util.tty.colify import *
 from llnl.util.tty.color import *
-from llnl.util.lang import *
+from spack.cmd import display_specs
 
 description = "Find installed spack packages"
 
@@ -104,89 +104,6 @@ def setup_parser(subparser):
                            help='optional specs to filter results')
 
 
-def gray_hash(spec, length):
-    return colorize('@K{%s}' % spec.dag_hash(length))
-
-
-def display_specs(specs, **kwargs):
-    mode = kwargs.get('mode', 'short')
-    hashes = kwargs.get('long', False)
-    namespace = kwargs.get('namespace', False)
-    flags = kwargs.get('show_flags', False)
-    variants = kwargs.get('variants', False)
-
-    hlen = 7
-    if kwargs.get('very_long', False):
-        hashes = True
-        hlen = None
-
-    nfmt = '.' if namespace else '_'
-    ffmt = '$%+' if flags else ''
-    vfmt = '$+' if variants else ''
-    format_string = '$%s$@%s%s' % (nfmt, ffmt, vfmt)
-
-    # Make a dict with specs keyed by architecture and compiler.
-    index = index_by(specs, ('architecture', 'compiler'))
-
-    # Traverse the index and print out each package
-    for i, (architecture, compiler) in enumerate(sorted(index)):
-        if i > 0:
-            print
-
-        header = "%s{%s} / %s{%s}" % (spack.spec.architecture_color,
-                                      architecture, spack.spec.compiler_color,
-                                      compiler)
-        tty.hline(colorize(header), char='-')
-
-        specs = index[(architecture, compiler)]
-        specs.sort()
-
-        abbreviated = [s.format(format_string, color=True) for s in specs]
-        if mode == 'paths':
-            # Print one spec per line along with prefix path
-            width = max(len(s) for s in abbreviated)
-            width += 2
-            format = "    %%-%ds%%s" % width
-
-            for abbrv, spec in zip(abbreviated, specs):
-                if hashes:
-                    print(gray_hash(spec, hlen), )
-                print(format % (abbrv, spec.prefix))
-
-        elif mode == 'deps':
-            for spec in specs:
-                print(spec.tree(
-                    format=format_string,
-                    color=True,
-                    indent=4,
-                    prefix=(lambda s: gray_hash(s, hlen)) if hashes else None))
-
-        elif mode == 'short':
-            # Print columns of output if not printing flags
-            if not flags:
-
-                def fmt(s):
-                    string = ""
-                    if hashes:
-                        string += gray_hash(s, hlen) + ' '
-                    string += s.format('$-%s$@%s' % (nfmt, vfmt), color=True)
-
-                    return string
-
-                colify(fmt(s) for s in specs)
-            # Print one entry per line if including flags
-            else:
-                for spec in specs:
-                    # Print the hash if necessary
-                    hsh = gray_hash(spec, hlen) + ' ' if hashes else ''
-                    print(hsh + spec.format(format_string, color=True) + '\n')
-
-        else:
-            raise ValueError(
-                "Invalid mode for display_specs: %s. Must be one of (paths,"
-                "deps, short)." % mode)  # NOQA: ignore=E501
-
-
 def query_arguments(args):
     # Check arguments
     if args.explicit and args.implicit:
diff --git a/lib/spack/spack/cmd/module.py b/lib/spack/spack/cmd/module.py
index 55826d133c21396960665192e7868ffe5b736acf..a10e36e077a127f1ffbb73437d3d70f6d94c6fa1 100644
--- a/lib/spack/spack/cmd/module.py
+++ b/lib/spack/spack/cmd/module.py
@@ -23,135 +23,233 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
 from __future__ import print_function
+
+import collections
 import os
 import shutil
 import sys
 
 import llnl.util.tty as tty
 import spack.cmd
-from llnl.util.filesystem import mkdirp
+import spack.cmd.common.arguments as arguments
+import llnl.util.filesystem as filesystem
 from spack.modules import module_types
-from spack.util.string import *
-
-description = "Manipulate modules and dotkits."
-
-
-def setup_parser(subparser):
-    sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='module_command')
-
-    sp.add_parser('refresh', help='Regenerate all module files.')
 
-    find_parser = sp.add_parser('find', help='Find module files for packages.')
+description = "Manipulate module files"
 
-    find_parser.add_argument(
-        'module_type',
-        help="Type of module to find file for. [" +
-        '|'.join(module_types) + "]")
+# Dictionary that will be populated with the list of sub-commands
+# Each sub-command must be callable and accept 3 arguments :
+# - mtype : the type of the module file
+# - specs : the list of specs to be processed
+# - args : namespace containing the parsed command line arguments
+callbacks = {}
 
-    find_parser.add_argument(
-        '-r', '--dependencies', action='store_true',
-        dest='recurse_dependencies',
-        help='Recursively traverse dependencies for modules to load.')
 
-    find_parser.add_argument(
-        '-s', '--shell', action='store_true', dest='shell',
-        help='Generate shell script (instead of input for module command)')
+def subcommand(subparser_name):
+    """Registers a function in the callbacks dictionary"""
+    def decorator(callback):
+        callbacks[subparser_name] = callback
+        return callback
+    return decorator
 
-    find_parser.add_argument(
-        '-p', '--prefix', dest='prefix',
-        help='Prepend to module names when issuing module load commands')
 
-    find_parser.add_argument(
-        'spec', nargs='+',
-        help='spec to find a module file for.')
-
-
-def module_find(mtype, flags, spec_array):
-    """Look at all installed packages and see if the spec provided
-       matches any.  If it does, check whether there is a module file
-       of type <mtype> there, and print out the name that the user
-       should type to use that package's module.
-    prefix:
-        Prepend this to module names when issuing "module load" commands.
-        Some systems seem to need it.
+def setup_parser(subparser):
+    sp = subparser.add_subparsers(metavar='SUBCOMMAND', dest='subparser_name')
+
+    # spack module refresh
+    refresh_parser = sp.add_parser('refresh', help='Regenerate module files')
+    refresh_parser.add_argument(
+        '--delete-tree',
+        help='Delete the module file tree before refresh',
+        action='store_true'
+    )
+    arguments.add_common_arguments(
+        refresh_parser, ['constraint', 'module_type', 'yes_to_all']
+    )
+
+    # spack module find
+    find_parser = sp.add_parser('find', help='Find module files for packages')
+    arguments.add_common_arguments(find_parser, ['constraint', 'module_type'])
+
+    # spack module rm
+    rm_parser = sp.add_parser('rm', help='Remove module files')
+    arguments.add_common_arguments(
+        rm_parser, ['constraint', 'module_type', 'yes_to_all']
+    )
+
+    # spack module loads
+    loads_parser = sp.add_parser(
+        'loads',
+        help='Prompt the list of modules associated with a constraint'
+    )
+    loads_parser.add_argument(
+        '--input-only', action='store_false', dest='shell',
+        help='Generate input for module command (instead of a shell script)'
+    )
+    loads_parser.add_argument(
+        '-p', '--prefix', dest='prefix', default='',
+        help='Prepend to module names when issuing module load commands'
+    )
+    arguments.add_common_arguments(
+        loads_parser, ['constraint', 'module_type', 'recurse_dependencies']
+    )
+
+
+class MultipleMatches(Exception):
+    pass
+
+
+class NoMatch(Exception):
+    pass
+
+
+@subcommand('loads')
+def loads(mtype, specs, args):
+    """Prompt the list of modules associated with a list of specs"""
+    # Get a comprehensive list of specs
+    if args.recurse_dependencies:
+        specs_from_user_constraint = specs[:]
+        specs = []
+        # FIXME : during module file creation nodes seem to be visited
+        # FIXME : multiple times even if cover='nodes' is given. This
+        # FIXME : work around permits to get a unique list of spec anyhow.
+        # FIXME : (same problem as in spack/modules.py)
+        seen = set()
+        seen_add = seen.add
+        for spec in specs_from_user_constraint:
+            specs.extend(
+                [item for item in spec.traverse(order='post', cover='nodes') if not (item in seen or seen_add(item))]  # NOQA: ignore=E501
+            )
+
+    module_cls = module_types[mtype]
+    modules = [(spec, module_cls(spec).use_name)
+               for spec in specs if os.path.exists(module_cls(spec).file_name)]
+
+    module_commands = {
+        'tcl': 'module load ',
+        'dotkit': 'dotkit use '
+    }
+
+    d = {
+        'command': '' if not args.shell else module_commands[mtype],
+        'prefix': args.prefix
+    }
+
+    prompt_template = '{comment}{command}{prefix}{name}'
+    for spec, mod in modules:
+        d['comment'] = '' if not args.shell else '# {0}\n'.format(
+            spec.format())
+        d['name'] = mod
+        print(prompt_template.format(**d))
+
+
+@subcommand('find')
+def find(mtype, specs, args):
     """
-    if mtype not in module_types:
-        tty.die("Invalid module type: '%s'.  Options are %s" %
-                (mtype, comma_or(module_types)))
-
-    # --------------------------------------
-    def _find_modules(spec, modules_list):
-        """Finds all modules and sub-modules for a spec"""
-        if str(spec.version) == 'system':
-            # No Spack module for system-installed packages
-            return
-
-        if flags.recurse_dependencies:
-            for dep in spec.dependencies():
-                _find_modules(dep, modules_list)
-
-        mod = module_types[mtype](spec)
-        if not os.path.isfile(mod.file_name):
-            tty.die("No %s module is installed for %s" % (mtype, spec))
-        modules_list.append((spec, mod))
-
-
-    # --------------------------------------
-    raw_specs = spack.cmd.parse_specs(spec_array)
-    modules = set()    # Modules we will load
-    seen = set()
-    for raw_spec in raw_specs:
-
-        # ----------- Make sure the spec only resolves to ONE thing
-        specs = spack.installed_db.query(raw_spec)
-        if len(specs) == 0:
-            tty.die("No installed packages match spec %s" % raw_spec)
-
-        if len(specs) > 1:
-            tty.error("Multiple matches for spec %s.  Choose one:" % raw_spec)
-            for s in specs:
-                sys.stderr.write(s.tree(color=True))
-            sys.exit(1)
-        spec = specs[0]
-
-        # ----------- Chase down modules for it and all its dependencies
-        modules_dups = list()
-        _find_modules(spec, modules_dups)
-
-        # Remove duplicates while keeping order
-        modules_unique = list()
-        for spec,mod in modules_dups:
-            if mod.use_name not in seen:
-                modules_unique.append((spec,mod))
-                seen.add(mod.use_name)
-
-        # Output...
-        if flags.shell:
-            module_cmd = {'tcl': 'module load', 'dotkit': 'dotkit use'}[mtype]
-        for spec,mod in modules_unique:
-            if flags.shell:
-                print('# %s' % spec.format())
-                print('%s %s%s' % (module_cmd, flags.prefix, mod.use_name))
-            else:
-                print(mod.use_name)
-
-def module_refresh():
-    """Regenerate all module files for installed packages known to
-       spack (some packages may no longer exist)."""
-    specs = [s for s in spack.installed_db.query(installed=True, known=True)]
-
-    for name, cls in module_types.items():
-        tty.msg("Regenerating %s module files." % name)
-        if os.path.isdir(cls.path):
-            shutil.rmtree(cls.path, ignore_errors=False)
-        mkdirp(cls.path)
-        for spec in specs:
-            cls(spec).write()
+    Look at all installed packages and see if the spec provided
+    matches any.  If it does, check whether there is a module file
+    of type <mtype> there, and print out the name that the user
+    should type to use that package's module.
+    """
+    if len(specs) == 0:
+        raise NoMatch()
+
+    if len(specs) > 1:
+        raise MultipleMatches()
+
+    spec = specs.pop()
+    mod = module_types[mtype](spec)
+    if not os.path.isfile(mod.file_name):
+        tty.die("No %s module is installed for %s" % (mtype, spec))
+    print(mod.use_name)
+
+
+@subcommand('rm')
+def rm(mtype, specs, args):
+    """Deletes module files associated with items in specs"""
+    module_cls = module_types[mtype]
+    specs_with_modules = [
+        spec for spec in specs if os.path.exists(module_cls(spec).file_name)]
+    modules = [module_cls(spec) for spec in specs_with_modules]
+
+    if not modules:
+        tty.msg('No module file matches your query')
+        raise SystemExit(1)
+
+    # Ask for confirmation
+    if not args.yes_to_all:
+        tty.msg('You are about to remove {0} module files the following specs:\n'.format(mtype))  # NOQA: ignore=E501
+        spack.cmd.display_specs(specs_with_modules, long=True)
+        print('')
+        spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
+
+    # Remove the module files
+    for s in modules:
+        s.remove()
+
+
+@subcommand('refresh')
+def refresh(mtype, specs, args):
+    """Regenerate module files for item in specs"""
+    # Prompt a message to the user about what is going to change
+    if not specs:
+        tty.msg('No package matches your query')
+        return
+
+    if not args.yes_to_all:
+        tty.msg('You are about to regenerate {name} module files for the following specs:\n'.format(name=mtype))  # NOQA: ignore=E501
+        spack.cmd.display_specs(specs, long=True)
+        print('')
+        spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
+
+    cls = module_types[mtype]
+
+    # Detect name clashes
+    writers = [cls(spec) for spec in specs]
+    file2writer = collections.defaultdict(list)
+    for item in writers:
+        file2writer[item.file_name].append(item)
+
+    if len(file2writer) != len(writers):
+        message = 'Name clashes detected in module files:\n'
+        for filename, writer_list in file2writer.items():
+            if len(writer_list) > 1:
+                message += '\nfile : {0}\n'.format(filename)
+                for x in writer_list:
+                    message += 'spec : {0}\n'.format(x.spec.format(color=True))
+        tty.error(message)
+        tty.error('Operation aborted')
+        raise SystemExit(1)
+
+    # Proceed regenerating module files
+    tty.msg('Regenerating {name} module files'.format(name=mtype))
+    if os.path.isdir(cls.path) and args.delete_tree:
+        shutil.rmtree(cls.path, ignore_errors=False)
+    filesystem.mkdirp(cls.path)
+    for x in writers:
+        x.write(overwrite=True)
 
 
 def module(parser, args):
-    if args.module_command == 'refresh':
-        module_refresh()
-
-    elif args.module_command == 'find':
-        module_find(args.module_type, args, args.spec)
+    # Qualifiers to be used when querying the db for specs
+    constraint_qualifiers = {
+        'refresh': {
+            'installed': True,
+            'known': True
+        },
+    }
+    arguments.ConstraintAction.qualifiers.update(constraint_qualifiers)
+
+    module_type = args.module_type
+    constraint = args.constraint
+    try:
+        callbacks[args.subparser_name](module_type, args.specs, args)
+    except MultipleMatches:
+        message = 'the constraint \'{query}\' matches multiple packages, and this is not allowed in this context'  # NOQA: ignore=E501
+        tty.error(message.format(query=constraint))
+        for s in args.specs:
+            sys.stderr.write(s.format(color=True) + '\n')
+        raise SystemExit(1)
+    except NoMatch:
+        message = 'the constraint \'{query}\' match no package, and this is not allowed in this context'  # NOQA: ignore=E501
+        tty.die(message.format(query=constraint))
diff --git a/lib/spack/spack/cmd/uninstall.py b/lib/spack/spack/cmd/uninstall.py
index a6f08d09ed8c526b43b0b58b904f234e2fa07428..a17b7c685c35278b9f7e4f34b0033092945f76ce 100644
--- a/lib/spack/spack/cmd/uninstall.py
+++ b/lib/spack/spack/cmd/uninstall.py
@@ -30,7 +30,6 @@
 import spack
 import spack.cmd
 import spack.repository
-from spack.cmd.find import display_specs
 
 description = "Remove an installed package"
 
@@ -43,21 +42,10 @@
 display_args = {
     'long': True,
     'show_flags': True,
-    'variants':True
+    'variants': True
 }
 
 
-def ask_for_confirmation(message):
-    while True:
-        tty.msg(message + '[y/n]')
-        choice = raw_input().lower()
-        if choice == 'y':
-            break
-        elif choice == 'n':
-            raise SystemExit('Operation aborted')
-        tty.warn('Please reply either "y" or "n"')
-
-
 def setup_parser(subparser):
     subparser.add_argument(
         '-f', '--force', action='store_true', dest='force',
@@ -65,32 +53,37 @@ def setup_parser(subparser):
     subparser.add_argument(
         '-a', '--all', action='store_true', dest='all',
         help="USE CAREFULLY. Remove ALL installed packages that match each " +
-             "supplied spec. i.e., if you say uninstall libelf, ALL versions of " +
-             "libelf are uninstalled. This is both useful and dangerous, like rm -r.")
+             "supplied spec. i.e., if you say uninstall libelf, ALL versions of " +  # NOQA: ignore=E501
+             "libelf are uninstalled. This is both useful and dangerous, like rm -r.")  # NOQA: ignore=E501
     subparser.add_argument(
         '-d', '--dependents', action='store_true', dest='dependents',
-        help='Also uninstall any packages that depend on the ones given via command line.'
+        help='Also uninstall any packages that depend on the ones given via command line.'  # NOQA: ignore=E501
     )
     subparser.add_argument(
         '-y', '--yes-to-all', action='store_true', dest='yes_to_all',
-        help='Assume "yes" is the answer to every confirmation asked to the user.'
+        help='Assume "yes" is the answer to every confirmation asked to the user.'  # NOQA: ignore=E501
 
     )
-    subparser.add_argument('packages', nargs=argparse.REMAINDER, help="specs of packages to uninstall")
+    subparser.add_argument(
+        'packages',
+        nargs=argparse.REMAINDER,
+        help="specs of packages to uninstall"
+    )
 
 
 def concretize_specs(specs, allow_multiple_matches=False, force=False):
-    """
-    Returns a list of specs matching the non necessarily concretized specs given from cli
+    """Returns a list of specs matching the non necessarily
+    concretized specs given from cli
 
     Args:
         specs: list of specs to be matched against installed packages
-        allow_multiple_matches : boolean (if True multiple matches for each item in specs are admitted)
+        allow_multiple_matches : if True multiple matches are admitted
 
     Return:
         list of specs
     """
-    specs_from_cli = []  # List of specs that match expressions given via command line
+    # List of specs that match expressions given via command line
+    specs_from_cli = []
     has_errors = False
     for spec in specs:
         matching = spack.installed_db.query(spec)
@@ -99,7 +92,7 @@ def concretize_specs(specs, allow_multiple_matches=False, force=False):
         if not allow_multiple_matches and len(matching) > 1:
             tty.error("%s matches multiple packages:" % spec)
             print()
-            display_specs(matching, **display_args)
+            spack.cmd.display_specs(matching, **display_args)
             print()
             has_errors = True
 
@@ -116,8 +109,8 @@ def concretize_specs(specs, allow_multiple_matches=False, force=False):
 
 
 def installed_dependents(specs):
-    """
-    Returns a dictionary that maps a spec with a list of its installed dependents
+    """Returns a dictionary that maps a spec with a list of its
+    installed dependents
 
     Args:
         specs: list of specs to be checked for dependents
@@ -147,7 +140,7 @@ def do_uninstall(specs, force):
         try:
             # should work if package is known to spack
             packages.append(item.package)
-        except spack.repository.UnknownPackageError as e:
+        except spack.repository.UnknownPackageError:
             # The package.py file has gone away -- but still
             # want to uninstall.
             spack.Package(item).do_uninstall(force=True)
@@ -169,17 +162,20 @@ def uninstall(parser, args):
     with spack.installed_db.write_transaction():
         specs = spack.cmd.parse_specs(args.packages)
         # Gets the list of installed specs that match the ones give via cli
-        uninstall_list = concretize_specs(specs, args.all, args.force)  # takes care of '-a' is given in the cli
-        dependent_list = installed_dependents(uninstall_list)  # takes care of '-d'
+        # takes care of '-a' is given in the cli
+        uninstall_list = concretize_specs(specs, args.all, args.force)
+        dependent_list = installed_dependents(
+            uninstall_list)  # takes care of '-d'
 
         # Process dependent_list and update uninstall_list
         has_error = False
         if dependent_list and not args.dependents and not args.force:
             for spec, lst in dependent_list.items():
-                tty.error("Will not uninstall %s" % spec.format("$_$@$%@$#", color=True))
+                tty.error("Will not uninstall %s" %
+                          spec.format("$_$@$%@$#", color=True))
                 print('')
                 print("The following packages depend on it:")
-                display_specs(lst, **display_args)
+                spack.cmd.display_specs(lst, **display_args)
                 print('')
                 has_error = True
         elif args.dependents:
@@ -188,14 +184,14 @@ def uninstall(parser, args):
             uninstall_list = list(set(uninstall_list))
 
         if has_error:
-            tty.die('You can use spack uninstall --dependents to uninstall these dependencies as well')
+            tty.die('You can use spack uninstall --dependents to uninstall these dependencies as well')  # NOQA: ignore=E501
 
         if not args.yes_to_all:
             tty.msg("The following packages will be uninstalled : ")
             print('')
-            display_specs(uninstall_list, **display_args)
+            spack.cmd.display_specs(uninstall_list, **display_args)
             print('')
-            ask_for_confirmation('Do you want to proceed ? ')
+            spack.cmd.ask_for_confirmation('Do you want to proceed ? ')
 
         # Uninstall everything on the list
         do_uninstall(uninstall_list, args.force)
diff --git a/lib/spack/spack/config.py b/lib/spack/spack/config.py
index 84179e146966b18a738d6872709bfe40661e56fb..3a66e9f2a60f060da38cac16e71de2d5f5fb7989 100644
--- a/lib/spack/spack/config.py
+++ b/lib/spack/spack/config.py
@@ -328,6 +328,11 @@
                 'anyOf': [
                     {
                         'properties': {
+                            'hash_length': {
+                                'type': 'integer',
+                                'minimum': 0,
+                                'default': 7
+                            },
                             'whitelist': {'$ref': '#/definitions/array_of_strings'},
                             'blacklist': {'$ref': '#/definitions/array_of_strings'},
                             'naming_scheme': {
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index a2e528d295abfdcb308c263792771ec4c0b22808..72656b8ae0c4f0bc9d4ae85b7619021dd655db71 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -188,6 +188,8 @@ def parse_config_options(module_generator):
     #####
 
     # Automatic loading loads
+    module_file_actions['hash_length'] = module_configuration.get(
+        'hash_length', 7)
     module_file_actions['autoload'] = dependencies(
         module_generator.spec, module_file_actions.get('autoload', 'none'))
     # Prerequisites
@@ -237,6 +239,7 @@ class EnvModule(object):
     formats = {}
 
     class __metaclass__(type):
+
         def __init__(cls, name, bases, dict):
             type.__init__(cls, name, bases, dict)
             if cls.name != 'env_module' and cls.name in CONFIGURATION[
@@ -295,7 +298,9 @@ def use_name(self):
             if constraint in self.spec:
                 suffixes.append(suffix)
         # Always append the hash to make the module file unique
-        suffixes.append(self.spec.dag_hash())
+        hash_length = configuration.pop('hash_length', 7)
+        if hash_length != 0:
+            suffixes.append(self.spec.dag_hash(length=hash_length))
         name = '-'.join(suffixes)
         return name
 
@@ -338,7 +343,7 @@ def blacklisted(self):
 
         return False
 
-    def write(self):
+    def write(self, overwrite=False):
         """
         Writes out a module file for this object.
 
@@ -399,6 +404,15 @@ def write(self):
         for line in self.module_specific_content(module_configuration):
             module_file_content += line
 
+        # Print a warning in case I am accidentally overwriting
+        # a module file that is already there (name clash)
+        if not overwrite and os.path.exists(self.file_name):
+            message = 'Module file already exists : skipping creation\n'
+            message += 'file : {0.file_name}\n'
+            message += 'spec : {0.spec}'
+            tty.warn(message.format(self))
+            return
+
         # Dump to file
         with open(self.file_name, 'w') as f:
             f.write(module_file_content)
@@ -454,7 +468,7 @@ def remove(self):
 
 class Dotkit(EnvModule):
     name = 'dotkit'
-
+    path = join_path(spack.share_path, 'dotkit')
     environment_modifications_formats = {
         PrependPath: 'dk_alter {name} {value}\n',
         SetEnv: 'dk_setenv {name} {value}\n'
@@ -466,7 +480,7 @@ class Dotkit(EnvModule):
 
     @property
     def file_name(self):
-        return join_path(spack.share_path, "dotkit", self.spec.architecture,
+        return join_path(self.path, self.spec.architecture,
                          '%s.dk' % self.use_name)
 
     @property
@@ -494,7 +508,7 @@ def prerequisite(self, spec):
 
 class TclModule(EnvModule):
     name = 'tcl'
-
+    path = join_path(spack.share_path, "modules")
     environment_modifications_formats = {
         PrependPath: 'prepend-path --delim "{delim}" {name} \"{value}\"\n',
         AppendPath: 'append-path   --delim "{delim}" {name} \"{value}\"\n',
@@ -514,7 +528,7 @@ class TclModule(EnvModule):
 
     @property
     def file_name(self):
-        return join_path(spack.share_path, "modules", self.spec.architecture, self.use_name)
+        return join_path(self.path, self.spec.architecture, self.use_name)
 
     @property
     def header(self):
diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py
index 9f7da46a1a37c9368cf7cd9df98f149a6c51d301..a849d5f35021ae04be751073ee8727c6f40ee57c 100644
--- a/lib/spack/spack/test/__init__.py
+++ b/lib/spack/spack/test/__init__.py
@@ -40,7 +40,8 @@
     'mirror', 'modules', 'url_extrapolate', 'cc', 'link_tree', 'spec_yaml',
     'optional_deps', 'make_executable', 'build_system_guess', 'lock',
     'database', 'namespace_trie', 'yaml', 'sbang', 'environment', 'cmd.find',
-    'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd'
+    'cmd.uninstall', 'cmd.test_install', 'cmd.test_compiler_cmd',
+    'cmd.module'
 ]
 
 
diff --git a/lib/spack/spack/test/cmd/find.py b/lib/spack/spack/test/cmd/find.py
index 371e9650e04700c6135a4323cc81f67ca1221208..fa82db7733789fb933f851ea00fe6f8c53cd5730 100644
--- a/lib/spack/spack/test/cmd/find.py
+++ b/lib/spack/spack/test/cmd/find.py
@@ -27,11 +27,7 @@
 import spack.cmd.find
 import unittest
 
-
-class Bunch(object):
-
-    def __init__(self, **kwargs):
-        self.__dict__.update(kwargs)
+from spack.util.pattern import Bunch
 
 
 class FindTest(unittest.TestCase):
diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py
new file mode 100644
index 0000000000000000000000000000000000000000..36a4a73fe6423c723b498521492fe6f5a5cc85bc
--- /dev/null
+++ b/lib/spack/spack/test/cmd/module.py
@@ -0,0 +1,83 @@
+##############################################################################
+# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC.
+# Produced at the Lawrence Livermore National Laboratory.
+#
+# This file is part of Spack.
+# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
+# LLNL-CODE-647188
+#
+# For details, see https://github.com/llnl/spack
+# Please also see the LICENSE file for our notice and the LGPL.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License (as
+# published by the Free Software Foundation) version 2.1, February 1999.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
+# conditions of the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 os.path
+
+import spack.cmd.module as module
+import spack.modules as modules
+import spack.test.mock_database
+
+
+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  # NOQA: ignore=E501
+        ]
+
+    def test_module_common_operations(self):
+        parser = argparse.ArgumentParser()
+        module.setup_parser(parser)
+        # Try to remove a non existing module [tcl]
+        args = parser.parse_args(['rm', 'doesnotexist'])
+        self.assertRaises(SystemExit, module.module, parser, args)
+        # Remove existing modules [tcl]
+        args = parser.parse_args(['rm', '-y', 'mpileaks'])
+        module_files = self._get_module_files(args)
+        for item in module_files:
+            self.assertTrue(os.path.exists(item))
+        module.module(parser, args)
+        for item in module_files:
+            self.assertFalse(os.path.exists(item))
+        # Add them back [tcl]
+        args = parser.parse_args(['refresh', '-y', 'mpileaks'])
+        module.module(parser, args)
+        for item in module_files:
+            self.assertTrue(os.path.exists(item))
+        # TODO : test the --delete-tree option
+        # TODO : this requires having a separate directory for test modules
+        # Try to find a module with multiple matches
+        args = parser.parse_args(['find', 'mpileaks'])
+        self.assertRaises(SystemExit, module.module, parser, args)
+        # Try to find a module with no matches
+        args = parser.parse_args(['find', 'doesnotexist'])
+        self.assertRaises(SystemExit, module.module, parser, args)
+        # Try to find a module
+        args = parser.parse_args(['find', 'libelf'])
+        module.module(parser, args)
+        # Remove existing modules [dotkit]
+        args = parser.parse_args(['rm', '-y', '-m', 'dotkit', 'mpileaks'])
+        module_files = self._get_module_files(args)
+        for item in module_files:
+            self.assertTrue(os.path.exists(item))
+        module.module(parser, args)
+        for item in module_files:
+            self.assertFalse(os.path.exists(item))
+        # Add them back [dotkit]
+        args = parser.parse_args(['refresh', '-y', '-m', 'dotkit', 'mpileaks'])
+        module.module(parser, args)
+        for item in module_files:
+            self.assertTrue(os.path.exists(item))
+        # TODO : add tests for loads and find to check the prompt format
diff --git a/lib/spack/spack/util/pattern.py b/lib/spack/spack/util/pattern.py
index 6d4bcb10396bf690f1cbffdbe202e1f2cc5a35bc..bc5e9d2ffef6d1c34bb9df4822602d2db611684e 100644
--- a/lib/spack/spack/util/pattern.py
+++ b/lib/spack/spack/util/pattern.py
@@ -28,42 +28,50 @@
 
 
 def composite(interface=None, method_list=None, container=list):
-    """
-    Returns a class decorator that patches a class adding all the methods it needs to be a composite for a given
-    interface.
+    """Returns a class decorator that patches a class adding all the methods
+    it needs to be a composite for a given interface.
 
-    :param interface: class exposing the interface to which the composite object must conform. Only non-private and
-    non-special methods will be taken into account
+    :param interface: class exposing the interface to which the composite
+    object must conform. Only non-private and non-special methods will be
+    taken into account
 
     :param method_list: names of methods that should be part of the composite
 
-    :param container: container for the composite object (default = list). Must fulfill the MutableSequence contract.
-    The composite class will expose the container API to manage object composition
+    :param container: container for the composite object (default = list).
+    Must fulfill the MutableSequence contract. The composite class will expose
+    the container API to manage object composition
 
     :return: class decorator
     """
-    # Check if container fulfills the MutableSequence contract and raise an exception if it doesn't
-    # The patched class returned by the decorator will inherit from the container class to expose the
-    # interface needed to manage objects composition
+    # Check if container fulfills the MutableSequence contract and raise an
+    # exception if it doesn't. The patched class returned by the decorator will
+    # inherit from the container class to expose the interface needed to manage
+    # objects composition
     if not issubclass(container, collections.MutableSequence):
         raise TypeError("Container must fulfill the MutableSequence contract")
 
-    # Check if at least one of the 'interface' or the 'method_list' arguments are defined
+    # Check if at least one of the 'interface' or the 'method_list' arguments
+    # are defined
     if interface is None and method_list is None:
-        raise TypeError("Either 'interface' or 'method_list' must be defined on a call to composite")
+        raise TypeError("Either 'interface' or 'method_list' must be defined on a call to composite")  # NOQA : ignore=E501
 
     def cls_decorator(cls):
-        # Retrieve the base class of the composite. Inspect its methods and decide which ones will be overridden
+        # Retrieve the base class of the composite. Inspect its methods and
+        # decide which ones will be overridden
         def no_special_no_private(x):
             return inspect.ismethod(x) and not x.__name__.startswith('_')
 
-        # Patch the behavior of each of the methods in the previous list. This is done associating an instance of the
-        # descriptor below to any method that needs to be patched.
+        # Patch the behavior of each of the methods in the previous list.
+        # This is done associating an instance of the descriptor below to
+        # any method that needs to be patched.
         class IterateOver(object):
+            """Decorator used to patch methods in a composite.
+
+            It iterates over all the items in the instance containing the
+            associated attribute and calls for each of them an attribute
+            with the same name
             """
-            Decorator used to patch methods in a composite. It iterates over all the items in the instance containing the
-            associated attribute and calls for each of them an attribute with the same name
-            """
+
             def __init__(self, name, func=None):
                 self.name = name
                 self.func = func
@@ -72,8 +80,9 @@ def __get__(self, instance, owner):
                 def getter(*args, **kwargs):
                     for item in instance:
                         getattr(item, self.name)(*args, **kwargs)
-                # If we are using this descriptor to wrap a method from an interface, then we must conditionally
-                # use the `functools.wraps` decorator to set the appropriate fields.
+                # If we are using this descriptor to wrap a method from an
+                # interface, then we must conditionally use the
+                # `functools.wraps` decorator to set the appropriate fields
                 if self.func is not None:
                     getter = functools.wraps(self.func)(getter)
                 return getter
@@ -81,7 +90,8 @@ def getter(*args, **kwargs):
         dictionary_for_type_call = {}
         # Construct a dictionary with the methods explicitly passed as name
         if method_list is not None:
-            # python@2.7: method_list_dict = {name: IterateOver(name) for name in method_list}
+            # python@2.7: method_list_dict = {name: IterateOver(name) for name
+            # in method_list}
             method_list_dict = {}
             for name in method_list:
                 method_list_dict[name] = IterateOver(name)
@@ -89,28 +99,40 @@ def getter(*args, **kwargs):
         # Construct a dictionary with the methods inspected from the interface
         if interface is not None:
             ##########
-            # python@2.7: interface_methods = {name: method for name, method in inspect.getmembers(interface, predicate=no_special_no_private)}
+            # python@2.7: interface_methods = {name: method for name, method in
+            # inspect.getmembers(interface, predicate=no_special_no_private)}
             interface_methods = {}
-            for name, method in inspect.getmembers(interface, predicate=no_special_no_private):
+            for name, method in inspect.getmembers(interface, predicate=no_special_no_private):  # NOQA: ignore=E501
                 interface_methods[name] = method
             ##########
-            # python@2.7: interface_methods_dict = {name: IterateOver(name, method) for name, method in interface_methods.iteritems()}
+            # python@2.7: interface_methods_dict = {name: IterateOver(name,
+            # method) for name, method in interface_methods.iteritems()}
             interface_methods_dict = {}
             for name, method in interface_methods.iteritems():
                 interface_methods_dict[name] = IterateOver(name, method)
             ##########
             dictionary_for_type_call.update(interface_methods_dict)
-        # Get the methods that are defined in the scope of the composite class and override any previous definition
+        # Get the methods that are defined in the scope of the composite
+        # class and override any previous definition
         ##########
-        # python@2.7: cls_method = {name: method for name, method in inspect.getmembers(cls, predicate=inspect.ismethod)}
+        # python@2.7: cls_method = {name: method for name, method in
+        # inspect.getmembers(cls, predicate=inspect.ismethod)}
         cls_method = {}
-        for name, method in inspect.getmembers(cls, predicate=inspect.ismethod):
+        for name, method in inspect.getmembers(cls, predicate=inspect.ismethod):  # NOQA: ignore=E501
             cls_method[name] = method
         ##########
         dictionary_for_type_call.update(cls_method)
         # Generate the new class on the fly and return it
         # FIXME : inherit from interface if we start to use ABC classes?
-        wrapper_class = type(cls.__name__, (cls, container), dictionary_for_type_call)
+        wrapper_class = type(cls.__name__, (cls, container),
+                             dictionary_for_type_call)
         return wrapper_class
 
     return cls_decorator
+
+
+class Bunch(object):
+    """Carries a bunch of named attributes (from Alex Martelli bunch)"""
+
+    def __init__(self, **kwargs):
+        self.__dict__.update(kwargs)
diff --git a/share/spack/csh/spack.csh b/share/spack/csh/spack.csh
index d64ce8935b65424db19ea51cc6caf62e72f5545c..5acd1904499bd63a7a074fa14fc27f0be977e8a3 100644
--- a/share/spack/csh/spack.csh
+++ b/share/spack/csh/spack.csh
@@ -74,25 +74,25 @@ case unload:
     # tool's commands to add/remove the result from the environment.
     switch ($_sp_subcommand)
         case "use":
-            set _sp_full_spec = ( "`\spack $_sp_flags module find dotkit $_sp_spec`" )
+            set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type dotkit $_sp_spec`" )
             if ( $? == 0 ) then
                 use $_sp_module_args $_sp_full_spec
             endif
             breaksw
         case "unuse":
-            set _sp_full_spec = ( "`\spack $_sp_flags module find dotkit $_sp_spec`" )
+            set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type dotkit $_sp_spec`" )
             if ( $? == 0 ) then
                 unuse $_sp_module_args $_sp_full_spec
             endif
             breaksw
         case "load":
-            set _sp_full_spec = ( "`\spack $_sp_flags module find tcl $_sp_spec`" )
+            set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type tcl $_sp_spec`" )
             if ( $? == 0 ) then
                 module load $_sp_module_args $_sp_full_spec
             endif
             breaksw
         case "unload":
-            set _sp_full_spec = ( "`\spack $_sp_flags module find tcl $_sp_spec`" )
+            set _sp_full_spec = ( "`\spack $_sp_flags module find --module-type tcl $_sp_spec`" )
             if ( $? == 0 ) then
                 module unload $_sp_module_args $_sp_full_spec
             endif
diff --git a/share/spack/setup-env.sh b/share/spack/setup-env.sh
index 19206255db0ad89780199515c92da5076f8de816..c6183f990df1a8bc11dc2428e2d346a582cc7c5a 100755
--- a/share/spack/setup-env.sh
+++ b/share/spack/setup-env.sh
@@ -117,19 +117,19 @@ function spack {
             # If spack module command comes back with an error, do nothing.
             case $_sp_subcommand in
                 "use")
-                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args dotkit $_sp_spec); then
+                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args --module-type dotkit $_sp_spec); then
                         use $_sp_module_args $_sp_full_spec
                     fi ;;
                 "unuse")
-                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args dotkit $_sp_spec); then
+                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args --module-type dotkit $_sp_spec); then
                         unuse $_sp_module_args $_sp_full_spec
                     fi ;;
                 "load")
-                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args tcl $_sp_spec); then
+                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args --module-type tcl $_sp_spec); then
                         module load $_sp_module_args $_sp_full_spec
                     fi ;;
                 "unload")
-                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args tcl $_sp_spec); then
+                    if _sp_full_spec=$(command spack $_sp_flags module find $_sp_subcommand_args --module-type tcl $_sp_spec); then
                         module unload $_sp_module_args $_sp_full_spec
                     fi ;;
             esac