diff --git a/wa/commands/create.py b/wa/commands/create.py
index f1b78ea5..c2475d98 100644
--- a/wa/commands/create.py
+++ b/wa/commands/create.py
@@ -1,7 +1,9 @@
 import os
 import sys
 import stat
+import shutil
 import string
+import getpass
 from collections import OrderedDict
 from distutils.dir_util import copy_tree
 
@@ -106,6 +108,44 @@ class CreateWorkloadSubcommand(SubCommand):
             self.logger.error('ERROR: {}'.format(e))
 
 
+class CreatePackageSubcommand(SubCommand):
+
+    name = 'package'
+    description = '''Create a new empty Python package for WA extensions. On installation,
+                     this package will "advertise" itself to WA so that Plugins within it will
+                     be loaded by WA when it runs.'''
+
+    def initialize(self, context):
+        self.parser.add_argument('name', metavar='NAME',
+                                 help='Name of the package to be created')
+        self.parser.add_argument('-p', '--path', metavar='PATH', default=None,
+                                 help='The location at which the new package will be created. If not specified, ' +
+                                      'current working directory will be used.')
+        self.parser.add_argument('-f', '--force', action='store_true',
+                                 help='Create the new package even if a file or directory with the same name '
+                                      'already exists at the specified location.')
+
+    def execute(self, state, args):  # pylint: disable=R0201
+        package_dir = args.path or os.path.abspath('.')
+        template_path = os.path.join(TEMPLATES_DIR, 'setup.template')
+        self.create_extensions_package(package_dir, args.name, template_path, args.force)
+
+    def create_extensions_package(self, location, name, setup_template_path, overwrite=False):
+        package_path = os.path.join(location, name)
+        if os.path.exists(package_path):
+            if overwrite:
+                self.logger.info('overwriting existing "{}"'.format(package_path))
+                shutil.rmtree(package_path)
+            else:
+                raise CommandError('Location "{}" already exists.'.format(package_path))
+        actual_package_path = os.path.join(package_path, name)
+        os.makedirs(actual_package_path)
+        setup_text = render_template(setup_template_path, {'package_name': name, 'user': getpass.getuser()})
+        with open(os.path.join(package_path, 'setup.py'), 'w') as wfh:
+            wfh.write(setup_text)
+        touch(os.path.join(actual_package_path, '__init__.py'))
+
+
 class CreateCommand(ComplexCommand):
 
     name = 'create'
@@ -117,7 +157,7 @@ class CreateCommand(ComplexCommand):
     subcmd_classes = [
         CreateWorkloadSubcommand,
         CreateAgendaSubcommand,
-        #CreatePackageSubcommand,
+        CreatePackageSubcommand,
     ]
 
 
@@ -204,3 +244,7 @@ def render_template(name, params):
 def get_class_name(name, postfix=''):
     name = identifier(name)
     return ''.join(map(capitalize, name.split('_'))) + postfix
+
+def touch(path):
+    with open(path, 'w') as _:
+        pass
diff --git a/wa/commands/templates/setup.template b/wa/commands/templates/setup.template
new file mode 100644
index 00000000..d68801a2
--- /dev/null
+++ b/wa/commands/templates/setup.template
@@ -0,0 +1,102 @@
+import os
+import sys
+import warnings
+from multiprocessing import Process
+
+try:
+    from setuptools.command.install import install as orig_install
+    from setuptools import setup
+except ImportError:
+    from distutils.command.install import install as orig_install
+    from distutils.core import setup
+
+try:
+    import pwd
+except ImportError:
+    pwd = None
+
+warnings.filterwarnings('ignore', "Unknown distribution option: 'install_requires'")
+
+try:
+    os.remove('MANIFEST')
+except OSError:
+    pass
+
+
+packages = []
+data_files = {}
+source_dir = os.path.dirname(__file__)
+for root, dirs, files in os.walk('$package_name'):
+    rel_dir = os.path.relpath(root, source_dir)
+    data = []
+    if '__init__.py' in files:
+        for f in files:
+            if os.path.splitext(f)[1] not in ['.py', '.pyc', '.pyo']:
+                data.append(f)
+        package_name = rel_dir.replace(os.sep, '.')
+        package_dir = root
+        packages.append(package_name)
+        data_files[package_name] = data
+    else:
+        # use previous package name
+        filepaths = [os.path.join(root, f) for f in files]
+        data_files[package_name].extend([os.path.relpath(f, package_dir) for f in filepaths])
+
+params = dict(
+    name='$package_name',
+    version='0.0.1',
+    packages=packages,
+    package_data=data_files,
+    url='N/A',
+    maintainer='$user',
+    maintainer_email='$user@example.com',
+    install_requires=[
+        'wa',
+    ],
+    # https://pypi.python.org/pypi?%3Aaction=list_classifiers
+    classifiers=[
+        'Development Status :: 3 - Alpha',
+        'Environment :: Console',
+        'License :: Other/Proprietary License',
+        'Operating System :: Unix',
+        'Programming Language :: Python :: 2.7',
+    ],
+)
+
+
+def update_wa_packages():
+    sudo_user = os.getenv('SUDO_USER')
+    if sudo_user:
+        user_entry = pwd.getpwnam(sudo_user)
+        os.setgid(user_entry.pw_gid)
+        os.setuid(user_entry.pw_uid)
+    env_root = os.getenv('WA_USER_DIRECTORY', os.path.join(os.path.expanduser('~'), '.workload_automation'))
+    if not os.path.isdir(env_root):
+        os.makedirs(env_root)
+    wa_packages_file = os.path.join(env_root, 'packages')
+    if os.path.isfile(wa_packages_file):
+        with open(wa_packages_file, 'r') as wfh:
+            package_list = wfh.read().split()
+            if params['name'] not in package_list:
+                package_list.append(params['name'])
+    else:  # no existing package file
+        package_list = [params['name']]
+    with open(wa_packages_file, 'w') as wfh:
+        wfh.write('\n'.join(package_list))
+
+
+class install(orig_install):
+
+    def run(self):
+        orig_install.run(self)
+        # Must be done in a separate process because will drop privileges if
+        # sudo, and won't be able to reacquire them.
+        p = Process(target=update_wa_packages)
+        p.start()
+        p.join()
+
+
+params['cmdclass'] = {'install': install}
+
+
+setup(**params)