Try out pylint spelling.  Kinda noisy, but fixed some stuff.
diff --git a/CHANGES.txt b/CHANGES.txt
index 6d17267..6cd8e9e 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -327,8 +327,8 @@
   `issue 197`_, thanks Marius Gedminas.
 
 - When specifying a directory as the source= option, the directory itself no
-  longer needs to have a ``__init__.py`` file, though its subdirectories do, to
-  be considered as source files.
+  longer needs to have a ``__init__.py`` file, though its sub-directories do,
+  to be considered as source files.
 
 - Files encoded as UTF-8 with a BOM are now properly handled, fixing
   `issue 179`_.  Thanks, Pablo Carballo.
diff --git a/Makefile b/Makefile
index fdab74e..3958214 100644
--- a/Makefile
+++ b/Makefile
@@ -31,6 +31,9 @@
 	python -m tabnanny $(LINTABLE)
 	python igor.py check_eol
 
+spell:
+	-pylint --disable=all --enable=spelling $(LINTABLE)
+
 pep8:
 	pep8 --filename=*.py --ignore=E401,E301 --repeat coverage
 
diff --git a/coverage/__init__.py b/coverage/__init__.py
index 3a52c1d..41da609 100644
--- a/coverage/__init__.py
+++ b/coverage/__init__.py
@@ -18,7 +18,7 @@
 
 # Module-level functions.  The original API to this module was based on
 # functions defined directly in the module, with a singleton of the Coverage()
-# class.  That design hampered programmability, so the current api uses
+# class.  That design hampered programmability, so the current API uses
 # explicitly-created Coverage objects.  But for backward compatibility, here we
 # define the top-level functions to create the singleton when they are first
 # called.
diff --git a/coverage/backunittest.py b/coverage/backunittest.py
index 648e74e..95b6fcc 100644
--- a/coverage/backunittest.py
+++ b/coverage/backunittest.py
@@ -1,7 +1,7 @@
 """Implementations of unittest features from the future."""
 
 # Use unittest2 if it's available, otherwise unittest.  This gives us
-# backported features for 2.6.
+# back-ported features for 2.6.
 try:
     import unittest2 as unittest
 except ImportError:
@@ -9,7 +9,7 @@
 
 
 def unittest_has(method):
-    """Does `unitttest.TestCase` have `method` defined?"""
+    """Does `unittest.TestCase` have `method` defined?"""
     return hasattr(unittest.TestCase, method)
 
 
diff --git a/coverage/cmdline.py b/coverage/cmdline.py
index 1b4d322..7ad0ca1 100644
--- a/coverage/cmdline.py
+++ b/coverage/cmdline.py
@@ -512,7 +512,7 @@
     def args_ok(self, options, args):
         """Check for conflicts and problems in the options.
 
-        Returns True if everything is ok, or False if not.
+        Returns True if everything is OK, or False if not.
 
         """
         if options.action == "run" and not args:
diff --git a/coverage/config.py b/coverage/config.py
index 9bd5dd5..d15810e 100644
--- a/coverage/config.py
+++ b/coverage/config.py
@@ -5,7 +5,7 @@
 from coverage.misc import CoverageException
 
 
-# In py3, # ConfigParser was renamed to the more-standard configparser
+# In py3, ConfigParser was renamed to the more-standard configparser
 try:
     import configparser
 except ImportError:
diff --git a/coverage/control.py b/coverage/control.py
index 6aa06da..c59424d 100644
--- a/coverage/control.py
+++ b/coverage/control.py
@@ -315,7 +315,7 @@
         If loaded via runpy (aka -m), we can usually recover the "original" full
         dotted module name, otherwise, we resort to interpreting the filename to
         get the module's name.  In the case that the module name can't be
-        deteremined, None is returned.
+        determined, None is returned.
 
         """
         dunder_name = module_globals.get('__name__', None)
@@ -335,7 +335,7 @@
                 # Module loaded via: runpy -m
                 return fullname
 
-        # Script as first argument to Python CLI.
+        # Script as first argument to Python command line.
         inspectedname = inspect.getmodulename(filename)
         if inspectedname is not None:
             return inspectedname
@@ -695,7 +695,7 @@
 
                 if self.omit_match and self.omit_match.match(py_file):
                     # Turns out this file was omitted, so don't pull it back
-                    # in as unexecuted.
+                    # in as un-executed.
                     continue
 
                 self.data.touch_file(py_file)
@@ -943,7 +943,7 @@
 
 
 def process_startup():
-    """Call this at Python startup to perhaps measure coverage.
+    """Call this at Python start-up to perhaps measure coverage.
 
     If the environment variable COVERAGE_PROCESS_START is defined, coverage
     measurement is started.  The value of the variable is the config file
@@ -970,5 +970,5 @@
         cov._warn_unimported_source = False
 
 
-# A hack for debugging testing in subprocesses.
+# A hack for debugging testing in sub-processes.
 _TEST_NAME_FILE = "" #"/tmp/covtest.txt"
diff --git a/coverage/files.py b/coverage/files.py
index 7c82d5f..31fe61a 100644
--- a/coverage/files.py
+++ b/coverage/files.py
@@ -322,7 +322,7 @@
     To be importable, the files have to be in a directory with a __init__.py,
     except for `dirname` itself, which isn't required to have one.  The
     assumption is that `dirname` was specified directly, so the user knows
-    best, but subdirectories are checked for a __init__.py to be sure we only
+    best, but sub-directories are checked for a __init__.py to be sure we only
     find the importable files.
 
     """
diff --git a/coverage/html.py b/coverage/html.py
index 37d6228..a4b46a2 100644
--- a/coverage/html.py
+++ b/coverage/html.py
@@ -26,7 +26,7 @@
     is returned.
 
     Each directory in `STATIC_PATH` is searched as-is, and also, if `pkgdir`
-    is provided, at that subdirectory.
+    is provided, at that sub-directory.
 
     """
     for static_dir in STATIC_PATH:
@@ -289,6 +289,7 @@
     STATUS_FILE = "status.json"
     STATUS_FORMAT = 1
 
+    #                               pylint: disable=wrong-spelling-in-comment
     #  The data looks like:
     #
     #  {
diff --git a/coverage/parser.py b/coverage/parser.py
index 9041e34..ae36a73 100644
--- a/coverage/parser.py
+++ b/coverage/parser.py
@@ -237,7 +237,7 @@
         """Get information about the arcs available in the code.
 
         Returns a sorted list of line number pairs.  Line numbers have been
-        normalized to the first line of multiline statements.
+        normalized to the first line of multi-line statements.
 
         """
         all_arcs = []
diff --git a/coverage/phystokens.py b/coverage/phystokens.py
index 867388f..fe77c7d 100644
--- a/coverage/phystokens.py
+++ b/coverage/phystokens.py
@@ -42,7 +42,7 @@
                     inject_backslash = False
                 elif ttype == token.STRING:
                     if "\n" in ttext and ttext.split('\n', 1)[0][-1] == '\\':
-                        # It's a multiline string and the first line ends with
+                        # It's a multi-line string and the first line ends with
                         # a backslash, so we don't need to inject another.
                         inject_backslash = False
                 if inject_backslash:
@@ -136,10 +136,10 @@
         return orig_enc
 
     # From detect_encode():
-    # It detects the encoding from the presence of a utf-8 bom or an encoding
-    # cookie as specified in pep-0263.  If both a bom and a cookie are present,
+    # It detects the encoding from the presence of a UTF-8 BOM or an encoding
+    # cookie as specified in PEP-0263.  If both a BOM and a cookie are present,
     # but disagree, a SyntaxError will be raised.  If the encoding cookie is an
-    # invalid charset, raise a SyntaxError.  Note that if a utf-8 bom is found,
+    # invalid charset, raise a SyntaxError.  Note that if a UTF-8 BOM is found,
     # 'utf-8-sig' is returned.
 
     # If no encoding is specified, then the default will be returned.
@@ -169,14 +169,14 @@
         try:
             codec = codecs.lookup(encoding)
         except LookupError:
-            # This behaviour mimics the Python interpreter
+            # This behavior mimics the Python interpreter
             raise SyntaxError("unknown encoding: " + encoding)
 
         if bom_found:
             # codecs in 2.3 were raw tuples of functions, assume the best.
             codec_name = getattr(codec, 'name', encoding)
             if codec_name != 'utf-8':
-                # This behaviour mimics the Python interpreter
+                # This behavior mimics the Python interpreter
                 raise SyntaxError('encoding problem: utf-8')
             encoding += '-sig'
         return encoding
diff --git a/coverage/pytracer.py b/coverage/pytracer.py
index f3f490a..c2008d0 100644
--- a/coverage/pytracer.py
+++ b/coverage/pytracer.py
@@ -146,8 +146,8 @@
         self.stopped = True
         if self.threading and self.thread != self.threading.currentThread():
             # Called on a different thread than started us: we can't unhook
-            # ourseves, but we've set the flag that we should stop, so we won't
-            # do any more tracing.
+            # ourselves, but we've set the flag that we should stop, so we
+            # won't do any more tracing.
             return
 
         if self.warn:
diff --git a/coverage/templite.py b/coverage/templite.py
index 53824e0..5877c05 100644
--- a/coverage/templite.py
+++ b/coverage/templite.py
@@ -61,7 +61,7 @@
 
     Supported constructs are extended variable access::
 
-        {{var.modifer.modifier|filter|filter}}
+        {{var.modifier.modifier|filter|filter}}
 
     loops::
 
@@ -241,7 +241,7 @@
         return self._render_function(render_context, self._do_dots)
 
     def _do_dots(self, value, *dots):
-        """Evaluate dotted expressions at runtime."""
+        """Evaluate dotted expressions at run-time."""
         for dot in dots:
             try:
                 value = getattr(value, dot)
diff --git a/doc/changes.rst b/doc/changes.rst
index b9980af..a16c544 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -281,8 +281,8 @@
   `issue 197`_, thanks Marius Gedminas.
 
 - When specifying a directory as the source= option, the directory itself no
-  longer needs to have a ``__init__.py`` file, though its subdirectories do, to
-  be considered as source files.
+  longer needs to have a ``__init__.py`` file, though its sub-directories do,
+  to be considered as source files.
 
 - Files encoded as UTF-8 with a BOM are now properly handled, fixing
   `issue 179`_.  Thanks, Pablo Carballo.
@@ -701,7 +701,7 @@
 
 - The minimum supported Python version is 2.3.
 
-- When using the object api (that is, constructing a coverage() object), data
+- When using the object API (that is, constructing a coverage() object), data
   is no longer saved automatically on process exit.  You can re-enable it with
   the ``auto_data=True`` parameter on the coverage() constructor.
   The module-level interface still uses automatic saving.
diff --git a/doc/index.rst b/doc/index.rst
index ba83f2c..68780ea 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -139,7 +139,7 @@
 
 Bug reports are gladly accepted at the `Bitbucket issue tracker`_.
 Bitbucket also hosts the `code repository`_. There is a `mirrored repo`_ on
-Github.
+GitHub.
 
 .. _Bitbucket issue tracker: http://bitbucket.org/ned/coveragepy/issues
 .. _code repository: http://bitbucket.org/ned/coveragepy
diff --git a/doc/subprocess.rst b/doc/subprocess.rst
index a4e759d..40875f7 100644
--- a/doc/subprocess.rst
+++ b/doc/subprocess.rst
@@ -1,16 +1,16 @@
 .. _subprocess:
 
-======================
-Measuring subprocesses
-======================
+=======================
+Measuring sub-processes
+=======================
 
 :history: 20100224T201800, new for 3.3.
 :history: 20100725T211700, updated for 3.4.
 
 
-Complex test suites may spawn subprocesses to run tests, either to run them in
-parallel, or because subprocess behavior is an important part of the system
-under test. Measuring coverage in those subprocesses can be tricky because you
+Complex test suites may spawn sub-processes to run tests, either to run them in
+parallel, or because sub-process behavior is an important part of the system
+under test. Measuring coverage in those sub-processes can be tricky because you
 have to modify the code spawning the process to invoke coverage.py.
 
 There's an easier way to do it: coverage.py includes a function,
@@ -23,13 +23,13 @@
 multiple coverage.py runs will each write their data to a distinct file.
 
 
-Configuring Python for subprocess coverage
-------------------------------------------
+Configuring Python for sub-process coverage
+-------------------------------------------
 
-Measuring coverage in subprocesses is a little tricky.  When you spawn a
-subprocess, you are invoking Python to run your program.  Usually, to get
+Measuring coverage in sub-processes is a little tricky.  When you spawn a
+sub-process, you are invoking Python to run your program.  Usually, to get
 coverage measurement, you have to use coverage.py to run your program.  Your
-subprocess won't be using coverage.py, so we have to convince Python to use
+sub-process won't be using coverage.py, so we have to convince Python to use
 coverage even when not explicitly invokved.
 
 To do that, we'll configure Python to run a little coverage.py code when it
@@ -41,8 +41,8 @@
 invoke :func:`coverage.process_startup` when Python processes start.
 
 How you set ``COVERAGE_PROCESS_START`` depends on the details of how you create
-subprocesses.  As long as the environment variable is visible in your
-subprocess, it will work.
+sub-processes.  As long as the environment variable is visible in your
+sub-process, it will work.
 
 You can configure your Python installation to invoke the ``process_startup``
 function in two ways:
diff --git a/pylintrc b/pylintrc
index 2aa6f17..b923a0b 100644
--- a/pylintrc
+++ b/pylintrc
@@ -56,6 +56,7 @@
 
 # Disable the message(s) with the given id(s).
 disable= 
+    spelling,
 # Messages that are just silly:
 #   I0011:106: Locally disabling E1101
 #   W0122: 30:run_python_file: Use of the exec statement
@@ -327,3 +328,11 @@
 
 # Ignore docstrings when computing similarities.
 ignore-docstrings=yes
+
+#
+# SPELLING
+#
+
+spelling-dict=en_US
+# pylint doesn't strip the words, so they have to all be jammed on one line in order to be recognized... :(
+spelling-ignore-words=activestate,API,args,argv,bitbucket,BOM,boolean,BTW,builtin,builtins,bytecode,bytecodes,canonicalize,canonicalized,canonicalizes,codecs,config,configparser,configurability,configurability's,cov,coveragerc,covhtml,css,dict,dict's,dicts,dirname,django,docstring,docstrings,doctest,DOM,encodings,endfor,endif,eventlet,expr,filename,filenames,fname,fnmatch,fpath,fullcoverage,getattr,gevent,gevent's,GitHub,globals,greenlet,HTML,http,importlib,instancemethod,int,ints,iterable,iterables,jython,kwargs,matcher,matchers,merchantability,mixin,modulename,morf,morfs,multi,multi-line,namespace,namespaces,nano,nbsp,ned,nedbatchelder,nullary,num,OK,opcode,opcodes,optparse,os,outfile,parsable,parsers,pragma,pre,programmability,py,py's,pyc,pypy,pyw,rcfile,regex,regexes,renderer,settrace,sitecustomize,stackoverflow,stderr,stdlib,stdout,str,sys,templite,TODO,tokenization,tokenize,tokenized,tokenizer,tokenizes,tokenizing,traceback,tuple,tuples,txt,unittest,URL,UTF,utf,virtualenv,whitespace,wikipedia,wildcard,wildcards,XML,xrange
diff --git a/setup.py b/setup.py
index 53ed2b1..7a7e245 100644
--- a/setup.py
+++ b/setup.py
@@ -10,7 +10,7 @@
 
 Documentation is at `nedbatchelder.com <%s>`_.  Code repository and issue
 tracker are on `Bitbucket <http://bitbucket.org/ned/coveragepy>`_, with a
-mirrored repo on `Github <https://github.com/nedbat/coveragepy>`_.
+mirrored repo on `GitHub <https://github.com/nedbat/coveragepy>`_.
 
 New in 4.0 alpha: ``--concurrency``, dropped support for older Pythons,
 setup.cfg support.
diff --git a/tests/backtest.py b/tests/backtest.py
index 574e6ac..73b1067 100644
--- a/tests/backtest.py
+++ b/tests/backtest.py
@@ -10,7 +10,7 @@
 # This isn't really a backward compatibility thing, should be moved into a
 # helpers file or something.
 def run_command(cmd):
-    """Run a command in a subprocess.
+    """Run a command in a sub-process.
 
     Returns the exit status code and the combined stdout and stderr.
 
diff --git a/tests/coveragetest.py b/tests/coveragetest.py
index a680ed4..60ba505 100644
--- a/tests/coveragetest.py
+++ b/tests/coveragetest.py
@@ -274,7 +274,7 @@
         self.assertEqual(ret_actual, ret)
 
     def run_command(self, cmd):
-        """Run the command-line `cmd` in a subprocess, and print its output.
+        """Run the command-line `cmd` in a sub-process, and print its output.
 
         Use this when you need to test the process behavior of coverage.
 
@@ -283,7 +283,7 @@
         Returns the process' stdout text.
 
         """
-        # Running Python subprocesses can be tricky.  Use the real name of our
+        # Running Python sub-processes can be tricky.  Use the real name of our
         # own executable.  So "python foo.py" might get executed as
         # "python3.3 foo.py".  This is important because Python 3.x doesn't
         # install as "python", so you might get a Python 2 executable instead
@@ -295,7 +295,7 @@
         return output
 
     def run_command_status(self, cmd):
-        """Run the command-line `cmd` in a subprocess, and print its output.
+        """Run the command-line `cmd` in a sub-process, and print its output.
 
         Use this when you need to test the process behavior of coverage.
 
diff --git a/tests/test_api.py b/tests/test_api.py
index ca65d6d..d5591d8 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -1,4 +1,4 @@
-"""Tests for Coverage's api."""
+"""Tests for Coverage's API."""
 
 import fnmatch, os, re, sys, textwrap
 
@@ -495,7 +495,7 @@
 
 
 class XmlIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest):
-    """Tests of the xml include/omit functionality.
+    """Tests of the XML include/omit functionality.
 
     This also takes care of the HTML and annotate include/omit, by virtue
     of the structure of the code.
diff --git a/tests/test_config.py b/tests/test_config.py
index 34727ae..e042492 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -20,7 +20,7 @@
         self.assertEqual(cov.config.data_file, ".coverage")
 
     def test_arguments(self):
-        # Arguments to the constructor are applied to the configuation.
+        # Arguments to the constructor are applied to the configuration.
         cov = coverage.coverage(timid=True, data_file="fooey.dat")
         self.assertTrue(cov.config.timid)
         self.assertFalse(cov.config.branch)
@@ -129,7 +129,7 @@
             )
 
     def test_tweaks_after_constructor(self):
-        # Arguments to the constructor are applied to the configuation.
+        # Arguments to the constructor are applied to the configuration.
         cov = coverage.coverage(timid=True, data_file="fooey.dat")
         cov.config["run:timid"] = False
 
diff --git a/tests/test_farm.py b/tests/test_farm.py
index 661c67b..31bd4c6 100644
--- a/tests/test_farm.py
+++ b/tests/test_farm.py
@@ -1,4 +1,4 @@
-"""Run tests in the farm subdirectory.  Designed for nose."""
+"""Run tests in the farm sub-directory.  Designed for nose."""
 
 import difflib, filecmp, fnmatch, glob, os, re, shutil, sys
 from nose.plugins.skip import SkipTest
diff --git a/tests/test_files.py b/tests/test_files.py
index 6c5a332..00142ac 100644
--- a/tests/test_files.py
+++ b/tests/test_files.py
@@ -41,7 +41,7 @@
         # https://bitbucket.org/ned/coveragepy/issue/194
         # Build a path that has two pieces matching the absolute path prefix.
         # Technically, this test doesn't do that on Windows, but drive
-        # letters make that impractical to acheive.
+        # letters make that impractical to achieve.
         fl = FileLocator()
         d = abs_file(os.curdir)
         trick = os.path.splitdrive(d)[1].lstrip(os.path.sep)
diff --git a/tests/test_html.py b/tests/test_html.py
index 948a422..9448447 100644
--- a/tests/test_html.py
+++ b/tests/test_html.py
@@ -244,14 +244,14 @@
         self.make_file("innocuous.py", "<h1>This isn't python!</h1>")
         cov.html_report(ignore_errors=True)
         self.assert_exists("htmlcov/index.html")
-        # this would be better as a glob, if the html layout changes:
+        # This would be better as a glob, if the HTML layout changes:
         self.assert_doesnt_exist("htmlcov/innocuous.html")
 
     def test_dothtml_not_python(self):
         # We run a .html file, and when reporting, we can't parse it as
         # Python.  Since it wasn't .py, no error is reported.
 
-        # Run an "html" file
+        # Run an "HTML" file
         self.make_file("innocuous.html", "a = 3")
         self.run_command("coverage run innocuous.html")
         # Before reporting, change it to be an HTML file.
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 977378d..7b7d51d 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -34,11 +34,11 @@
     """Tests of misc.file_be_gone."""
 
     def test_remove_nonexistent_file(self):
-        # it's ok to try to remove a file that doesn't exist.
+        # It's OK to try to remove a file that doesn't exist.
         file_be_gone("not_here.txt")
 
     def test_remove_actual_file(self):
-        # it really does remove a file that does exist.
+        # It really does remove a file that does exist.
         self.make_file("here.txt", "We are here, we are here, we are here!")
         file_be_gone("here.txt")
         self.assert_doesnt_exist("here.txt")
diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py
index c528955..ccd5682 100644
--- a/tests/test_phystokens.py
+++ b/tests/test_phystokens.py
@@ -21,7 +21,7 @@
 
 
 class PhysTokensTest(CoverageTest):
-    """Tests for Coverage.py's improver tokenizer."""
+    """Tests for Coverage.py's improved tokenizer."""
 
     run_in_temp_dir = False
 
diff --git a/tests/test_process.py b/tests/test_process.py
index 7b416a0..1185c25 100644
--- a/tests/test_process.py
+++ b/tests/test_process.py
@@ -665,7 +665,7 @@
 
 
 class ProcessCoverageMixin(object):
-    """Set up a .pth file that causes all subprocesses to be coverage'd"""
+    """Set up a .pth file that causes all sub-processes to be coverage'd"""
     def setUp(self):
         super(ProcessCoverageMixin, self).setUp()
         # Find a place to put a .pth file.
@@ -691,12 +691,12 @@
 
 
 class ProcessStartupTest(ProcessCoverageMixin, CoverageTest):
-    """Test that we can measure coverage in subprocesses."""
+    """Test that we can measure coverage in sub-processes."""
 
     def test_subprocess_with_pth_files(self):           # pragma: not covered
         if METACOV:
             raise SkipTest(
-                "Can't test subprocess pth file suppport during metacoverage"
+                "Can't test sub-process pth file suppport during metacoverage"
                 )
 
         # Main will run sub.py
@@ -744,7 +744,7 @@
     ):                                                  # pragma: not covered
         if METACOV:
             raise SkipTest(
-                "Can't test subprocess pth file suppport during metacoverage"
+                "Can't test sub-process pth file suppport during metacoverage"
                 )
 
         def fullname(modname):
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 05db729..d714031 100644
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -120,10 +120,10 @@
     e2 = os.path.basename(e2)
 
     if e1 == "python" or e2 == "python" or e1 == e2:
-        # python and python2.3: ok
-        # python2.3 and python: ok
-        # python and python: ok
-        # python2.3 and python2.3: ok
+        # Python and Python2.3: OK
+        # Python2.3 and Python: OK
+        # Python and Python: OK
+        # Python2.3 and Python2.3: OK
         return True
 
     return False                                        # pragma: only failure