diff --git a/.pep8 b/.pep8
new file mode 100644
index 0000000000000000000000000000000000000000..5a67bb793e10696bc072aac9e7c63a7576a14cd4
--- /dev/null
+++ b/.pep8
@@ -0,0 +1,3 @@
+[pep8]
+ignore = E123,E124,E126,E127,E128
+exclude = nacl.py
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000000000000000000000000000000000000..19001fb0d074f8753521248feb88f33c46702dc3
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,71 @@
+[MASTER]
+# Pickle collected data for later comparisons.
+persistent=yes
+
+
+[MESSAGES CONTROL]
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once).
+#   W0511(fixme) - Do not need TODO's outputted typically
+#   I0011(locally-disabled) - If something is disabled it shouldn't generate more output
+#   C0111(missing-docstring) - Do not care if things are missing docstrings
+#   R0913(too-many-arguments) - Tool enforced limits like this are horrible
+#   R0903(too-few-public-methods) - Tool enforced limits like this are horrible
+#   R0904(too-many-public-methods) - Tool enforced limits like this are horrible
+#   R0911(too-many-return-statements) - Tool enforced limits like this are horrible
+#   R0912(too-many-branches) - Tool enforced limits like this are horrible
+#   R0914(too-many-locals) - Tool enforced limits like this are horrible
+#   R0201(no-self-use) - Does @staticmethod even really gain anything?
+#   W142(star-args) - Language features are not "magic"
+#   E0603(undefined-all-variable) - This appears to be broken?
+disable=W0511,I0011,C0111,R0913,R0903,R0904,R0911,R0912,R0914,R0201,W0142,E0603
+
+
+[REPORTS]
+
+output-format=colorized
+
+include-ids=yes
+
+symbols=yes
+
+reports=no
+
+comment=no
+
+
+[BASIC]
+# List of builtins function names that should not be used, separated by a comma
+bad-functions=map,filter,apply,input
+
+# Regular expression which should only match correct module level names
+const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))|(ffi|lib)$
+
+# Good variable names which should always be accepted, separated by a comma
+good-names=i,j,k,_,fp
+
+# Bad variable names which should always be refused, separated by a comma
+bad-names=
+
+[FORMAT]
+# Maximum number of characters on a single line.
+max-line-length=80
+
+
+[TYPECHECK]
+# List of members which are set dynamically and missed by pylint inference
+# system, and so shouldn't trigger E0201 when accessed. Python regular
+# expressions are accepted.
+generated-members=query,version,project
+
+# List of classes which members are set dynamically and missed by pylint
+# inference system, and so shouldn't trigger E1101 when accessed.
+ignored-classes=FFILibrary
+
+
+[VARIABLES]
+# A regular expression matching the beginning of the name of dummy variables
+# (i.e. not used).
+dummy-variables-rgx=_
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ffb8f5c0417d7543b2a5a573e67e658d67db1869
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,13 @@
+language: python
+python:
+  - "2.6"
+  - "2.7"
+  - "3.2"
+  - "3.3"
+  - "pypy"
+install:
+  - pip install -q "file://$PWD#egg=pynacl[tests]"
+script:
+  - pep8 nacl
+  - pylint --rcfile .pylintrc -r y nacl
+  - py.test
diff --git a/nacl/__about__.py b/nacl/__about__.py
index f7ca2ee91bbc5e8a3f29ecf1fddee94d5b8289c2..985972ac1b404d3dcfaec2253a6e50a2376e4402 100644
--- a/nacl/__about__.py
+++ b/nacl/__about__.py
@@ -1,3 +1,4 @@
+# pylint: disable=C0301
 from __future__ import absolute_import
 from __future__ import division
 from __future__ import unicode_literals
diff --git a/nacl/__init__.py b/nacl/__init__.py
index eca463aa3560c34d68d3e6ea6ee4edc24dc7a990..6642344d74f40139230c8d06ff6d66ad9421d04f 100644
--- a/nacl/__init__.py
+++ b/nacl/__init__.py
@@ -1 +1 @@
-from . import hash
+from . import hash  # pylint: disable=W0622
diff --git a/nacl/nacl.py b/nacl/nacl.py
index 3c43fcb6476c2f2c584489750d7422cb9a4fb83d..57ca20101fa8b4582b835ad5378fc94cd28ee3f1 100644
--- a/nacl/nacl.py
+++ b/nacl/nacl.py
@@ -11,6 +11,8 @@ __all__ = ["ffi", "lib"]
 
 ffi = FFI()
 ffi.cdef(
+    # pylint: disable=C0301
+
     # Low Level Hashing functions
     """
         static const int crypto_hash_BYTES;
diff --git a/setup.py b/setup.py
index 37ae4e337e837f88eacb0de6a88b4c41a5be3b97..638a8be5277c79c9941abc853a1c5b3b7295f7c9 100644
--- a/setup.py
+++ b/setup.py
@@ -32,6 +32,16 @@ setup(
     install_requires=[
         "cffi",
     ],
+    extras_require={
+        "tests": [
+            "pep8",
+            "pylint",
+            "pytest",
+        ],
+    },
+    tests_require=[
+        "pytest",
+    ],
 
     packages=[
         "nacl",