diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1bc87f19a75ebeec1b0f4efc381c15a59272730c..782494a5d52cc499d62054ea66255ed3c7df9dc0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -20,6 +20,14 @@ stages:
 before_script:
 - pip install -e .[dev]
 
+linting:
+  image: python:3.6
+  tags:
+  - passoft
+  stage: test
+  script:
+  - flake8 refscrub
+
 python3.6:
   image: python:3.6
   tags:
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 3f3c1fa5ce376afedaff562eda6794ec635cf85d..4934a6f12574c5efda7a094f46e96b6073a81ffb 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -45,7 +45,8 @@ articles, and such.
 Submit Feedback
 ~~~~~~~~~~~~~~~
 
-The best way to send feedback is to file an issue at https://git.passcal.nmt.edu/passoft/refscrub/issues.
+The best way to send feedback is to file an issue at
+https://git.passcal.nmt.edu/passoft/refscrub/issues.
 
 If you are proposing a feature:
 
@@ -59,31 +60,31 @@ Get Started!
 
 Ready to contribute? Here's how to set up `refscrub` for local development.
 
-1. Cone the `refscrub` repo::
+1. Clone the `refscrub` repo:
 
     $ git clone https://git.passcal.nmt.edu/passoft/refscrub.git
 
-3. Install your local copy::
+2. Install your local copy:
 
     $ pip install -e .[dev]
 
-4. Create a branch for local development::
+3. Create a branch for local development:
 
     $ git checkout -b name-of-your-bugfix-or-feature
 
    Now you can make your changes locally.
 
-5. When you're done making changes, check that your changes pass the
-   tests::
+4. When you're done making changes, check that your changes pass the
+   tests:
 
     $ python setup.py test
-6. Commit your changes and push your branch to GitHub::
+5. Commit your changes and push your branch to GitHub:
 
     $ git add .
     $ git commit -m "Your detailed description of your changes."
     $ git push origin name-of-your-bugfix-or-feature
 
-7. Submit a merge request through the Gitlab website.
+6. Submit a merge request through the Gitlab website.
 
 Pull Request Guidelines
 -----------------------
@@ -94,13 +95,13 @@ Before you submit a merge request, check that it meets these guidelines:
 2. If the merge request adds functionality, the docs should be updated. Put
    your new functionality into a function with a docstring, and add the
    feature to the list in README.rst.
-3. The pull request should work for Python 2.7
+3. The pull request should work for Python 3.[6,7,8]
 
 Tips
 ----
 
 To run a subset of tests::
-    $ python -m unittest tests.test_refscrub
+    $ python -m unittest
 
 Deploying
 ---------
@@ -111,4 +112,3 @@ Then run::
 
 $ git push
 $ git push --tags
-
diff --git a/HISTORY.rst b/HISTORY.rst
index e3a5348c48818e486a566df3f5c20c683861af2c..1f671faf243c045450c96d3156bb5e8633a8a033 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -22,3 +22,15 @@ History
 
 * Python 2.7 & 3.6 compatiblity.
 * Code cleanup to match PEP 8.
+
+2020.216 (2020-08-04)
+------------------
+* Updated to work with Python 3
+* Added unit tests to ensure basic functionalities of refscrub
+* Updated list of platform specific dependencies to be installed when
+  installing refscrub in dev mode (see setup.py)
+* Installed and tested refscrub against Python3.[6,7,8] using tox
+* Formatted Python code to conform to the PEP8 style guide
+* Created conda package for refscrub that can run on Python3.[6,7,8]
+* Updated .gitlab-ci.yml to run a linter and unit tests for Python3.[6,7,8]
+  in GitLab CI pipeline
diff --git a/MANIFEST.in b/MANIFEST.in
index 965b2dda7db7c49f68857dc3aea9af37e30a745e..2387d6e279b924229fa0c8c485eeeebf49784996 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -5,7 +5,5 @@ include LICENSE
 include README.rst
 
 recursive-include tests *
-recursive-exclude * __pycache__
-recursive-exclude * *.py[co]
 
-recursive-include docs *.rst conf.py Makefile make.bat *.jpg *.png *.gif
+recursive-include docs *.rst conf.py
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 58e1b94f564fcf4e40c50fbb79bc895531d11b5c..0000000000000000000000000000000000000000
--- a/Makefile
+++ /dev/null
@@ -1,89 +0,0 @@
-.PHONY: clean clean-test clean-pyc clean-build docs help
-.DEFAULT_GOAL := help
-
-define BROWSER_PYSCRIPT
-import os, webbrowser, sys
-
-try:
-	from urllib import pathname2url
-except:
-	from urllib.request import pathname2url
-
-webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
-endef
-export BROWSER_PYSCRIPT
-
-define PRINT_HELP_PYSCRIPT
-import re, sys
-
-for line in sys.stdin:
-	match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line)
-	if match:
-		target, help = match.groups()
-		print("%-20s %s" % (target, help))
-endef
-export PRINT_HELP_PYSCRIPT
-
-BROWSER := python -c "$$BROWSER_PYSCRIPT"
-
-help:
-	@python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST)
-
-clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts
-
-clean-build: ## remove build artifacts
-	rm -fr build/
-	rm -fr dist/
-	rm -fr .eggs/
-	find . -name '*.egg-info' -exec rm -fr {} +
-	find . -name '*.egg' -exec rm -f {} +
-
-clean-pyc: ## remove Python file artifacts
-	find . -name '*.pyc' -exec rm -f {} +
-	find . -name '*.pyo' -exec rm -f {} +
-	find . -name '*~' -exec rm -f {} +
-	find . -name '__pycache__' -exec rm -fr {} +
-
-clean-test: ## remove test and coverage artifacts
-	rm -fr .tox/
-	rm -f .coverage
-	rm -fr htmlcov/
-	rm -fr .pytest_cache
-
-lint: ## check style with flake8
-	flake8 refscrub tests
-
-test: ## run tests quickly with the default Python
-	python setup.py test
-
-
-test-all: ## run tests on every Python version with tox
-	tox
-
-coverage: ## check code coverage quickly with the default Python
-	coverage run --source refscrub setup.py test
-	coverage report -m
-	coverage html
-	$(BROWSER) htmlcov/index.html
-
-docs: ## generate Sphinx HTML documentation, including API docs
-	rm -f docs/refscrub.rst
-	rm -f docs/modules.rst
-	sphinx-apidoc -o docs/ refscrub
-	$(MAKE) -C docs clean
-	$(MAKE) -C docs html
-	$(BROWSER) docs/_build/html/index.html
-
-servedocs: docs ## compile the docs watching for changes
-	watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D .
-
-release: dist ## package and upload a release
-	twine upload dist/*
-
-dist: clean ## builds source and wheel package
-	python setup.py sdist
-	python setup.py bdist_wheel
-	ls -l dist
-
-install: clean ## install the package to the active Python's site-packages
-	python setup.py install
diff --git a/README.rst b/README.rst
index 198b6c62481dfb99f4c334e547613502f350a459..2348a6de6c15da8250ca8834f4772ab3d6e4cdcb 100644
--- a/README.rst
+++ b/README.rst
@@ -2,23 +2,8 @@
 refscrub
 ========
 
+* Description: Remove select packets from RT130 data
 
-Remove select packets from RT130 data
-
+* Usage: efscrub [options] infile1 [ infile2 ... infileN]
 
 * Free software: GNU General Public License v3 (GPLv3)
-
-
-
-Features
---------
-
-* TODO
-
-Credits
--------
-
-This package was created with Cookiecutter_ and the `passoft/cookiecutter`_ project template.
-
-.. _Cookiecutter: https://github.com/audreyr/cookiecutter
-.. _`passoft/cookiecutter`: https://git.passcal.nmt.edu/passoft/cookiecutter
diff --git a/refscrub/__init__.py b/refscrub/__init__.py
index 41aa9e9d143e7571a17e3ad6b5838e2a20f2049f..4ba932794d037a30903282c596d2812e73f8f36d 100644
--- a/refscrub/__init__.py
+++ b/refscrub/__init__.py
@@ -4,4 +4,4 @@
 
 __author__ = """IRIS PASSCAL"""
 __email__ = 'software-support@passcal.nmt.edu'
-__version__ = '2018.228'
+__version__ = '2020.216'
diff --git a/refscrub/refscrub.py b/refscrub/refscrub.py
index 9a1da488f3b5285957d2250bda78390e02a0786a..a05d4ea1d6271f76414943ba124c0f3d8cea9dc5 100644
--- a/refscrub/refscrub.py
+++ b/refscrub/refscrub.py
@@ -13,13 +13,22 @@ August 2018
 Updates to work on both Python 2 & 3.
 Code cleanup to match PEP 8.
 Cleanup global vars.
+
+Maeva Pourpoint
+August 2020
+Updates to work under Python 3.
+Unit tests to ensure basic functionality.
+Code cleanup to conform to the PEP8 style guide.
+Directory cleanup (remove unused files introduced by Cookiecutter).
+Packaged with conda.
 """
-import sys
+
 import argparse
 import struct
+import sys
 from os.path import basename, getsize, isfile
 
-PROG_VERSION = '2018.228'
+PROG_VERSION = '2020.216'
 VERBOSE = False
 EXTRACT = False
 SUMMARY_FILE = 'scrubsum.txt'
@@ -74,9 +83,11 @@ class SNseen(dict):
 
 class RTPacket:
     RTstruct = struct.Struct('2c1B1B2B6B2B2B')
-    # Define the packet types as byte literals, since that is what the above structure will cause the type field
-    # do be decoded as. Without this, they will not match below.
-    packet_types = (b'AD', b'CD', b'DS', b'DT', b'EH', b'ET', b'OM', b'SH', b'SC')
+    # Define the packet types as byte literals, since that is what the above
+    # structure will cause the type field do be decoded as. Without this, they
+    # will not match below.
+    packet_types = (b'AD', b'CD', b'DS', b'DT',
+                    b'EH', b'ET', b'OM', b'SH', b'SC')
     seen = SNseen()
     goodpkts = 0
     IOErrorCount = 0
@@ -111,11 +122,13 @@ class RTPacket:
             print(e)
 
     def settimestring(self):
-        self.timestring = "%(year)0.2d:%(day)0.3d:%(hour)0.2d:%(min)0.2d:%(sec)0.2d.%(millisec)0.3d" % self.__dict__
+        self.timestring = ("%(year)0.2d:%(day)0.3d:%(hour)0.2d:%(min)0.2d:"
+                           "%(sec)0.2d.%(millisec)0.3d" % self.__dict__)
 
     def isvalid(self):
         """
-        Returns True if a valid reftek packet (headers parse well and are valid)
+        Returns True if a valid reftek packet (headers parse well and are
+        valid)
         Also populates the objects attributes SN, time, etc.
         """
 
@@ -128,11 +141,12 @@ class RTPacket:
             self.expnum = int("%0.2X" % tup[2])
             self.year = int("%0.2X" % tup[3])
             self.sn = "%0.2X%0.2X" % (tup[4], tup[5])
-            assert '9001' <= self.sn, "BAD SN"
+            assert self.sn >= '9001', "BAD SN"
             assert self.sn <= 'FFFF', "BAD SN"
             time = "%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X" % tup[6:12]
             self.day, self.hour, self.min, self.sec, self.millisec = \
-                int(time[:3]), int(time[3:5]), int(time[5:7]), int(time[7:9]), int(time[9:])
+                int(time[:3]), int(time[3:5]), int(
+                    time[5:7]), int(time[7:9]), int(time[9:])
             assert self.day <= 366, "BAD TIME"
             assert self.hour <= 24, "BAD TIME"
             assert self.min <= 60, "BAD TIME"
@@ -199,8 +213,9 @@ def readfile(infile):
             infile.seek(-1023, 1)
 
     print(summary(infile))
-    # commented out as when run with many files as input like a cf dir the closed fh's need to be written to and isn't
-    # smart enough to be opened RTPacket.seen.close_fhs()
+    # commented out as when run with many files as input like a cf dir the
+    # closed fh's need to be written to and isn't smart enough to be opened
+    # RTPacket.seen.close_fhs()
 
 
 def summary(infile):
@@ -208,7 +223,8 @@ def summary(infile):
     offstring = "%6s: %12d\n"
     s = offstring % ("OFFSET", infile.tell())
     s += offstring % ("OF", FILESIZE)
-    s += "Good packets: %d = %8.2fMB\n" % (RTPacket.goodpkts, RTPacket.goodpkts / 1024.0)
+    s += "Good packets: %d = %8.2fMB\n" % (
+        RTPacket.goodpkts, RTPacket.goodpkts / 1024.0)
     s += "IOErrors: %d\n" % RTPacket.IOErrorCount
     s += str(RTPacket.seen) + '\n'
     return s
@@ -259,13 +275,13 @@ def main():
             PREFIX = basename(infilename)
         print("Using prefix %s" % PREFIX)
         FILESIZE = getsize(infilename)
-        # Must open the file in binary mode or else we will have unicode issues when reading.
+        # Must open the file in binary mode or else we will have unicode issues
+        # when reading.
         with open(infilename, "rb") as infile:
             readfile(infile)
             if args.SUMMARY:
                 summaryfh.write(infilename + ', ' + PREFIX + '\n')
                 summaryfh.write(summary(infile))
-
         print("----------------------------------------")
     if isfile(SUMMARY_FILE):
         summaryfh.close()
diff --git a/setup.cfg b/setup.cfg
index 371beb7b759af77d8f94aa900d751bf79f767bd9..3e16c9aa4de92883ce48eebabea3688a4ead6f10 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,22 +1,5 @@
-[bumpversion]
-current_version = 2018.228
-commit = True
-tag = True
-
-[bumpversion:file:setup.py]
-search = version='{current_version}'
-replace = version='{new_version}'
-
-[bumpversion:file:refscrub/__init__.py]
-search = __version__ = '{current_version}'
-replace = __version__ = '{new_version}'
-
-[bdist_wheel]
-universal = 1
-
 [flake8]
 exclude = docs
 
 [aliases]
 # Define setup.py command aliases here
-
diff --git a/setup.py b/setup.py
index 1dbc630f0fd2fbd36748db864703f0472bac75f1..6a9b920ea0786ca570af145969ce23eb1bc6ecd2 100644
--- a/setup.py
+++ b/setup.py
@@ -31,18 +31,11 @@ setup(
         ],
     },
     install_requires=[],
-    setup_requires = [],
+    setup_requires=[],
     extras_require={
         'dev': [
-            'pip',
-            'bumpversion',
-            'wheel',
-            'watchdog',
             'flake8',
             'tox',
-            'coverage',
-            'Sphinx',
-            'twine',
         ]
     },
     license="GNU General Public License v3",
@@ -51,8 +44,7 @@ setup(
     keywords='refscrub',
     name='refscrub',
     packages=find_packages(include=['refscrub']),
-    test_suite='tests',
     url='https://git.passcal.nmt.edu/passoft/refscrub',
-    version='2018.228',
+    version='2020.216',
     zip_safe=False,
 )
diff --git a/tox.ini b/tox.ini
index bf6c0725b91a09d47ebc02bcfec374415d4ecfc9..90a1bcaedb744359310e321f0e074a66af3055de 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,10 @@
 [tox]
-envlist = py36, py37, py38
+envlist = py36, py37, py38, flake8
+
+[testenv:flake8]
+basepython = python
+deps = flake8
+commands = flake8 refscrub
 
 [testenv]
 commands = python -m unittest