diff --git a/.gitignore b/.gitignore
index 0f3a23482a8e0c150022674d9f2e58575afdbb70..a6f2a7731fb1ed981f8d567b89748223e2e8dfe5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,4 +71,4 @@ target/
 #Data and output files
 .csv
 .png
-.SAV
\ No newline at end of file
+.SAV
diff --git a/.travis.yml b/.travis.yml
index 84d0c531e532c07f8ff5ec06baf9c366a238db8e..cde72427f5469ed95573eaf69558d1fc59f9c9a6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,10 @@ branches:
 only:
   - master
 
+os: 
+  - linux
+  - osx
+
 python:
   - "3.5"
 
@@ -35,6 +39,8 @@ install:
 
 script:
   - nosetests --with-coverage --cover-package=plio
+  # After test success, package and upload to Anaconda
+  - python build.py --project plio
 
 after_success:
   - coveralls
@@ -48,4 +54,4 @@ notifications:
       recipients:
         - jlaura@usgs.gov
       on_success: always
-      on_failure: always
\ No newline at end of file
+      on_failure: always
diff --git a/build.py b/build.py
new file mode 100644
index 0000000000000000000000000000000000000000..a10fb7253d84c00eca5249f05774273fde790f17
--- /dev/null
+++ b/build.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import sh
+
+from argparse import ArgumentParser
+
+
+# Initialize
+try:
+    token = os.environ['BINSTAR_KEYN']
+except KeyError:
+    sys.exit("Must set $BINSTAR_KEY")
+binstar = sh.Command('binstar').bake(t=token)
+conda = sh.Command('conda')
+
+
+def build_and_publish(path, channel):
+    binfile = conda.build("--output", path).strip()
+    print "Building..."
+    conda.build(path)
+    print "Upload to Anaconda.org..."
+    binstar.upload(binfile, force=True, channel=channel)
+
+
+def conda_paths(project_name):
+    conda_recipes_dir = os.path.join(project_name, 'conda')
+
+    if not os.path.isdir(conda_recipes_dir):
+        sys.exit('no such dir: {}'.format(conda_recipes_dir))
+
+    for name in sorted(os.listdir(conda_recipes_dir)):
+        yield os.path.join(conda_recipes_dir, name)
+
+
+def main():
+    parser = ArgumentParser()
+    parser.add_argument('-p', '--project', required=True)
+    parser.add_argument('-c', '--channel', required=False, default='main')
+    parser.add_argument('-s', '--site', required=False, default=None)
+    args = parser.parse_args()
+
+    for conda_path in conda_paths(args.project):
+        build_and_publish(conda_path, channel=args.channel)
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000000000000000000000000000000000000..027382180cf42707480b4cec272706a254d6d0ab
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,31 @@
+from setuptools import setup
+
+setup(
+    name = "plio",
+    version = "0.1.0",
+    author = "Jay Laura",
+    author_email = "jlaura@usgs.gov",
+    description = ("I/O API to support planetary data formats."),
+    license = "Public Domain",
+    keywords = "planetary io",
+    url = "http://packages.python.org/plio",
+    packages=['plio'],
+    install_requires=[
+        'gdal>=2',
+        'pvl',
+        'protobuf=3.0.0b2',
+        'h5py',
+        'pandas',
+        'sqlalchemy',
+        'pyyaml'],
+    classifiers=[
+        "Development Status :: 3 - Alpha",
+        "Topic :: Utilities",
+        "License :: Public Domain",
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
+    ],
+)