diff --git a/Gemfile b/Gemfile
index cef97fbc1ba690311d659aaf17bfb108e124b31c..b438bc89e3ec66fd29103053b7355214857c9051 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,4 +1,3 @@
 source 'https://rubygems.org'
-gem 'sass', '3.3.5'
 gem 'bourbon', '~> 4.0.2'
 gem 'neat', '~> 1.6.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 551990d98f6664ad65c2b1072316f08116d87c7f..fb1a1e69f7ee72ecdfc6e58863d53968bf20f149 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -7,7 +7,7 @@ GEM
     neat (1.6.0)
       bourbon (>= 3.1)
       sass (>= 3.3)
-    sass (3.3.5)
+    sass (3.4.21)
     thor (0.19.1)
 
 PLATFORMS
@@ -16,4 +16,3 @@ PLATFORMS
 DEPENDENCIES
   bourbon (~> 4.0.2)
   neat (~> 1.6.0)
-  sass (= 3.3.5)
diff --git a/circle.yml b/circle.yml
index c37428a7394c00ec18845d0dfd14567d3b612ea3..95549be641a11973554399b2a6b6a9e2f002a37d 100644
--- a/circle.yml
+++ b/circle.yml
@@ -29,6 +29,7 @@ dependencies:
     # Install a version which falls within that range.
     - pip install  --exists-action w pbr==0.9.0
     - pip install --exists-action w -r requirements/edx/base.txt
+    - pip install --exists-action w -r requirements/edx/paver.txt
     - if [ -e requirements/edx/post.txt ]; then pip install --exists-action w -r requirements/edx/post.txt ; fi
 
     - pip install coveralls==1.0
diff --git a/pavelib/acceptance_test.py b/pavelib/acceptance_test.py
index 373db696edc97c3d16e8d531df40444f2c9b31d4..254af313bdd66f386b5096bc7ce09655d7bb59b6 100644
--- a/pavelib/acceptance_test.py
+++ b/pavelib/acceptance_test.py
@@ -30,7 +30,7 @@ __test__ = False  # do not collect
 ])
 def test_acceptance(options):
     """
-    Run the acceptance tests for the either lms or cms
+    Run the acceptance tests for either lms or cms
     """
     opts = {
         'fasttest': getattr(options, 'fasttest', False),
diff --git a/pavelib/assets.py b/pavelib/assets.py
index e1d3cd15d7591173e575335ecc193c9cdcdc5080..d7c8c13c0da30b3aecf3886facb16bb13aeb006f 100644
--- a/pavelib/assets.py
+++ b/pavelib/assets.py
@@ -12,24 +12,28 @@ from paver import tasks
 from paver.easy import sh, path, task, cmdopts, needs, consume_args, call_task, no_help
 from watchdog.observers import Observer
 from watchdog.events import PatternMatchingEventHandler
-import sass
 
 from .utils.envs import Env
 from .utils.cmd import cmd, django_cmd
 
 # setup baseline paths
 
+ALL_SYSTEMS = ['lms', 'studio']
 COFFEE_DIRS = ['lms', 'cms', 'common']
 # A list of directories.  Each will be paired with a sibling /css directory.
-SASS_DIRS = [
+COMMON_SASS_DIRECTORIES = [
+    path("common/static/sass"),
+]
+LMS_SASS_DIRECTORIES = [
     path("lms/static/sass"),
     path("lms/static/themed_sass"),
-    path("cms/static/sass"),
-    path("common/static/sass"),
     path("lms/static/certificates/sass"),
 ]
+CMS_SASS_DIRECTORIES = [
+    path("cms/static/sass"),
+]
+THEME_SASS_DIRECTORIES = []
 SASS_LOAD_PATHS = ['common/static', 'common/static/sass']
-SASS_CACHE_PATH = '/tmp/sass-cache'
 
 
 def configure_paths():
@@ -44,7 +48,7 @@ def configure_paths():
         css_dir = theme_root / "static" / "css"
         if sass_dir.isdir():
             css_dir.mkdir_p()
-            SASS_DIRS.append(sass_dir)
+            THEME_SASS_DIRECTORIES.append(sass_dir)
 
     if edxapp_env.env_tokens.get("COMPREHENSIVE_THEME_DIR", ""):
         theme_dir = path(edxapp_env.env_tokens["COMPREHENSIVE_THEME_DIR"])
@@ -52,16 +56,39 @@ def configure_paths():
         lms_css = theme_dir / "lms" / "static" / "css"
         if lms_sass.isdir():
             lms_css.mkdir_p()
-            SASS_DIRS.append(lms_sass)
+            THEME_SASS_DIRECTORIES.append(lms_sass)
         cms_sass = theme_dir / "cms" / "static" / "sass"
         cms_css = theme_dir / "cms" / "static" / "css"
         if cms_sass.isdir():
             cms_css.mkdir_p()
-            SASS_DIRS.append(cms_sass)
+            THEME_SASS_DIRECTORIES.append(cms_sass)
 
 configure_paths()
 
 
+def applicable_sass_directories(systems=None):
+    """
+    Determine the applicable set of SASS directories to be
+    compiled for the specified list of systems.
+
+    Args:
+        systems: A list of systems (defaults to all)
+
+    Returns:
+        A list of SASS directories to be compiled.
+    """
+    if not systems:
+        systems = ALL_SYSTEMS
+    applicable_directories = []
+    applicable_directories.extend(COMMON_SASS_DIRECTORIES)
+    if "lms" in systems:
+        applicable_directories.extend(LMS_SASS_DIRECTORIES)
+    if "studio" in systems or "cms" in systems:
+        applicable_directories.extend(CMS_SASS_DIRECTORIES)
+    applicable_directories.extend(THEME_SASS_DIRECTORIES)
+    return applicable_directories
+
+
 class CoffeeScriptWatcher(PatternMatchingEventHandler):
     """
     Watches for coffeescript changes
@@ -99,7 +126,7 @@ class SassWatcher(PatternMatchingEventHandler):
         """
         register files with observer
         """
-        for dirname in SASS_LOAD_PATHS + SASS_DIRS:
+        for dirname in SASS_LOAD_PATHS + applicable_sass_directories():
             paths = []
             if '*' in dirname:
                 paths.extend(glob.glob(dirname))
@@ -185,6 +212,7 @@ def compile_coffeescript(*files):
 @task
 @no_help
 @cmdopts([
+    ('system=', 's', 'The system to compile sass for (defaults to all)'),
     ('debug', 'd', 'Debug mode'),
     ('force', '', 'Force full compilation'),
 ])
@@ -192,8 +220,18 @@ def compile_sass(options):
     """
     Compile Sass to CSS.
     """
-    debug = options.get('debug')
 
+    # Note: import sass only when it is needed and not at the top of the file.
+    # This allows other paver commands to operate even without libsass being
+    # installed. In particular, this allows the install_prereqs command to be
+    # used to install the dependency.
+    import sass
+
+    debug = options.get('debug')
+    force = options.get('force')
+    systems = getattr(options, 'system', ALL_SYSTEMS)
+    if isinstance(systems, basestring):
+        systems = systems.split(',')
     if debug:
         source_comments = True
         output_style = 'nested'
@@ -202,22 +240,39 @@ def compile_sass(options):
         output_style = 'compressed'
 
     timing_info = []
-
-    for sass_dir in SASS_DIRS:
+    system_sass_directories = applicable_sass_directories(systems)
+    all_sass_directories = applicable_sass_directories()
+    dry_run = tasks.environment.dry_run
+    for sass_dir in system_sass_directories:
         start = datetime.now()
         css_dir = sass_dir.parent / "css"
-        sass.compile(
-            dirname=(sass_dir, css_dir),
-            include_paths=SASS_LOAD_PATHS + SASS_DIRS,
-            source_comments=source_comments,
-            output_style=output_style,
-        )
-        duration = datetime.now() - start
-        timing_info.append((sass_dir, css_dir, duration))
+
+        if force:
+            if dry_run:
+                tasks.environment.info("rm -rf {css_dir}/*.css".format(
+                    css_dir=css_dir,
+                ))
+            else:
+                sh("rm -rf {css_dir}/*.css".format(css_dir=css_dir))
+
+        if dry_run:
+            tasks.environment.info("libsass {sass_dir}".format(
+                sass_dir=sass_dir,
+            ))
+        else:
+            sass.compile(
+                dirname=(sass_dir, css_dir),
+                include_paths=SASS_LOAD_PATHS + all_sass_directories,
+                source_comments=source_comments,
+                output_style=output_style,
+            )
+            duration = datetime.now() - start
+            timing_info.append((sass_dir, css_dir, duration))
 
     print("\t\tFinished compiling Sass:")
-    for sass_dir, css_dir, duration in timing_info:
-        print(">> {} -> {} in {}s".format(sass_dir, css_dir, duration))
+    if not dry_run:
+        for sass_dir, css_dir, duration in timing_info:
+            print(">> {} -> {} in {}s".format(sass_dir, css_dir, duration))
 
 
 def compile_templated_sass(systems, settings):
@@ -226,15 +281,15 @@ def compile_templated_sass(systems, settings):
     `systems` is a list of systems (e.g. 'lms' or 'studio' or both)
     `settings` is the Django settings module to use.
     """
-    for sys in systems:
-        if sys == "studio":
-            sys = "cms"
+    for system in systems:
+        if system == "studio":
+            system = "cms"
         sh(django_cmd(
-            sys, settings, 'preprocess_assets',
-            '{sys}/static/sass/*.scss'.format(sys=sys),
-            '{sys}/static/themed_sass'.format(sys=sys)
+            system, settings, 'preprocess_assets',
+            '{system}/static/sass/*.scss'.format(system=system),
+            '{system}/static/themed_sass'.format(system=system)
         ))
-        print("\t\tFinished preprocessing {} assets.".format(sys))
+        print("\t\tFinished preprocessing {} assets.".format(system))
 
 
 def process_xmodule_assets():
@@ -310,7 +365,7 @@ def update_assets(args):
     """
     parser = argparse.ArgumentParser(prog='paver update_assets')
     parser.add_argument(
-        'system', type=str, nargs='*', default=['lms', 'studio'],
+        'system', type=str, nargs='*', default=ALL_SYSTEMS,
         help="lms or studio",
     )
     parser.add_argument(
@@ -334,7 +389,7 @@ def update_assets(args):
     compile_templated_sass(args.system, args.settings)
     process_xmodule_assets()
     compile_coffeescript()
-    call_task('pavelib.assets.compile_sass', options={'debug': args.debug})
+    call_task('pavelib.assets.compile_sass', options={'system': args.system, 'debug': args.debug})
 
     if args.collect:
         collect_assets(args.system, args.settings)
diff --git a/pavelib/paver_tests/test_assets.py b/pavelib/paver_tests/test_assets.py
new file mode 100644
index 0000000000000000000000000000000000000000..b690b6d0fe85bd05710a803c75f6e2c93f4cf276
--- /dev/null
+++ b/pavelib/paver_tests/test_assets.py
@@ -0,0 +1,58 @@
+"""Unit tests for the Paver asset tasks."""
+
+import ddt
+from paver.easy import call_task
+
+from .utils import PaverTestCase
+
+
+@ddt.ddt
+class TestPaverAssetTasks(PaverTestCase):
+    """
+    Test the Paver asset tasks.
+    """
+    @ddt.data(
+        [""],
+        ["--force"],
+        ["--debug"],
+        ["--system=lms"],
+        ["--system=lms --force"],
+        ["--system=studio"],
+        ["--system=studio --force"],
+        ["--system=lms,studio"],
+        ["--system=lms,studio --force"],
+    )
+    @ddt.unpack
+    def test_compile_sass(self, options):
+        """
+        Test the "compile_sass" task.
+        """
+        parameters = options.split(" ")
+        system = []
+        if "--system=studio" not in parameters:
+            system += ["lms"]
+        if "--system=lms" not in parameters:
+            system += ["studio"]
+        debug = "--debug" in parameters
+        force = "--force" in parameters
+        self.reset_task_messages()
+        call_task('pavelib.assets.compile_sass', options={"system": system, "debug": debug, "force": force})
+        expected_messages = []
+        if force:
+            expected_messages.append("rm -rf common/static/css/*.css")
+        expected_messages.append("libsass common/static/sass")
+        if "lms" in system:
+            if force:
+                expected_messages.append("rm -rf lms/static/css/*.css")
+            expected_messages.append("libsass lms/static/sass")
+            if force:
+                expected_messages.append("rm -rf lms/static/css/*.css")
+            expected_messages.append("libsass lms/static/themed_sass")
+            if force:
+                expected_messages.append("rm -rf lms/static/certificates/css/*.css")
+            expected_messages.append("libsass lms/static/certificates/sass")
+        if "studio" in system:
+            if force:
+                expected_messages.append("rm -rf cms/static/css/*.css")
+            expected_messages.append("libsass cms/static/sass")
+        self.assertEquals(self.task_messages, expected_messages)
diff --git a/pavelib/paver_tests/test_servers.py b/pavelib/paver_tests/test_servers.py
index 9d75e57ce275f4389d189bf83cc817b8c3749961..d2169b7ac07cfdcb3f5ad106a6ff33959fa5fd99 100644
--- a/pavelib/paver_tests/test_servers.py
+++ b/pavelib/paver_tests/test_servers.py
@@ -11,21 +11,19 @@ EXPECTED_COFFEE_COMMAND = (
     "{platform_root}/cms {platform_root}/common -type f -name \"*.coffee\"`"
 )
 EXPECTED_SASS_COMMAND = (
-    "sass --update --cache-location /tmp/sass-cache --default-encoding utf-8 --style compressed"
-    " --quiet"
-    " --load-path ."
-    " --load-path common/static"
-    " --load-path common/static/sass"
-    " --load-path lms/static/sass"
-    " --load-path lms/static/themed_sass"
-    " --load-path cms/static/sass --load-path common/static/sass"
-    " --load-path lms/static/certificates/sass"
-    " lms/static/sass:lms/static/css"
-    " lms/static/themed_sass:lms/static/css"
-    " cms/static/sass:cms/static/css"
-    " common/static/sass:common/static/css"
-    " lms/static/certificates/sass:lms/static/certificates/css"
+    "libsass {sass_directory}"
 )
+EXPECTED_COMMON_SASS_DIRECTORIES = [
+    "common/static/sass",
+]
+EXPECTED_LMS_SASS_DIRECTORIES = [
+    "lms/static/sass",
+    "lms/static/themed_sass",
+    "lms/static/certificates/sass",
+]
+EXPECTED_CMS_SASS_DIRECTORIES = [
+    "cms/static/sass",
+]
 EXPECTED_PREPROCESS_ASSETS_COMMAND = (
     "python manage.py {system} --settings={asset_settings} preprocess_assets"
     " {system}/static/sass/*.scss {system}/static/themed_sass"
@@ -236,7 +234,7 @@ class TestPaverServerTasks(PaverTestCase):
             ))
             expected_messages.append("xmodule_assets common/static/xmodule")
             expected_messages.append(EXPECTED_COFFEE_COMMAND.format(platform_root=platform_root))
-            expected_messages.append(EXPECTED_SASS_COMMAND)
+            expected_messages.extend(self.expected_sass_commands(system=system))
         if expected_collect_static:
             expected_messages.append(EXPECTED_COLLECT_STATIC_COMMAND.format(
                 system=system, asset_settings=expected_asset_settings
@@ -278,7 +276,7 @@ class TestPaverServerTasks(PaverTestCase):
             ))
             expected_messages.append("xmodule_assets common/static/xmodule")
             expected_messages.append(EXPECTED_COFFEE_COMMAND.format(platform_root=platform_root))
-            expected_messages.append(EXPECTED_SASS_COMMAND)
+            expected_messages.extend(self.expected_sass_commands())
         if expected_collect_static:
             expected_messages.append(EXPECTED_COLLECT_STATIC_COMMAND.format(
                 system="lms", asset_settings=expected_asset_settings
@@ -302,3 +300,15 @@ class TestPaverServerTasks(PaverTestCase):
         )
         expected_messages.append(EXPECTED_CELERY_COMMAND.format(settings="dev_with_worker"))
         self.assertEquals(self.task_messages, expected_messages)
+
+    def expected_sass_commands(self, system=None):
+        """
+        Returns the expected SASS commands for the specified system.
+        """
+        expected_sass_directories = []
+        expected_sass_directories.extend(EXPECTED_COMMON_SASS_DIRECTORIES)
+        if system != 'cms':
+            expected_sass_directories.extend(EXPECTED_LMS_SASS_DIRECTORIES)
+        if system != 'lms':
+            expected_sass_directories.extend(EXPECTED_CMS_SASS_DIRECTORIES)
+        return [EXPECTED_SASS_COMMAND.format(sass_directory=directory) for directory in expected_sass_directories]
diff --git a/pavelib/prereqs.py b/pavelib/prereqs.py
index 0646ca307616ba60f41fbe003fbd72fae80d5d5b..1136865381cea9cb3d9e28a02d27f09112d103a4 100644
--- a/pavelib/prereqs.py
+++ b/pavelib/prereqs.py
@@ -24,6 +24,7 @@ PYTHON_REQ_FILES = [
     'requirements/edx/github.txt',
     'requirements/edx/local.txt',
     'requirements/edx/base.txt',
+    'requirements/edx/paver.txt',
     'requirements/edx/post.txt',
 ]